dsh-team 0.2.6 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"client.ts","names":[],"sources":["../src/contract.d.ts","../src/client/TeamStage.d.ts","../src/client/locales.d.ts","../src/client/index.d.ts"],"sourcesContent":["/**\n * The team vocabulary shared by the host half and the browser half: the\n * durable projection value, the mailbox message source, and the relationship\n * model. Types only — the browser bundle imports this module type-only, so it\n * must never grow a runtime import of a host package.\n *\n * @module dsh-team/contract\n */\n/** The two relationship levels between the leader and a teammate. */\nexport type TeamRelation = 'managed' | 'peer';\n/** Lifecycle of one shared task. */\nexport type TeamTaskStatus = 'pending' | 'active' | 'done';\n/** What kind of traffic one mailbox row records. */\nexport type TeamMessageKind = \n/** Content one member addressed to another through `team_send`. */\n'message'\n/** A teammate's own result, delivered through the harness `report` tool. */\n | 'report'\n/** The runtime's account of a teammate's activation ending. */\n | 'settled';\n/** One teammate as the leader's log records it. */\nexport interface TeamMemberView {\n /** The teammate's session id; the address every team tool takes. */\n readonly memberId: string;\n readonly name: string;\n readonly role?: string;\n readonly relation: TeamRelation;\n /** Model route recorded at spawn, when the leader overrode its own. */\n readonly model?: string;\n /** Provider-owned reasoning effort recorded at spawn, when one was requested. */\n readonly effort?: string;\n /** Epoch ms of the spawn that added this member. */\n readonly joinedAt: number;\n}\n/** One shared task. */\nexport interface TeamTaskView {\n readonly taskId: string;\n readonly title: string;\n /** Assigned teammate; absent means unassigned (leader-held). */\n readonly assigneeId?: string;\n readonly status: TeamTaskStatus;\n /** Closing note recorded by whoever moved the task to `done`. */\n readonly note?: string;\n}\n/**\n * One mailbox row. `from`/`to` absent means the leader — the projection is\n * served per session, so the owning session needs no id of its own.\n */\nexport interface TeamMessageView {\n readonly messageId: string;\n readonly from?: string;\n readonly to?: string;\n readonly kind: TeamMessageKind;\n readonly text: string;\n readonly time: number;\n /**\n * Depth of this delivery in its conversation chain: 0 is a message the\n * leader started, and every teammate-to-teammate relay adds one. A row\n * without it was written before the plugin recorded chains.\n */\n readonly hop?: number;\n}\n/**\n * One entry of the team's shared workspace, as the leader's log last recorded\n * it. Only the shared area is ever projected: a member's private pad stays\n * private, including from this panel.\n */\nexport interface TeamBoardEntryView {\n readonly key: string;\n /** Session id of the member that wrote it last. */\n readonly authorId: string;\n readonly authorName: string;\n readonly updatedAt: number;\n /** First non-empty line, bounded — the projection never carries note bodies. */\n readonly preview: string;\n}\n/** The durable team state folded from one leader session's log. */\nexport interface TeamView {\n /** True once a spawn settled and the team was not ended afterwards. */\n readonly active: boolean;\n readonly members: readonly TeamMemberView[];\n readonly tasks: readonly TeamTaskView[];\n /** Bounded newest-last mailbox feed of leader-visible traffic. */\n readonly messages: readonly TeamMessageView[];\n /**\n * The shared workspace as of the last time the leader read or wrote it.\n * Teammates write straight to the durable workspace, which no session log\n * records, so this index is a snapshot rather than a live view.\n */\n readonly board: readonly TeamBoardEntryView[];\n /** When that snapshot was taken; absent while the leader has never looked. */\n readonly boardAt?: number;\n}\n/** The empty value every session without a team folds to. */\nexport declare const EMPTY_TEAM_VIEW: TeamView;\n/**\n * One delivery's place in a conversation chain. A chain begins whenever the\n * leader addresses a teammate and grows by one hop with every relay a teammate\n * makes off the message it is working from; escalation to the leader always\n * ends it. The pair is what bounds a peer conversation mechanically instead of\n * by prompt — see `src/service.ts`.\n */\nexport interface TeamChain {\n /** Identity of the conversation this delivery belongs to (per leader, per process). */\n readonly chainId: string;\n /** Relays between the chain's first delivery and this one. */\n readonly hop: number;\n}\n/**\n * Durable attribution for one team mailbox delivery, carried by the recipient's\n * own `user/message` event so the sender survives persistence on both sides.\n */\nexport interface TeamMessageSource extends TeamChain {\n readonly kind: 'team-message';\n /** A message another agent addressed to this one (`relay` context form). */\n readonly form: 'relay';\n /** Session id of the sending member, or of the leader. */\n readonly senderSessionId: string;\n /** Display name of the sender at delivery time. */\n readonly senderName: string;\n}\n/** The projection key this plugin owns. */\nexport declare const TEAM_PROJECTION_KEY = \"team\";\n","import type { PropsLocale, PropsRuntime, SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots';\nimport type { TeamBoardEntryView, TeamMemberView, TeamMessageView, TeamTaskView } from '../contract.ts';\n/** What the plugin's session follower publishes to this entry. */\nexport interface TeamPanelState {\n /** The session whose log owns the team; absent while no team is in view. */\n readonly leaderId?: string;\n /** The session currently open, so the stage can mark the one you are reading. */\n readonly currentId?: string;\n readonly members: readonly TeamMemberView[];\n readonly tasks: readonly TeamTaskView[];\n readonly messages: readonly TeamMessageView[];\n /** The shared workspace as the leader's log last recorded it. */\n readonly board: readonly TeamBoardEntryView[];\n /** When that snapshot was taken; absent while the leader has never looked. */\n readonly boardAt?: number;\n}\n/** Navigation and chrome the plugin body owns (it holds the client services). */\nexport interface TeamInjected {\n /** Open one teammate's transcript through its durable parent address. */\n readonly openMember: (leaderId: string, memberId: string) => void;\n /** Return to the leader's own conversation. */\n readonly openLeader: (leaderId: string) => void;\n /**\n * Take the composer seat for as long as the room is on screen; the returned\n * disposer hands it back. The room is a picture, not a place you type into,\n * and the tab is worth more than the strip of window the input card takes.\n */\n readonly holdComposer?: () => () => void;\n}\n/** Complete view-tab props: the root kit, the locale, and the inject face. */\nexport type TeamStageProps = PropsRuntime<'conversation.view'> & PropsLocale<'team'> & TeamInjected & {\n readonly useTeam: SnapshotSelectorHook<TeamPanelState>;\n};\n/**\n * The team stage. Rendered as one conversation view tab, so it exists only\n * while the surrounding session has a team — an ordinary conversation never\n * grows a tab it cannot fill.\n */\nexport declare function TeamStage(props: TeamStageProps): import(\"react\").JSX.Element;\n","/** Locale copy for the agent-team stage view. Product copy is Chinese. */\nexport declare const NS = \"team\";\nexport declare const zh: {\n readonly 'view.title': \"Agent 团队\";\n readonly 'stage.title': \"团队协作室\";\n readonly 'stage.room': \"协作室\";\n readonly 'stage.feed': \"消息流\";\n readonly 'stage.board': \"任务板\";\n readonly 'stage.workspace': \"共享工作区\";\n readonly 'stage.members': \"{count} 名成员\";\n readonly 'stage.running': \"{count} 名工作中\";\n readonly 'stage.idle': \"全部空闲\";\n readonly 'stage.tasks': \"{open}/{total} 项任务\";\n readonly 'stage.noTeam': \"这个会话还没有组建团队\";\n readonly 'stage.noTeamHint': \"让主会话调用 team_spawn 派生第一名队友。\";\n readonly 'stage.noMessages': \"还没有消息往来\";\n readonly 'stage.noTasks': \"还没有任务\";\n readonly 'stage.noNotes': \"共享工作区还是空的\";\n readonly 'stage.noNotesHint': \"成员用 team_note 把结论写在这里,不必互相发消息。\";\n readonly 'stage.boardAt': \"{time} 的快照\";\n readonly 'stage.boardStale': \"队友的写入直接进持久工作区,不经过主会话的日志——这里是主会话最后一次读写时的样子\";\n readonly 'stage.peerRing': \"同级成员可以直接走过去找对方;受管成员只找主会话\";\n readonly 'stage.roomHint': \"每个成员都有自己的工位;要说话就走过去说\";\n readonly 'stage.dock': \"协作面板\";\n readonly 'drawer.close': \"收起面板\";\n readonly 'feed.crew': \"成员状态\";\n readonly 'feed.log': \"往来记录\";\n readonly 'feed.open': \"在手 {count}\";\n readonly 'feed.quiet': \"还没有往来\";\n readonly 'screen.working': \"工作中…\";\n readonly 'member.leader': \"主会话\";\n readonly 'member.open': \"打开 {name} 的会话\";\n readonly 'member.openLeader': \"回到主会话\";\n readonly 'member.here': \"你正在看这个会话\";\n readonly 'relation.managed': \"受管\";\n readonly 'relation.peer': \"同级\";\n readonly 'status.running': \"工作中\";\n readonly 'status.idle': \"空闲\";\n readonly 'task.pending': \"待办\";\n readonly 'task.active': \"进行中\";\n readonly 'task.done': \"已完成\";\n readonly 'task.unassigned': \"未指派\";\n readonly 'message.report': \"汇报\";\n readonly 'message.settled': \"已收工\";\n readonly 'message.hop': \"第 {hop} 跳\";\n readonly 'message.hopHint': \"这条消息在一次队友间对话里的转发深度;深度用完只能回到主会话\";\n};\n/** The namespace's dictionary key union (literal keys, locale-typed seats). */\nexport type TeamKey = keyof typeof zh;\nexport declare const en: Record<TeamKey, string>;\n","/**\n * Browser half of dsh-team: follow the current session's `team` projection and\n * contribute the team stage as one conversation view tab.\n *\n * There is no client-side fold. The host computes the team value once and the\n * framework pushes it here (history tail baseline + `session/projection`\n * frames), so this module only tracks WHICH session's value is on screen — and\n * whether that session has a team at all, because the tab exists exactly while\n * it does: an ordinary conversation never grows a view it cannot fill.\n */\nimport type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';\nimport { type TeamPanelState } from './TeamStage.tsx';\nimport { type TeamKey } from './locales.ts';\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n /** Agent-team stage copy. */\n team: TeamKey;\n }\n}\n/** Required services: the slot registry, the session domain, and locale. */\nexport declare const inject: string[];\n/**\n * Register the locale dictionary and the view tab, and keep the stage store\n * pointed at the right session.\n * @param ctx - client root context.\n */\nexport declare function apply(ctx: ClientContext): void;\nexport type { TeamPanelState };\n"],"mappings":";;;;;;AAAA,IAAW,CAAC,gBAAgB;CAAC;OAAU,CAAC;CAAG,CAAC;AAAC;AAC7C,IAAW,CAAC,kBAAkB;CAAC;OAAU,CAAC;CAAG,CAAC;AAAC;AAC/C,IAAW,CAAC,mBAAmB;CAAC;OAAU,CAAC;CAAG,CAAC;AAAC;AAChD,IAAW,CAAC,kBAAkB;CAAC;OAAU,CAAC,YAAY;CAAG;EAAC;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;CAAE;AAAC;AACzF,IAAW,CAAC,gBAAgB;CAAC;OAAU,CAAC,cAAc;CAAG;EAAC;EAAI;EAAI;EAAI;EAAI;EAAI;CAAE;AAAC;AACjF,IAAW,CAAC,mBAAmB;CAAC;OAAU,CAAC,eAAe;CAAG;EAAC;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;CAAE;AAAC;AAC7F,IAAW,CAAC,sBAAsB;CAAC;OAAU,CAAC;CAAG;EAAC;EAAI;EAAI;EAAI;EAAI;CAAE;AAAC;;;;ACJrE,IAAW,CAAC,kBAAkB;CAAC;OAAS;EAAC;EAAgB;EAAc;EAAiB;CAAkB;CAAG;EAAC;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;CAAE;AAAC;;;;ACDzJ,IAAW,CAAC,MAAM;CAAC;OAAS,CAAC;CAAG;EAAC;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;CAAE;AAAC;AAC5M,IAAW,CAAC,WAAW;CAAC;OAAS,CAAC,EAAE;CAAG,CAAC,EAAE;AAAC;;;;ACC3C,IAAI,CAAC,MAAM;CAAC;OAAS,CAAC,OAAO;CAAG;EAAC;EAAI;EAAI;CAAE;CAAG,WAAW,EAAE;AAAC;AAC5D,IAAW,CAAC,UAAU;CAAC;OAAS,CAAC;CAAG,CAAC;AAAC;AACtC,IAAW,CAAC,SAAS;CAAC;OAAS,CAAC,aAAa;CAAG,CAAC,IAAI,EAAE;AAAC"}
1
+ {"version":3,"file":"client.ts","names":["ClientContext"],"sources":["../src/contract.d.ts","../src/client/TeamStage.d.ts","../src/client/locales.d.ts","../src/client/index.d.ts"],"sourcesContent":["/**\n * The team vocabulary shared by the host half and the browser half: the\n * durable projection value, the mailbox message source, and the relationship\n * model. Types only — the browser bundle imports this module type-only, so it\n * must never grow a runtime import of a host package.\n *\n * @module dsh-team/contract\n */\n/** The two relationship levels between the leader and a teammate. */\nexport type TeamRelation = 'managed' | 'peer';\n/** Lifecycle of one shared task. */\nexport type TeamTaskStatus = 'pending' | 'active' | 'done';\n/** What kind of traffic one mailbox row records. */\nexport type TeamMessageKind = \n/** Content one member addressed to another through `team_send`. */\n'message'\n/** A teammate's own result, delivered through the continuation settlement message. */\n | 'report'\n/** The runtime's account of a teammate's activation ending. */\n | 'settled';\n/** One teammate as the leader's log records it. */\nexport interface TeamMemberView {\n /** The teammate's session id; the address every team tool takes. */\n readonly memberId: string;\n readonly name: string;\n readonly role?: string;\n readonly relation: TeamRelation;\n /** Model route recorded at spawn, when the leader overrode its own. */\n readonly model?: string;\n /** Provider-owned reasoning effort recorded at spawn, when one was requested. */\n readonly effort?: string;\n /** Epoch ms of the spawn that added this member. */\n readonly joinedAt: number;\n}\n/** One shared task. */\nexport interface TeamTaskView {\n readonly taskId: string;\n readonly title: string;\n /** Assigned teammate; absent means unassigned (leader-held). */\n readonly assigneeId?: string;\n readonly status: TeamTaskStatus;\n /** Closing note recorded by whoever moved the task to `done`. */\n readonly note?: string;\n}\n/**\n * One mailbox row. `from`/`to` absent means the leader — the projection is\n * served per session, so the owning session needs no id of its own.\n */\nexport interface TeamMessageView {\n readonly messageId: string;\n readonly from?: string;\n readonly to?: string;\n readonly kind: TeamMessageKind;\n readonly text: string;\n readonly time: number;\n /**\n * Depth of this delivery in its conversation chain: 0 is a message the\n * leader started, and every teammate-to-teammate relay adds one. A row\n * without it was written before the plugin recorded chains.\n */\n readonly hop?: number;\n}\n/**\n * One entry of the team's shared workspace, as the leader's log last recorded\n * it. Only the shared area is ever projected: a member's private pad stays\n * private, including from this panel.\n */\nexport interface TeamBoardEntryView {\n readonly key: string;\n /** Session id of the member that wrote it last. */\n readonly authorId: string;\n readonly authorName: string;\n readonly updatedAt: number;\n /** First non-empty line, bounded — the projection never carries note bodies. */\n readonly preview: string;\n}\n/** The durable team state folded from one leader session's log. */\nexport interface TeamView {\n /** True once a spawn settled and the team was not ended afterwards. */\n readonly active: boolean;\n readonly members: readonly TeamMemberView[];\n readonly tasks: readonly TeamTaskView[];\n /** Bounded newest-last mailbox feed of leader-visible traffic. */\n readonly messages: readonly TeamMessageView[];\n /**\n * The shared workspace as of the last time the leader read or wrote it.\n * Teammates write straight to the durable workspace, which no session log\n * records, so this index is a snapshot rather than a live view.\n */\n readonly board: readonly TeamBoardEntryView[];\n /** When that snapshot was taken; absent while the leader has never looked. */\n readonly boardAt?: number;\n}\n/** The empty value every session without a team folds to. */\nexport declare const EMPTY_TEAM_VIEW: TeamView;\n/**\n * One delivery's place in a conversation chain. A chain begins whenever the\n * leader addresses a teammate and grows by one hop with every relay a teammate\n * makes off the message it is working from; escalation to the leader always\n * ends it. The pair is what bounds a peer conversation mechanically instead of\n * by prompt — see `src/service.ts`.\n */\nexport interface TeamChain {\n /** Identity of the conversation this delivery belongs to (per leader, per process). */\n readonly chainId: string;\n /** Relays between the chain's first delivery and this one. */\n readonly hop: number;\n}\n/**\n * Durable attribution for one team mailbox delivery, carried by the recipient's\n * own `user/message` event so the sender survives persistence on both sides.\n */\nexport interface TeamMessageSource extends TeamChain {\n readonly kind: 'team-message';\n /** A message another agent addressed to this one (`relay` context form). */\n readonly form: 'relay';\n /** Session id of the sending member, or of the leader. */\n readonly senderSessionId: string;\n /** Display name of the sender at delivery time. */\n readonly senderName: string;\n}\n/** The projection key this plugin owns. */\nexport declare const TEAM_PROJECTION_KEY = \"team\";\n","import type { PropsLocale, PropsRuntime, SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots';\nimport type { TeamBoardEntryView, TeamMemberView, TeamMessageView, TeamTaskView } from '../contract.ts';\n/** The host’s projected team state; the client does not fold session events. */\nexport interface TeamPanelState {\n readonly leaderId?: string;\n readonly currentId?: string;\n readonly members: readonly TeamMemberView[];\n readonly tasks: readonly TeamTaskView[];\n readonly messages: readonly TeamMessageView[];\n readonly board: readonly TeamBoardEntryView[];\n /** Time of the leader’s last workspace snapshot. */\n readonly boardAt?: number;\n}\nexport interface TeamInjected {\n readonly openMember: (leaderId: string, memberId: string) => void;\n readonly openLeader: (leaderId: string) => void;\n /** Returns a disposer that restores the composer when this view unmounts. */\n readonly holdComposer?: () => () => void;\n}\nexport type TeamStageProps = PropsRuntime<'conversation.view'> & PropsLocale<'team'> & TeamInjected & {\n readonly useTeam: SnapshotSelectorHook<TeamPanelState>;\n};\nexport declare function TeamStage(props: TeamStageProps): import(\"react\").JSX.Element;\n","/** Locale copy for the agent-team stage view. Product copy is Chinese. */\nexport declare const NS = \"team\";\nexport declare const zh: {\n readonly 'view.title': \"Agent 团队\";\n readonly 'stage.title': \"团队协作室\";\n readonly 'stage.eyebrow': \"共享空间\";\n readonly 'stage.sceneHint': \"点击成员,查看会话\";\n readonly 'stage.rosterView': \"成员视图\";\n readonly 'stage.room': \"协作室\";\n readonly 'stage.feed': \"消息流\";\n readonly 'stage.board': \"任务板\";\n readonly 'stage.workspace': \"共享工作区\";\n readonly 'stage.members': \"{count} 名成员\";\n readonly 'stage.running': \"{count} 名工作中\";\n readonly 'stage.idle': \"全部空闲\";\n readonly 'stage.tasks': \"{open}/{total} 项任务\";\n readonly 'stage.noTeam': \"这个会话还没有组建团队\";\n readonly 'stage.noTeamHint': \"让主会话调用 team_spawn 派生第一名队友。\";\n readonly 'stage.noMessages': \"还没有消息往来\";\n readonly 'stage.noTasks': \"还没有任务\";\n readonly 'stage.noNotes': \"共享工作区还是空的\";\n readonly 'stage.noNotesHint': \"成员用 team_note 把结论写在这里,不必互相发消息。\";\n readonly 'stage.boardAt': \"{time} 的快照\";\n readonly 'stage.boardStale': \"队友的写入直接进持久工作区,不经过主会话的日志——这里是主会话最后一次读写时的样子\";\n readonly 'stage.peerRing': \"同级成员可以直接走过去找对方;受管成员只找主会话\";\n readonly 'stage.roomHint': \"每个成员都有自己的工位;要说话就走过去说\";\n readonly 'stage.dock': \"协作面板\";\n readonly 'drawer.close': \"收起面板\";\n readonly 'drawer.feedHint': \"成员近况与团队往来\";\n readonly 'drawer.workspaceHint': \"留在这里的结论,整个团队都能看到\";\n readonly 'drawer.tasksHint': \"从待办到完成,每一步都在这里\";\n readonly 'feed.crew': \"成员状态\";\n readonly 'feed.log': \"往来记录\";\n readonly 'feed.open': \"在手 {count}\";\n readonly 'feed.quiet': \"还没有往来\";\n readonly 'screen.working': \"工作中…\";\n readonly 'member.leader': \"主会话\";\n readonly 'member.open': \"打开 {name} 的会话\";\n readonly 'member.openLeader': \"回到主会话\";\n readonly 'relation.managed': \"受管\";\n readonly 'relation.peer': \"同级\";\n readonly 'status.running': \"工作中\";\n readonly 'status.idle': \"空闲\";\n readonly 'task.pending': \"待办\";\n readonly 'task.active': \"进行中\";\n readonly 'task.done': \"已完成\";\n readonly 'task.unassigned': \"未指派\";\n readonly 'message.report': \"汇报\";\n readonly 'message.settled': \"已收工\";\n readonly 'message.hop': \"第 {hop} 跳\";\n readonly 'message.hopHint': \"这条消息在一次队友间对话里的转发深度;深度用完只能回到主会话\";\n};\n/** The namespace's dictionary key union (literal keys, locale-typed seats). */\nexport type TeamKey = keyof typeof zh;\nexport declare const en: Record<TeamKey, string>;\n","/**\n * Browser half of dsh-team: follow the current session's `team` projection and\n * contribute the team stage as one conversation view tab.\n *\n * There is no client-side fold. The host computes the team value once and the\n * framework pushes it here (history tail baseline + `session/projection`\n * frames), so this module only tracks WHICH session's value is on screen — and\n * whether that session has a team at all, because the tab exists exactly while\n * it does: an ordinary conversation never grows a view it cannot fill.\n */\nimport type { Context as ClientContext } from '@deepseek-ai/cordis';\nimport { type TeamPanelState } from './TeamStage.tsx';\nimport { type TeamKey } from './locales.ts';\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n /** Agent-team stage copy. */\n team: TeamKey;\n }\n}\n/** Required services: the slot registry, the session domain, and locale. */\nexport declare const inject: string[];\n/**\n * Register the locale dictionary and the view tab, and keep the stage store\n * pointed at the right session.\n * @param ctx - client root context.\n */\nexport declare function apply(ctx: ClientContext): void;\nexport type { TeamPanelState };\n"],"mappings":";;;;;;AAAA,IAAW,CAAC,gBAAgB;CAAC;OAAU,CAAC;CAAG,CAAC;AAAC;AAC7C,IAAW,CAAC,kBAAkB;CAAC;OAAU,CAAC;CAAG,CAAC;AAAC;AAC/C,IAAW,CAAC,mBAAmB;CAAC;OAAU,CAAC;CAAG,CAAC;AAAC;AAChD,IAAW,CAAC,kBAAkB;CAAC;OAAU,CAAC,YAAY;CAAG;EAAC;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;CAAE;AAAC;AACzF,IAAW,CAAC,gBAAgB;CAAC;OAAU,CAAC,cAAc;CAAG;EAAC;EAAI;EAAI;EAAI;EAAI;EAAI;CAAE;AAAC;AACjF,IAAW,CAAC,mBAAmB;CAAC;OAAU,CAAC,eAAe;CAAG;EAAC;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;CAAE;AAAC;AAC7F,IAAW,CAAC,sBAAsB;CAAC;OAAU,CAAC;CAAG;EAAC;EAAI;EAAI;EAAI;EAAI;CAAE;AAAC;;;;ACJrE,IAAW,CAAC,kBAAkB;CAAC;OAAS;EAAC;EAAgB;EAAc;EAAiB;CAAkB;CAAG;EAAC;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;CAAE;AAAC;;;;ACDzJ,IAAW,CAAC,MAAM;CAAC;OAAS,CAAC;CAAG;EAAC;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;EAAI;CAAE;AAAC;AAChO,IAAW,CAAC,WAAW;CAAC;OAAS,CAAC,EAAE;CAAG,CAAC,EAAE;AAAC;;;;ACC3C,IAAI,CAAC,MAAM;CAAC;OAAS,CAAC,OAAO;CAAG;EAAC;EAAI;EAAI;CAAE;CAAG,WAAW,EAAE;AAAC;AAC5D,IAAW,CAAC,UAAU;CAAC;OAAS,CAAC;CAAG,CAAC;AAAC;AACtC,IAAW,CAAC,SAAS;CAAC;OAAS,CAACA,OAAa;CAAG,CAAC,IAAI,EAAE;AAAC"}
package/dist/index.d.ts CHANGED
@@ -50,7 +50,7 @@ type TeamTaskStatus = 'pending' | 'active' | 'done';
50
50
  type TeamMessageKind =
51
51
  /** Content one member addressed to another through `team_send`. */
52
52
  'message' |
53
- /** A teammate's own result, delivered through the harness `report` tool. */
53
+ /** A teammate's own result, delivered through the continuation settlement message. */
54
54
  'report' |
55
55
  /** The runtime's account of a teammate's activation ending. */
56
56
  'settled';
@@ -290,10 +290,10 @@ declare class TeamService extends Service {
290
290
  teamOf(leader: Agent): TeamState;
291
291
  /**
292
292
  * Adopt one continuable child into the team world while its scope is being
293
- * composed. Called from the teammate setup contribution, which runs inside
294
- * the child's unpublished creation window — on cold resume the child is
295
- * already on the leader's roster, and only a child the roster has never seen
296
- * can be the spawn currently in flight.
293
+ * composed. Called from the teammate setup contribution after the child is
294
+ * published — on cold resume the child is already on the leader's roster,
295
+ * and only a child the roster has never seen can be the spawn currently in
296
+ * flight.
297
297
  * @param child - the unpublished child agent.
298
298
  * @returns the membership facts, or undefined for a child outside any team.
299
299
  */
@@ -590,7 +590,13 @@ declare const name = "team";
590
590
  declare const inject: string[];
591
591
  /**
592
592
  * Compose the team capability: the service, the durable projection unit, the
593
- * teammate world, the per-session leader tools, and the virtual workspaces.
593
+ * teammate world, the per-session leader tools, the virtual workspaces, and
594
+ * the human `/agent-teams` command.
595
+ *
596
+ * `commands` is injected softly rather than declared on the row, like
597
+ * `storageDomain`: UI-less compositions ship no command adapter, and the row
598
+ * must load there with every other capability intact.
599
+ *
594
600
  * @param ctx - the row's context.
595
601
  * @param config - the validated row configuration.
596
602
  */
package/dist/index.js CHANGED
@@ -1,8 +1,9 @@
1
1
  import z from "@deepseek-ai/schemastery";
2
+ import { ReasoningEffortId, createUserMessage } from "@deepseek-ai/dsh-llm";
2
3
  import { z as z$1 } from "zod";
3
4
  import { Service } from "@deepseek-ai/cordis";
4
- import { ReasoningEffortId, createUserMessage } from "@deepseek-ai/dsh-llm";
5
5
  import { SessionId } from "@deepseek-ai/dsh-session";
6
+ import { queueHostSubagentPrompt } from "@deepseek-ai/dsh-subagent/internal";
6
7
  import { defineTool } from "@deepseek-ai/dsh-tools";
7
8
  import { defineDomain, domainTable } from "@deepseek-ai/dsh-storage-domain";
8
9
  //#region src/config.ts
@@ -27,6 +28,60 @@ const Config = z.object({
27
28
  maxNoteChars: z.number().step(1).min(200).max(2e5).default(4e3)
28
29
  });
29
30
  //#endregion
31
+ //#region src/command.ts
32
+ /**
33
+ * The standing instruction that makes `/team <goal>` mean "use the team":
34
+ * without it the leader would often just do the work solo, which is exactly
35
+ * what the user typed the command to avoid having to argue against.
36
+ */
37
+ const BRIEF = "Pursue this request through your agent team rather than alone: decide what teammates the work needs, spawn them with team_spawn (each with a self-contained first task), coordinate them over team_send and the shared task list, and keep this session posted as results land.";
38
+ /** What the composer shows when the steering was accepted. */
39
+ const ACK = "The leader takes it from here: it will assemble and drive the team for this.";
40
+ /**
41
+ * The `/agent-teams` definition: one command, whole-goal input, image-capable.
42
+ * @returns the command definition for the registry.
43
+ */
44
+ function teamCommand() {
45
+ return {
46
+ name: "agent-teams",
47
+ description: "Hand a goal to an agent team: the main session spawns named teammates and coordinates them. Everything after the command becomes the team's brief.",
48
+ input: {
49
+ hint: "<what the team should do>",
50
+ images: true
51
+ },
52
+ handler({ agent, rawInput, attachments }) {
53
+ if (agent.session.header.origin === "subagent") return {
54
+ kind: "error",
55
+ text: "/agent-teams works in your main session — a teammate cannot lead a team."
56
+ };
57
+ const goal = rawInput.trim();
58
+ if (goal.length === 0 && attachments.length === 0) return {
59
+ kind: "error",
60
+ text: "Tell /agent-teams what the team should do, e.g. \"/agent-teams migrate auth to the new SDK\"."
61
+ };
62
+ agent.steer(createUserMessage({
63
+ content: [...attachments, {
64
+ type: "text",
65
+ text: goal.length === 0 ? BRIEF : `${BRIEF}\n\nRequest:\n${goal}`
66
+ }],
67
+ source: { kind: "user" }
68
+ }));
69
+ return {
70
+ kind: "success",
71
+ text: ACK
72
+ };
73
+ }
74
+ };
75
+ }
76
+ /**
77
+ * Register {@link teamCommand} into the row's context.
78
+ * @param ctx - the row context; must carry `ctx.commands`.
79
+ * @returns the exact disposer unregistering the command.
80
+ */
81
+ function installCommand(ctx) {
82
+ return ctx.commands.register(teamCommand());
83
+ }
84
+ //#endregion
30
85
  //#region src/contract.ts
31
86
  /** The empty value every session without a team folds to. */
32
87
  const EMPTY_TEAM_VIEW = {
@@ -167,17 +222,16 @@ function readFact(meta) {
167
222
  /**
168
223
  * Narrow one delivered message's source into a mailbox row, or reject it.
169
224
  *
170
- * Three vocabularies reach a leader's log: this plugin's own `team-message`
171
- * deliveries, and the harness's `subagent-report` / `subagent-settled` edges,
172
- * which a teammate produces through the built-in `report` tool and through the
173
- * end of its activation. The last two also arrive from ordinary subagents, so
174
- * the caller keeps only senders that are on the roster.
225
+ * Team deliveries use `team-message`; current continuation messages use
226
+ * `agent-message`; historical report and settlement sources remain readable so
227
+ * existing leader logs keep their mailbox rows. The latter sources can also
228
+ * come from ordinary subagents, so the caller keeps only roster members.
175
229
  */
176
230
  function readIncoming(source) {
177
231
  const record = asRecord(source);
178
232
  if (record === void 0) return void 0;
179
233
  const kind = record["kind"];
180
- if (kind !== "team-message" && kind !== "subagent-report" && kind !== "subagent-settled") return void 0;
234
+ if (kind !== "team-message" && kind !== "agent-message" && kind !== "subagent-report" && kind !== "subagent-settled") return void 0;
181
235
  const senderSessionId = asText(record["senderSessionId"]);
182
236
  if (senderSessionId === void 0) return void 0;
183
237
  const senderName = asText(record["senderName"]);
@@ -186,7 +240,7 @@ function readIncoming(source) {
186
240
  senderSessionId,
187
241
  ...senderName !== void 0 ? { senderName } : {},
188
242
  ...hop !== void 0 ? { hop } : {},
189
- kind: kind === "team-message" ? "message" : kind === "subagent-report" ? "report" : "settled"
243
+ kind: kind === "team-message" || kind === "agent-message" ? "message" : kind === "subagent-report" ? "report" : "settled"
190
244
  };
191
245
  }
192
246
  /** Append one row to the bounded feed. */
@@ -407,7 +461,7 @@ function teamProjection(maxRecentMessages) {
407
461
  viewSchema: teamViewSchema,
408
462
  view: (state) => state
409
463
  },
410
- stateVersion: 3
464
+ stateVersion: 4
411
465
  };
412
466
  }
413
467
  //#endregion
@@ -518,10 +572,10 @@ var TeamService = class extends Service {
518
572
  }
519
573
  /**
520
574
  * Adopt one continuable child into the team world while its scope is being
521
- * composed. Called from the teammate setup contribution, which runs inside
522
- * the child's unpublished creation window — on cold resume the child is
523
- * already on the leader's roster, and only a child the roster has never seen
524
- * can be the spawn currently in flight.
575
+ * composed. Called from the teammate setup contribution after the child is
576
+ * published — on cold resume the child is already on the leader's roster,
577
+ * and only a child the roster has never seen can be the spawn currently in
578
+ * flight.
525
579
  * @param child - the unpublished child agent.
526
580
  * @returns the membership facts, or undefined for a child outside any team.
527
581
  */
@@ -557,7 +611,10 @@ var TeamService = class extends Service {
557
611
  if (team.members.size >= this.config.maxTeammates) throw new TeamError("MAX_TEAMMATES", String(this.config.maxTeammates));
558
612
  if (findByName(team, request.name) !== void 0) throw new TeamError("DUPLICATE_NAME", request.name);
559
613
  await this.assertEffortOffered(leader, request);
560
- const agentOptions = { ...request.model !== void 0 ? { model: request.model } : {} };
614
+ const agentOptions = {
615
+ ...request.model !== void 0 ? { model: request.model } : {},
616
+ ...request.reasoningEffort !== void 0 ? { reasoningEffort: ReasoningEffortId(request.reasoningEffort) } : {}
617
+ };
561
618
  const pending = {
562
619
  fact: {
563
620
  name: request.name,
@@ -795,7 +852,7 @@ var TeamService = class extends Service {
795
852
  /** The durable view the leader's log folds to (the projection registry's cached cut). */
796
853
  durableView(leader) {
797
854
  const registry = this.ctx.get("sessionProjections");
798
- if (registry === void 0) return foldTeam(leader.session.events, this.config.maxRecentMessages);
855
+ if (registry === void 0) return foldTeam(leader.session.snapshotEvents(), this.config.maxRecentMessages);
799
856
  return registry.snapshot(leader.session).values.team ?? EMPTY_TEAM_VIEW;
800
857
  }
801
858
  /** Live runtime state of one teammate; `ready` means no live agent remains. */
@@ -933,10 +990,7 @@ var TeamService = class extends Service {
933
990
  actor.leader.send(message, "next-turn", true);
934
991
  return message.id;
935
992
  }
936
- return await this.ctx.subagents.followup(actor.leader, SessionId(recipient.id), content, {
937
- source,
938
- signal
939
- });
993
+ return await queueHostSubagentPrompt(this.ctx.subagents, actor.leader, SessionId(recipient.id), content, source, signal);
940
994
  }
941
995
  /**
942
996
  * Reject a reasoning effort the selected model does not offer, at spawn
@@ -1336,7 +1390,7 @@ function spawnTool(ctx) {
1336
1390
  function sendTool(ctx, audience) {
1337
1391
  return defineTool({
1338
1392
  name: "team_send",
1339
- description: audience === "leader" ? "Send a message to one teammate you have already spawned — with no team yet there is nobody to write to, so team_spawn comes first. It becomes that teammate's next turn: if it is busy, the message waits until the current turn ends, so it cannot redirect work already underway. Delivery is asynchronous — this returns once the message is accepted, never the teammate's answer; the reply arrives later as its own message to you." : "Send a message to another team member. Address the leader as \"leader\", or a teammate by its name. The message becomes the recipient's next turn; you get no answer back from this call. Use it to ask a peer for input, hand work over, or raise something with the leader mid-task. Finished work goes to the leader through the report tool instead. A conversation between teammates carries a budget: it may only relay so far and you may not keep going back and forth with the same member about it, so ask for what you actually need in one message. Messaging the leader is never refused — when a peer exchange stops converging, that is the way out.",
1393
+ description: audience === "leader" ? "Send a message to one teammate you have already spawned — with no team yet there is nobody to write to, so team_spawn comes first. It becomes that teammate's next turn: if it is busy, the message waits until the current turn ends, so it cannot redirect work already underway. Delivery is asynchronous — this returns once the message is accepted, never the teammate's answer; the reply arrives later as its own message to you." : "Send a message to another team member. Address the leader as \"leader\", or a teammate by its name. The message becomes the recipient's next turn; you get no answer back from this call. Use it to ask a peer for input, hand work over, or raise something with the leader mid-task. Finished work goes to the leader through team_send. A conversation between teammates carries a budget: it may only relay so far and you may not keep going back and forth with the same member about it, so ask for what you actually need in one message. Messaging the leader is never refused — when a peer exchange stops converging, that is the way out.",
1340
1394
  parameters: {
1341
1395
  to: {
1342
1396
  type: "string",
@@ -1399,15 +1453,14 @@ function sendTool(ctx, audience) {
1399
1453
  }
1400
1454
  /**
1401
1455
  * `team_task` — the shared task list. Writes are the leader's; teammates read
1402
- * it through `team_list` and report their outcomes through the built-in
1403
- * `report` tool.
1456
+ * it through `team_list` and send outcomes through `team_send`.
1404
1457
  * @param ctx - context carrying the team service.
1405
1458
  * @returns the tool definition.
1406
1459
  */
1407
1460
  function taskTool(ctx) {
1408
1461
  return defineTool({
1409
1462
  name: "team_task",
1410
- description: "Create or update one row of the shared team task list — the list every teammate can read, so it is where multi-teammate work is coordinated without routing every detail through messages. The list belongs to a live team, so spawn the teammates first: a row nobody is on the roster to read changes nothing, and assigning one to a name that is not on the roster is refused. Omit task_id to create a row (title required); pass task_id to update one. Assign with a teammate name or member id. A teammate closes its own row through its report, so you rarely set status yourself.",
1463
+ description: "Create or update one row of the shared team task list — the list every teammate can read, so it is where multi-teammate work is coordinated without routing every detail through messages. The list belongs to a live team, so spawn the teammates first: a row nobody is on the roster to read changes nothing, and assigning one to a name that is not on the roster is refused. Omit task_id to create a row (title required); pass task_id to update one. Assign with a teammate name or member id. A teammate closes its own row by sending the outcome to the leader, so you rarely set status yourself.",
1411
1464
  parameters: {
1412
1465
  title: {
1413
1466
  type: "string",
@@ -1914,6 +1967,30 @@ function release(disposers) {
1914
1967
  if (failures.length === 1) throw failures[0];
1915
1968
  if (failures.length > 1) throw new AggregateError(failures, "dsh-team: teammate teardown failed");
1916
1969
  }
1970
+ /** Observe the live agent registry so cold resumes and fresh children share one setup path. */
1971
+ function registerChildSetup(ctx, setup) {
1972
+ const installed = /* @__PURE__ */ new Map();
1973
+ const install = (agent) => {
1974
+ if (agent.session.header.origin !== "subagent" || installed.has(agent.id)) return;
1975
+ const dispose = setup(agent.ctx);
1976
+ installed.set(agent.id, dispose);
1977
+ };
1978
+ const disposeCreated = ctx.on("agent/created", (payload) => {
1979
+ install(payload.agent);
1980
+ });
1981
+ const disposeRemoved = ctx.on("agent/disposed", (payload) => {
1982
+ const dispose = installed.get(payload.agent.id);
1983
+ installed.delete(payload.agent.id);
1984
+ dispose?.();
1985
+ });
1986
+ for (const agent of ctx.agents.list()) install(agent);
1987
+ return () => {
1988
+ disposeRemoved();
1989
+ disposeCreated();
1990
+ for (const dispose of installed.values()) dispose();
1991
+ installed.clear();
1992
+ };
1993
+ }
1917
1994
  /** One roster line as a teammate reads it. */
1918
1995
  function memberLine(member) {
1919
1996
  const parts = [member.role, member.relation === "peer" ? "peer" : "managed"].filter((part) => part !== void 0);
@@ -1949,34 +2026,19 @@ function briefing(ctx, team, child) {
1949
2026
  reach,
1950
2027
  list,
1951
2028
  mine.length === 0 ? "No task on the shared list is assigned to you right now." : `Assigned to you on the shared task list: ${mine.map((task) => `${task.taskId} "${task.title}"`).join("; ")}.`,
1952
- "Nobody sees your session but you, so deliver results with the report tool — a self-contained answer, not \"done\". Use team_send when you need something FROM a member mid-task; the reply arrives later as its own turn, so do not wait for it in place. team_list shows the roster, the shared task list, and recent traffic. When you have reported, stop and wait for the next message instead of starting work nobody asked for. A conversation between teammates is budgeted: it may only relay so far and one pair may not keep trading messages inside it, so put everything you need into one message rather than negotiating. Reaching the leader is never refused — when an exchange with a peer stops converging, say so to the leader and move on."
2029
+ "Nobody sees your session but you, so deliver results to the leader with team_send — a self-contained answer, not \"done\". Use team_send when you need something FROM a member mid-task; the reply arrives later as its own turn, so do not wait for it in place. team_list shows the roster, the shared task list, and recent traffic. When you have sent the outcome, stop and wait for the next message instead of starting work nobody asked for. A conversation between teammates is budgeted: it may only relay so far and one pair may not keep trading messages inside it, so put everything you need into one message rather than negotiating. Reaching the leader is never refused — when an exchange with a peer stops converging, say so to the leader and move on."
1953
2030
  ].join("\n");
1954
2031
  }
1955
2032
  /**
1956
- * Pin one teammate's reasoning effort onto its own requests. `AgentOptions`
1957
- * carries no effort — it is request-header state — so the child's scoped
1958
- * request waterfall is where a per-teammate effort belongs.
1959
- * @param childCtx - the teammate's scoped context.
1960
- * @param effort - the provider-owned effort id recorded at spawn.
1961
- * @returns the disposer for the scoped listener.
1962
- */
1963
- function installEffort(childCtx, effort) {
1964
- return childCtx.on("agent/request", async (_payload, next) => ({
1965
- ...await next(),
1966
- reasoningEffort: ReasoningEffortId(effort)
1967
- }));
1968
- }
1969
- /**
1970
2033
  * Register the teammate composition for every continuable child of a team.
1971
2034
  * @param ctx - context carrying the team and subagent services.
1972
2035
  * @returns the exact effect disposer removing the contribution.
1973
2036
  */
1974
2037
  function installTeammateWorld(ctx) {
1975
- return ctx.subagents.registerContinuableSetup((childCtx) => {
2038
+ return registerChildSetup(ctx, (childCtx) => {
1976
2039
  const child = childCtx.agent;
1977
2040
  if (child === void 0) return () => {};
1978
- const member = ctx.team.adopt(child);
1979
- if (member === void 0) return () => {};
2041
+ if (ctx.team.adopt(child) === void 0) return () => {};
1980
2042
  const disposers = [];
1981
2043
  try {
1982
2044
  disposers.push(childCtx.systemPrompt.section({
@@ -1986,7 +2048,6 @@ function installTeammateWorld(ctx) {
1986
2048
  }));
1987
2049
  disposers.push(childCtx.tools.register(sendTool(ctx, "member")));
1988
2050
  disposers.push(childCtx.tools.register(listTool(ctx, "member")));
1989
- if (member.effort !== void 0) disposers.push(installEffort(childCtx, member.effort));
1990
2051
  } catch (error) {
1991
2052
  release(disposers);
1992
2053
  throw error;
@@ -2007,7 +2068,7 @@ function installTeammateWorld(ctx) {
2007
2068
  * @returns the exact effect disposer removing the contribution.
2008
2069
  */
2009
2070
  function installTeammateWorkspace(ctx, workspace) {
2010
- return ctx.subagents.registerContinuableSetup((childCtx) => {
2071
+ return registerChildSetup(ctx, (childCtx) => {
2011
2072
  const child = childCtx.agent;
2012
2073
  const leaderId = child?.session.header.parentSession;
2013
2074
  const roster = child === void 0 ? void 0 : ctx.team.rosterFor(child);
@@ -2128,12 +2189,21 @@ function installWorkspaces(ctx, config) {
2128
2189
  }
2129
2190
  /**
2130
2191
  * Compose the team capability: the service, the durable projection unit, the
2131
- * teammate world, the per-session leader tools, and the virtual workspaces.
2192
+ * teammate world, the per-session leader tools, the virtual workspaces, and
2193
+ * the human `/agent-teams` command.
2194
+ *
2195
+ * `commands` is injected softly rather than declared on the row, like
2196
+ * `storageDomain`: UI-less compositions ship no command adapter, and the row
2197
+ * must load there with every other capability intact.
2198
+ *
2132
2199
  * @param ctx - the row's context.
2133
2200
  * @param config - the validated row configuration.
2134
2201
  */
2135
2202
  function apply(ctx, config) {
2136
2203
  ctx.plugin(TeamService, config);
2204
+ ctx.inject(["commands"], (commandCtx) => {
2205
+ commandCtx.effect(() => installCommand(commandCtx), "team: /agent-teams command");
2206
+ });
2137
2207
  ctx.inject(["team"], (teamCtx) => {
2138
2208
  teamCtx.effect(() => teamCtx.sessionProjections.register(teamProjection(config.maxRecentMessages)), "team: durable projection unit");
2139
2209
  teamCtx.effect(() => installTeammateWorld(teamCtx), "team: teammate world");
package/dsh-manifest.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-team",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "description": "Agent teams for DeepSeek Harness: named long-lived teammates over ctx.subagents, a shared task list, a member-to-member mailbox, virtual workspaces, and a live team room in the conversation view",
5
5
  "license": "MIT",
6
6
  "author": "huxint",
@@ -31,7 +31,7 @@
31
31
  "client": {
32
32
  "inject": [
33
33
  "@deepseek-ai/dsh-client-locale",
34
- "@deepseek-ai/dsh-client-runtime",
34
+ "@deepseek-ai/dsh-api-session-controller",
35
35
  "@deepseek-ai/dsh-client-ui-conversation"
36
36
  ],
37
37
  "platform": "web"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-team",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "description": "Agent teams for DeepSeek Harness: named long-lived teammates over ctx.subagents, a shared task list, a member-to-member mailbox, virtual workspaces, and a live team room in the conversation view",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -26,7 +26,7 @@
26
26
  "client": {
27
27
  "inject": [
28
28
  "@deepseek-ai/dsh-client-locale",
29
- "@deepseek-ai/dsh-client-runtime",
29
+ "@deepseek-ai/dsh-api-session-controller",
30
30
  "@deepseek-ai/dsh-client-ui-conversation"
31
31
  ],
32
32
  "platform": "web"
@@ -36,57 +36,71 @@
36
36
  "build": "tsdown",
37
37
  "test": "vitest run",
38
38
  "typecheck": "tsc --noEmit -p tsconfig.json",
39
+ "screenshot": "node scripts/screenshot/shoot.mjs",
39
40
  "check": "pnpm run typecheck && pnpm run test && pnpm run build"
40
41
  },
41
42
  "dependencies": {
42
- "@deepseek-ai/schemastery": "^3.18.1",
43
+ "@deepseek-ai/schemastery": "^3.18.2",
44
+ "three": "^0.185.1",
43
45
  "zod": "^4.4.3"
44
46
  },
45
47
  "peerDependencies": {
46
- "@deepseek-ai/cordis": "^4.0.1",
47
- "@deepseek-ai/dsh-agent": "^0.1.1-rc.2",
48
- "@deepseek-ai/dsh-client-locale": "^0.1.1-rc.2",
49
- "@deepseek-ai/dsh-client-runtime": "^0.1.1-rc.2",
50
- "@deepseek-ai/dsh-client-ui-layout": "^0.1.1-rc.2",
51
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.1-rc.2",
52
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.1-rc.2",
53
- "@deepseek-ai/dsh-llm": "^0.1.1-rc.2",
54
- "@deepseek-ai/dsh-session": "^0.1.1-rc.2",
55
- "@deepseek-ai/dsh-session-projection": "^0.1.1-rc.2",
56
- "@deepseek-ai/dsh-storage-domain": "^0.1.1-rc.2",
57
- "@deepseek-ai/dsh-subagent": "^0.1.1-rc.2",
58
- "@deepseek-ai/dsh-system-prompt": "^0.1.1-rc.2",
59
- "@deepseek-ai/dsh-tools": "^0.1.1-rc.2",
48
+ "@deepseek-ai/cordis": "^4.0.2",
49
+ "@deepseek-ai/dsh-agent": "^0.1.2-rc.1",
50
+ "@deepseek-ai/dsh-api-session-controller": "^0.1.2-rc.1",
51
+ "@deepseek-ai/dsh-client-locale": "^0.1.2-rc.1",
52
+ "@deepseek-ai/dsh-client-store": "^0.1.2-rc.1",
53
+ "@deepseek-ai/dsh-client-ui-renderer": "^0.1.2-rc.1",
54
+ "@deepseek-ai/dsh-client-ui-session": "^0.1.2-rc.1",
55
+ "@deepseek-ai/dsh-client-ui-layout": "^0.1.2-rc.1",
56
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.2-rc.1",
57
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.2-rc.1",
58
+ "@deepseek-ai/dsh-commands": "^0.1.2-rc.1",
59
+ "@deepseek-ai/dsh-llm": "^0.1.2-rc.1",
60
+ "@deepseek-ai/dsh-session": "^0.1.2-rc.1",
61
+ "@deepseek-ai/dsh-session-projection": "^0.1.2-rc.1",
62
+ "@deepseek-ai/dsh-storage-domain": "^0.1.2-rc.1",
63
+ "@deepseek-ai/dsh-subagent": "^0.1.2-rc.1",
64
+ "@deepseek-ai/dsh-system-prompt": "^0.1.2-rc.1",
65
+ "@deepseek-ai/dsh-tools": "^0.1.2-rc.1",
60
66
  "react": "^18.2.0"
61
67
  },
62
68
  "devDependencies": {
63
- "@deepseek-ai/cordis": "^4.0.1",
64
- "@deepseek-ai/dsh-agent": "^0.1.1-rc.2",
65
- "@deepseek-ai/dsh-client-locale": "^0.1.1-rc.2",
66
- "@deepseek-ai/dsh-client-runtime": "^0.1.1-rc.2",
67
- "@deepseek-ai/dsh-client-ui-conversation": "0.1.1-rc.2",
68
- "@deepseek-ai/dsh-client-ui-layout": "^0.1.1-rc.2",
69
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.1-rc.2",
70
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.1-rc.2",
71
- "@deepseek-ai/dsh-llm": "^0.1.1-rc.2",
72
- "@deepseek-ai/dsh-session": "^0.1.1-rc.2",
73
- "@deepseek-ai/dsh-session-persistence": "^0.1.1-rc.2",
74
- "@deepseek-ai/dsh-session-projection": "^0.1.1-rc.2",
75
- "@deepseek-ai/dsh-storage": "0.1.1-rc.2",
76
- "@deepseek-ai/dsh-storage-domain": "0.1.1-rc.2",
77
- "@deepseek-ai/dsh-subagent": "^0.1.1-rc.2",
78
- "@deepseek-ai/dsh-system-prompt": "^0.1.1-rc.2",
79
- "@deepseek-ai/dsh-tools": "^0.1.1-rc.2",
69
+ "@deepseek-ai/cordis": "^4.0.2",
70
+ "@deepseek-ai/dsh-agent": "^0.1.2-rc.1",
71
+ "@deepseek-ai/dsh-api-session-controller": "^0.1.2-rc.1",
72
+ "@deepseek-ai/dsh-client-locale": "^0.1.2-rc.1",
73
+ "@deepseek-ai/dsh-client-store": "^0.1.2-rc.1",
74
+ "@deepseek-ai/dsh-client-ui-conversation": "0.1.2-rc.1",
75
+ "@deepseek-ai/dsh-client-ui-renderer": "^0.1.2-rc.1",
76
+ "@deepseek-ai/dsh-client-ui-session": "^0.1.2-rc.1",
77
+ "@deepseek-ai/dsh-client-ui-layout": "^0.1.2-rc.1",
78
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.2-rc.1",
79
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.2-rc.1",
80
+ "@deepseek-ai/dsh-commands": "^0.1.2-rc.1",
81
+ "@deepseek-ai/dsh-llm": "^0.1.2-rc.1",
82
+ "@deepseek-ai/dsh-session": "^0.1.2-rc.1",
83
+ "@deepseek-ai/dsh-session-persistence": "^0.1.2-rc.1",
84
+ "@deepseek-ai/dsh-session-projection": "^0.1.2-rc.1",
85
+ "@deepseek-ai/dsh-storage": "0.1.2-rc.1",
86
+ "@deepseek-ai/dsh-storage-domain": "0.1.2-rc.1",
87
+ "@deepseek-ai/dsh-subagent": "^0.1.2-rc.1",
88
+ "@deepseek-ai/dsh-system-prompt": "^0.1.2-rc.1",
89
+ "@deepseek-ai/dsh-tools": "^0.1.2-rc.1",
90
+ "@deepseek-ai/dsh-util-values": "^0.1.2-rc.1",
80
91
  "@testing-library/react": "^16.3.0",
81
92
  "@types/node": "^22.10.0",
82
93
  "@types/react": "~18.3.1",
83
94
  "@types/react-dom": "~18.3.0",
95
+ "@types/three": "^0.185.4",
84
96
  "jsdom": "^26.1.0",
85
97
  "lightningcss": "^1.28.0",
98
+ "playwright-core": "1.62.1",
86
99
  "react": "^18.2.0",
87
100
  "react-dom": "^18.3.1",
88
101
  "tsdown": "^0.22.2",
89
102
  "typescript": "^6.0.3",
103
+ "vite": "8.2.1",
90
104
  "vitest": "^4.1.8"
91
105
  }
92
106
  }