@nanmicoder/dsh-agent-teams 0.1.0

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.
Files changed (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +72 -0
  3. package/assets/agent-teams/action-celebrating.png +0 -0
  4. package/assets/agent-teams/action-reporting.png +0 -0
  5. package/assets/agent-teams/action-sending.png +0 -0
  6. package/assets/agent-teams/action-sleeping.png +0 -0
  7. package/assets/agent-teams/action-thinking.png +0 -0
  8. package/assets/agent-teams/action-working.png +0 -0
  9. package/assets/agent-teams/data-analyst.png +0 -0
  10. package/assets/agent-teams/designer.png +0 -0
  11. package/assets/agent-teams/docs-coordinator.png +0 -0
  12. package/assets/agent-teams/engineer.png +0 -0
  13. package/assets/agent-teams/qa-engineer.png +0 -0
  14. package/assets/agent-teams/researcher.png +0 -0
  15. package/assets/agent-teams/security-reviewer.png +0 -0
  16. package/assets/agent-teams/team-lead.png +0 -0
  17. package/cordis.patch.yml +21 -0
  18. package/lib/client/ActivityPanel.js +340 -0
  19. package/lib/client/AgentTeamsCard.js +74 -0
  20. package/lib/client/activity-model.js +70 -0
  21. package/lib/client/agent-teams-card-definition.js +85 -0
  22. package/lib/client/artwork.js +40 -0
  23. package/lib/client/index.js +33 -0
  24. package/lib/client.js +1235 -0
  25. package/lib/client.js.map +1 -0
  26. package/lib/event-types.js +12 -0
  27. package/lib/events.js +60 -0
  28. package/lib/index.js +172 -0
  29. package/lib/members.js +168 -0
  30. package/lib/snapshot.js +155 -0
  31. package/lib/state.js +461 -0
  32. package/lib/tools.js +749 -0
  33. package/lib/types/client/ActivityPanel.d.ts +64 -0
  34. package/lib/types/client/AgentTeamsCard.d.ts +24 -0
  35. package/lib/types/client/activity-model.d.ts +31 -0
  36. package/lib/types/client/agent-teams-card-definition.d.ts +44 -0
  37. package/lib/types/client/artwork.d.ts +19 -0
  38. package/lib/types/client/index.d.ts +11 -0
  39. package/lib/types/event-types.d.ts +103 -0
  40. package/lib/types/events.d.ts +37 -0
  41. package/lib/types/index.d.ts +42 -0
  42. package/lib/types/members.d.ts +86 -0
  43. package/lib/types/snapshot.d.ts +83 -0
  44. package/lib/types/state.d.ts +144 -0
  45. package/lib/types/tools.d.ts +40 -0
  46. package/lib/types/types.d.ts +73 -0
  47. package/lib/types.js +11 -0
  48. package/package.json +108 -0
@@ -0,0 +1,64 @@
1
+ /**
2
+ * AgentTeams activity panel: the top-right floater monitoring every team.
3
+ *
4
+ * Modeled on the Claude Code desktop SessionActivityPanel: a fixed glass
5
+ * panel at the top-right corner. On wide viewports it cooperatively makes the
6
+ * conversation column yield space; narrow viewports keep overlay mode. It
7
+ * polls the host `/plugins/dsh-agent-teams/state` route for
8
+ * server-side snapshots (durable files + live subagent activity), with a
9
+ * collapsed badge that auto-expands once when activity appears. Archived
10
+ * teams stay available for the owning conversation after live work ends.
11
+ *
12
+ * The floater mounts through a body portal (no top-right slot exists in the
13
+ * web shell); it is not a conversation node — the in-conversation panel was
14
+ * removed in favor of this always-available monitor.
15
+ * @module dsh-agent-teams/client/activity
16
+ */
17
+ import type { SessionId } from '@deepseek-ai/dsh-session/types';
18
+ import type { ObservableSnapshot, SessionListState } from '@deepseek-ai/dsh-client-runtime/client';
19
+ /** One member row of a host snapshot. */
20
+ export interface ActivityMember {
21
+ readonly id: string;
22
+ readonly name: string;
23
+ readonly role: string;
24
+ readonly activity: 'working' | 'idle' | 'unknown';
25
+ readonly progress: number;
26
+ readonly done: number;
27
+ readonly total: number;
28
+ readonly currentTask: string;
29
+ readonly unread: number;
30
+ }
31
+ /** One task row of a host snapshot. */
32
+ export interface ActivityTask {
33
+ readonly id: string;
34
+ readonly subject: string;
35
+ readonly status: string;
36
+ readonly state: 'blocked' | 'open' | 'running' | 'completed';
37
+ readonly assignee: string;
38
+ readonly dependencies: readonly string[];
39
+ readonly depth: number;
40
+ }
41
+ /** One captain-inbox preview row. */
42
+ export interface ActivityMessage {
43
+ readonly from: string;
44
+ readonly content: string;
45
+ }
46
+ /** One team snapshot (mirrors the host TeamActivitySnapshot). */
47
+ export interface ActivityTeam {
48
+ readonly workspace: string;
49
+ readonly teamId: string;
50
+ readonly name: string;
51
+ readonly description?: string;
52
+ readonly captainSessionId: string;
53
+ readonly members: readonly ActivityMember[];
54
+ readonly tasks: readonly ActivityTask[];
55
+ readonly messageCount: number;
56
+ readonly captainInbox: readonly ActivityMessage[];
57
+ }
58
+ /** The top-right activity floater. Teams follow the current session: live
59
+ * snapshots and historic card summaries are only shown while their captain
60
+ * session is the one currently open. */
61
+ export declare function ActivityPanel({ sessionsList, openSession }: {
62
+ readonly sessionsList: ObservableSnapshot<SessionListState>;
63
+ readonly openSession: (id: SessionId) => void;
64
+ }): import("react").JSX.Element | null;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * AgentTeams conversation card: the lightweight in-conversation summary for
3
+ * one team — the captain's whale avatar and name, the member roster as
4
+ * clickable whale avatars (opening the member's subagent transcript), and
5
+ * an "activity panel" button that re-activates the top-right floater.
6
+ *
7
+ * The floater and this card share the `agent-teams:open-panel` window event
8
+ * so the card can summon the panel even after it was closed (or when an old
9
+ * session is re-opened for review).
10
+ * @module dsh-agent-teams/client/card
11
+ */
12
+ import type { PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
13
+ import type { SessionId } from '@deepseek-ai/dsh-session/types';
14
+ /** Window event name the floater listens for to open itself. */
15
+ export declare const OPEN_PANEL_EVENT = "agent-teams:open-panel";
16
+ /** Navigation action injected from the plugin's own SessionsService access. */
17
+ export interface AgentTeamsCardInjected {
18
+ readonly openSession: (id: SessionId) => void;
19
+ readonly currentSessionId: () => SessionId | undefined;
20
+ }
21
+ /** Complete keyed Chat renderer props. */
22
+ export type AgentTeamsCardProps = PropsRuntime<'conversation.chat.node', 'agent-teams'> & PropsLocale<'agentTeams'> & AgentTeamsCardInjected;
23
+ /** Render one durable team as a compact conversation card. */
24
+ export declare function AgentTeamsCard({ node, openSession, currentSessionId }: AgentTeamsCardProps): import("react").JSX.Element;
@@ -0,0 +1,31 @@
1
+ /** Pure relationship projections used by the AgentTeams activity panel. */
2
+ /** Minimum task shape needed to derive dependency relationships. */
3
+ export interface RelationshipTask {
4
+ readonly id: string;
5
+ readonly dependencies: readonly string[];
6
+ readonly depth: number;
7
+ }
8
+ /** One dependency-depth stage in stable display order. */
9
+ export interface RelationshipStage<T extends RelationshipTask> {
10
+ readonly depth: number;
11
+ readonly tasks: readonly T[];
12
+ }
13
+ /**
14
+ * Whether an expanded activity panel still belongs to the current session.
15
+ *
16
+ * The panel is mounted through a body portal, so React does not remount it
17
+ * when the conversation route changes. Ownership keeps an expanded panel
18
+ * from leaking onto the new-session screen (or another conversation) while
19
+ * its local open state is being reset.
20
+ */
21
+ export declare function activityPanelExpandedForSession(open: boolean, owner: string | undefined, current: string | undefined): boolean;
22
+ /** Group tasks by their precomputed dependency depth. */
23
+ export declare function taskStages<T extends RelationshipTask>(tasks: readonly T[]): readonly RelationshipStage<T>[];
24
+ /**
25
+ * Return the complete upstream/downstream chain around one task.
26
+ *
27
+ * Traversal uses both dependency directions and remains cycle-safe, so the UI
28
+ * can highlight every handoff related to the focused task even if malformed
29
+ * durable data contains a cycle.
30
+ */
31
+ export declare function relatedTaskIds(taskId: string, tasks: readonly RelationshipTask[]): ReadonlySet<string>;
@@ -0,0 +1,44 @@
1
+ /**
2
+ * AgentTeams conversation card: a lightweight in-conversation summary shown
3
+ * when a team is created — the captain's name, the member roster with whale
4
+ * avatars, and an entry point that re-activates the top-right activity
5
+ * panel (useful after the floater was closed, or when re-opening an old
6
+ * session for review).
7
+ *
8
+ * The fold anchors to the Harness's durable `tool/call` + `tool/result`
9
+ * records for `agent_teams_create`. Those are first-party session events, so
10
+ * the card survives restarts without writing an out-of-repo event type.
11
+ * @module dsh-agent-teams/client/card
12
+ */
13
+ import type { ConversationNodeDefinition } from '@deepseek-ai/dsh-client-runtime/client';
14
+ /** Final keyed Chat payload for the team summary card. */
15
+ export interface AgentTeamsCardData {
16
+ readonly teamId: string;
17
+ /** The captain session that owns this team (panel follows it). */
18
+ readonly captainSessionId: string;
19
+ readonly teamName: string;
20
+ readonly members: readonly {
21
+ readonly id: string;
22
+ readonly name: string;
23
+ readonly role: string;
24
+ }[];
25
+ }
26
+ declare module '@deepseek-ai/dsh-client-ui-conversation/client' {
27
+ interface ChatNodeDataMap {
28
+ /** Lightweight team summary card anchoring the conversation. */
29
+ 'agent-teams': AgentTeamsCardData;
30
+ }
31
+ }
32
+ /** Folded team record (the node's business state). */
33
+ export interface AgentTeamsNodeState {
34
+ readonly teamId: string;
35
+ readonly name: string;
36
+ readonly accepted: boolean;
37
+ }
38
+ /** Parse the only create-call fields the historic card owns. */
39
+ export declare function parseAgentTeamsCreateArgs(value: string): {
40
+ teamId: string;
41
+ name: string;
42
+ } | undefined;
43
+ /** Durable first-party tool events folded into one keyed Chat node. */
44
+ export declare const agentTeamsCardDefinition: ConversationNodeDefinition<AgentTeamsNodeState>;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Shared whale artwork lookup for the activity panel and the conversation
3
+ * card: role keywords map to the packaged role images; the captain always
4
+ * uses the lead whale.
5
+ * @module dsh-agent-teams/client/artwork
6
+ */
7
+ /** Artwork route prefix served by the plugin host half. */
8
+ export declare const ART_BASE = "/plugins/dsh-agent-teams/assets/";
9
+ /** Captain artwork (always the lead whale). */
10
+ export declare const LEAD_ART = "/plugins/dsh-agent-teams/assets/team-lead.png";
11
+ /** Status action artwork per member activity. */
12
+ export declare const ACTION_ART: Record<'working' | 'idle' | 'unknown', string>;
13
+ /**
14
+ * Member artwork URL, or null when no role matches (initial-letter fallback).
15
+ * @param name - the member's display name.
16
+ * @param role - the member's role text.
17
+ * @returns the artwork URL, or null when unmatched.
18
+ */
19
+ export declare function memberArtUrl(name: string, role: string): string | null;
@@ -0,0 +1,11 @@
1
+ /** Browser plugin for the AgentTeams activity floater and conversation card. */
2
+ import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';
3
+ /** Required services: conversation nodes, slots, and sessions navigation. */
4
+ export declare const inject: string[];
5
+ /**
6
+ * Mount the floater through a body portal (the web shell has no top-right
7
+ * slot) and register the in-conversation team card, whose "activity panel"
8
+ * button re-activates the floater via a window event — the recovery path
9
+ * for a closed floater or a re-opened session.
10
+ */
11
+ export declare function apply(ctx: ClientContext): void;
@@ -0,0 +1,103 @@
1
+ /**
2
+ * AgentTeams session event types — pure types only, zero imports.
3
+ *
4
+ * This file intentionally imports nothing: both the host program (the
5
+ * emitter in `events.ts`) and the browser program (the Conversation Node
6
+ * definition) must be able to load these types and the `SessionEventMap`
7
+ * declaration merge without pulling in host-side `Context` augmentations
8
+ * (dsh-session's index declares `Context.sessions: SessionStore`, which
9
+ * collides with the browser runtime's `ISessions` under the same name).
10
+ * @module dsh-agent-teams/event-types
11
+ */
12
+ /** Opens one team record: the captain created the team. */
13
+ export interface AgentTeamsTeamCreatedData {
14
+ readonly teamId: string;
15
+ /** The captain session that owns this team (UI follows it). */
16
+ readonly captainSessionId: string;
17
+ readonly name: string;
18
+ readonly description?: string;
19
+ }
20
+ /** Records one member after its continuable subagent is spawned. */
21
+ export interface AgentTeamsMemberAddedData {
22
+ readonly teamId: string;
23
+ readonly memberId: string;
24
+ readonly name: string;
25
+ readonly role?: string;
26
+ }
27
+ /** Marks one member removed. */
28
+ export interface AgentTeamsMemberRemovedData {
29
+ readonly teamId: string;
30
+ readonly memberId: string;
31
+ }
32
+ /** Records one task in the team's task list. */
33
+ export interface AgentTeamsTaskCreatedData {
34
+ readonly teamId: string;
35
+ readonly taskId: string;
36
+ readonly subject: string;
37
+ readonly dependencies: readonly string[];
38
+ readonly assignee?: string;
39
+ }
40
+ /** Records one task status/assignee/output transition. */
41
+ export interface AgentTeamsTaskUpdatedData {
42
+ readonly teamId: string;
43
+ readonly taskId: string;
44
+ readonly status: string;
45
+ readonly assignee?: string;
46
+ readonly output?: string;
47
+ }
48
+ /** Closes one team record: the team was deleted. */
49
+ export interface AgentTeamsTeamDeletedData {
50
+ readonly teamId: string;
51
+ }
52
+ /** Records one mailbox message sent between team agents. */
53
+ export interface AgentTeamsMessageSentData {
54
+ readonly teamId: string;
55
+ readonly messageId: string;
56
+ /** `captain` or a member name. */
57
+ readonly from: string;
58
+ /** `captain` or a member name. */
59
+ readonly to: string;
60
+ readonly content: string;
61
+ readonly ts: number;
62
+ }
63
+ declare module '@deepseek-ai/dsh-session/types' {
64
+ interface SessionEventMap {
65
+ /**
66
+ * Opens one team record.
67
+ * @param data - stable team identity and display name.
68
+ */
69
+ 'agent-teams/team-created': AgentTeamsTeamCreatedData;
70
+ /**
71
+ * Records one team member.
72
+ * @param data - team identity, member child session, and display identity.
73
+ */
74
+ 'agent-teams/member-added': AgentTeamsMemberAddedData;
75
+ /**
76
+ * Records one member removal.
77
+ * @param data - team identity and the member's child session id.
78
+ */
79
+ 'agent-teams/member-removed': AgentTeamsMemberRemovedData;
80
+ /**
81
+ * Records one task creation.
82
+ * @param data - team identity, task id, subject, dependencies, assignee.
83
+ */
84
+ 'agent-teams/task-created': AgentTeamsTaskCreatedData;
85
+ /**
86
+ * Records one task transition.
87
+ * @param data - team identity, task id, and the new status/assignee/output.
88
+ */
89
+ 'agent-teams/task-updated': AgentTeamsTaskUpdatedData;
90
+ /**
91
+ * Records one mailbox message.
92
+ * @param data - team identity, sender, recipient, and content.
93
+ */
94
+ 'agent-teams/message-sent': AgentTeamsMessageSentData;
95
+ /**
96
+ * Closes one team record after deletion.
97
+ * @param data - stable team identity.
98
+ */
99
+ 'agent-teams/team-deleted': AgentTeamsTeamDeletedData;
100
+ }
101
+ }
102
+ /** The full set of `agent-teams/*` event names. */
103
+ export type AgentTeamsEventType = 'agent-teams/team-created' | 'agent-teams/member-added' | 'agent-teams/member-removed' | 'agent-teams/task-created' | 'agent-teams/task-updated' | 'agent-teams/message-sent' | 'agent-teams/team-deleted';
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Durable AgentTeams session events and their emitter.
3
+ *
4
+ * Every team-state mutation appends one event to the captain's Session, so
5
+ * the web client's Conversation Node mechanism can fold the tree view from
6
+ * the session log deterministically (same mechanism as `tool-workflow`'s
7
+ * `tool-workflow/*` record events). Events append to the captain's session
8
+ * even when a member agent performed the mutation, so the captain's
9
+ * conversation stream stays the single authoritative monitor surface.
10
+ *
11
+ * Types and the `SessionEventMap` merge live in `event-types.ts` (zero
12
+ * imports) so the browser program can load them without host augmentations.
13
+ * @module dsh-agent-teams/events
14
+ */
15
+ import type { Context } from '@deepseek-ai/cordis';
16
+ import type { Session } from '@deepseek-ai/dsh-session';
17
+ import type { SessionEventMap } from '@deepseek-ai/dsh-session/types';
18
+ import type { AgentTeamsEventType } from './event-types.ts';
19
+ /**
20
+ * Append one AgentTeams event to a Session, containing failures (a broken
21
+ * durable record must never break team tool execution).
22
+ * @param ctx - the plugin context (for logging).
23
+ * @param session - the session to record into (the captain's, normally).
24
+ * @param type - the event type.
25
+ * @param data - the event payload.
26
+ */
27
+ export declare function appendTeamEvent(ctx: Context, session: Session, type: AgentTeamsEventType, data: SessionEventMap[AgentTeamsEventType]): void;
28
+ /**
29
+ * Resolve the captain's live Session for event recording. The captain agent
30
+ * may be offline (its team outlives the session), in which case the caller's
31
+ * own session is used as the fallback record target.
32
+ * @param ctx - the plugin context (injects `agents`).
33
+ * @param captainSessionId - the captain's durable session id.
34
+ * @param fallback - the calling agent's session, used when the captain is not live.
35
+ * @returns the session to record into.
36
+ */
37
+ export declare function captainSessionOf(ctx: Context, captainSessionId: string, fallback: Session): Session;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * AgentTeams for DeepSeek Harness.
3
+ *
4
+ * A host-plane plugin that registers the `agent_teams_*` tools and one usage
5
+ * section into the global system prompt. After installation any session can
6
+ * run multi-agent teamwork through natural language (e.g. "use AgentTeams to research X"):
7
+ * the model creates a team (it becomes the captain), spawns members as
8
+ * durable continuable subagents, breaks the goal into tasks with
9
+ * dependencies, wakes members with messages, relays reports, and collects
10
+ * results.
11
+ *
12
+ * Installation (bundle): `dsh plugin --profile <name> add @nanmicoder/dsh-agent-teams`
13
+ * (or a local path). The bundle patch mounts this plugin row into the host
14
+ * composition; the tools register into the shared `tools` registry and the
15
+ * usage section into the global system prompt, so the plugin needs no realm.
16
+ *
17
+ * @module dsh-agent-teams
18
+ */
19
+ import type { Context } from '@deepseek-ai/cordis';
20
+ import z from '@deepseek-ai/schemastery';
21
+ export declare const name = "agent-teams";
22
+ export declare const inject: string[];
23
+ /** Plugin configuration. */
24
+ export interface Config {
25
+ /**
26
+ * State directory name under the captain's workspace; team state lives at
27
+ * `<workspace>/<stateDir>/<teamId>/` (default `.agent-teams`).
28
+ */
29
+ stateDir?: string;
30
+ /** `ctx.subagents` provider used to spawn members; must support continuable children and personas (default `spawn`). */
31
+ memberProvider?: string;
32
+ /** Optional model override applied to every member. */
33
+ memberModel?: string;
34
+ /** Member delegation depth cap (default `1`; `0` forbids delegation entirely). */
35
+ memberMaxDepth?: number;
36
+ /** Team size cap in members (default `8`). */
37
+ maxMembers?: number;
38
+ /** Prompt-section order for the usage policy (default `117`, after delegation policy). */
39
+ promptSectionOrder?: number;
40
+ }
41
+ export declare const Config: z<Config>;
42
+ export declare function apply(ctx: Context, config: Config): void;
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Member subagent lifecycle: spawn a continuable child per member, deliver
3
+ * messages into its FIFO inbox, and observe its activity.
4
+ *
5
+ * Members are durable continuable subagents of the captain, so a member keeps
6
+ * its conversation across turns and across harness restarts: the captain
7
+ * wakes it with {@link ctx.subagents.followup}, it works through its turn
8
+ * (updating team state through the `agent_teams_*` tools), and becomes idle
9
+ * again. Its final assistant message is not readable programmatically, so the
10
+ * member persists its report into the captain's mailbox and the task records,
11
+ * which the captain reads through `agent_teams_status`.
12
+ * @module dsh-agent-teams/members
13
+ */
14
+ import type { Context } from '@deepseek-ai/cordis';
15
+ import type { Agent } from '@deepseek-ai/dsh-agent';
16
+ import type { TeamMember, TeamState } from './types.ts';
17
+ /** Runtime knobs for member spawning, resolved from plugin config. */
18
+ export interface MemberRuntimeConfig {
19
+ /** Registered `ctx.subagents` provider name (must support continuable + persona). */
20
+ provider: string;
21
+ /** Optional model override applied to every member. */
22
+ model?: string;
23
+ /** Child delegation depth cap (0 forbids delegation entirely). */
24
+ maxDepth?: number;
25
+ }
26
+ /**
27
+ * The member's system prompt (persona), shadowing the deployment persona for
28
+ * that child. Self-contained: it replaces the whole persona section.
29
+ * @param team - the team the member joined.
30
+ * @param member - the member record (name/role are read before spawning).
31
+ * @param stateDir - configured state directory, so the member can locate the
32
+ * team files with its own file tools.
33
+ */
34
+ export declare function memberPersona(team: TeamState, member: TeamMember, stateDir: string): string;
35
+ /**
36
+ * The initial user message delivered when the member is created.
37
+ * @param team - the team the member joined.
38
+ */
39
+ export declare function memberWelcome(team: TeamState): string;
40
+ /**
41
+ * Spawn one member as a durable continuable subagent of the captain and fill
42
+ * `member.id` with its child session id. On failure nothing is persisted.
43
+ * @param ctx - the plugin context (injects `subagents`).
44
+ * @param config - member runtime knobs.
45
+ * @param captain - the exact live captain agent (the calling agent).
46
+ * @param team - the team record (read-only here).
47
+ * @param member - the member draft whose `id` is filled on success.
48
+ * @param stateDir - configured state directory (for the persona).
49
+ * @param signal - caller cancellation, forwarded to the start.
50
+ */
51
+ export declare function spawnMember(ctx: Context, config: MemberRuntimeConfig, captain: Agent, team: TeamState, member: TeamMember, stateDir: string, signal: AbortSignal): Promise<void>;
52
+ /**
53
+ * Deliver one message to a member as its next FIFO turn. Best effort: a
54
+ * failure (member gone or not continuable) is logged and reported as `false`
55
+ * so the caller can decide (mailbox delivery still happened).
56
+ *
57
+ * Any team sender can route through this helper: the captain is the direct
58
+ * parent of every member, and the caller passes the captain's live Agent
59
+ * (its own when the captain calls, the registry-resolved one when a member
60
+ * sends) — mirroring the Claude Code mailbox model where the writer writes
61
+ * the target's inbox and the target picks it up on its own.
62
+ * @param ctx - the plugin context (injects `subagents`).
63
+ * @param captain - the exact live captain agent (the member's direct parent).
64
+ * @param childId - the member's durable child session id.
65
+ * @param text - the message content.
66
+ * @param signal - caller cancellation, forwarded to the delivery.
67
+ * @returns whether the member inbox accepted the message.
68
+ */
69
+ export declare function deliverToMember(ctx: Context, captain: Agent, childId: string, text: string, signal: AbortSignal): Promise<boolean>;
70
+ /**
71
+ * Request cancellation of one live member's current turn. Best effort, fire
72
+ * and return; the target may keep running until it observes the signal.
73
+ * @param ctx - the plugin context (injects `subagents`).
74
+ * @param captain - the exact live captain agent (the member's parent).
75
+ * @param childId - the member's durable child session id.
76
+ */
77
+ export declare function interruptMember(ctx: Context, captain: Agent, childId: string): void;
78
+ /**
79
+ * Snapshot each direct continuable child's activity under the captain's
80
+ * session, keyed by child session id. A member that is currently running its
81
+ * turn reports `running`; an idle member reports `inactive`.
82
+ * @param ctx - the plugin context (injects `subagents`).
83
+ * @param captainSessionId - the captain's session id.
84
+ * @returns child id → activity, missing entries are unknown children.
85
+ */
86
+ export declare function memberActivity(ctx: Context, captainSessionId: string): Promise<Map<string, 'running' | 'inactive'>>;
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Team activity snapshot assembly for the activity panel.
3
+ *
4
+ * Server-side assembly mirrors the Claude Code desktop teamWatcher: read the
5
+ * durable team files (the truth source) and enrich with live subagent
6
+ * activity, so the panel always reflects the on-disk state even when a model
7
+ * skipped a tool "ritual" (e.g. not calling update_task on completion).
8
+ * @module dsh-agent-teams/snapshot
9
+ */
10
+ import type { Context } from '@deepseek-ai/cordis';
11
+ import type { TeamState } from './types.ts';
12
+ /** Visual task state for the activity panel. */
13
+ export type VisualTaskState = 'blocked' | 'open' | 'running' | 'completed';
14
+ /** One member row of the activity snapshot. */
15
+ export interface TeamActivityMember {
16
+ readonly id: string;
17
+ readonly name: string;
18
+ readonly role: string;
19
+ readonly activity: 'working' | 'idle' | 'unknown';
20
+ readonly progress: number;
21
+ readonly done: number;
22
+ readonly total: number;
23
+ readonly currentTask: string;
24
+ readonly unread: number;
25
+ }
26
+ /** One task row of the activity snapshot. */
27
+ export interface TeamActivityTask {
28
+ readonly id: string;
29
+ readonly subject: string;
30
+ readonly status: string;
31
+ readonly state: VisualTaskState;
32
+ readonly assignee: string;
33
+ readonly dependencies: readonly string[];
34
+ readonly depth: number;
35
+ }
36
+ /** One captain-inbox preview row. */
37
+ export interface TeamActivityMessage {
38
+ readonly from: string;
39
+ readonly content: string;
40
+ }
41
+ /** The full panel payload for one team. */
42
+ export interface TeamActivitySnapshot {
43
+ readonly workspace: string;
44
+ readonly teamId: string;
45
+ readonly name: string;
46
+ readonly description?: string;
47
+ readonly captainSessionId: string;
48
+ readonly members: readonly TeamActivityMember[];
49
+ readonly tasks: readonly TeamActivityTask[];
50
+ readonly messageCount: number;
51
+ readonly captainInbox: readonly TeamActivityMessage[];
52
+ }
53
+ /**
54
+ * Assemble one team snapshot from its durable files plus live activity.
55
+ * @param ctx - the plugin context (injects `subagents`, used for activity).
56
+ * @param stateRoot - resolved absolute state root of the owning workspace.
57
+ * @param workspace - display name of the owning workspace.
58
+ * @param state - the durable team record.
59
+ * @returns the panel snapshot.
60
+ */
61
+ export declare function assembleTeamSnapshot(ctx: Context, stateRoot: string, workspace: string, state: TeamState): Promise<TeamActivitySnapshot>;
62
+ /**
63
+ * Collect every team under the given workspace state roots.
64
+ * @param ctx - the plugin context.
65
+ * @param roots - `{ workspace, stateRoot }` pairs (resolved absolute roots).
66
+ * @returns the snapshots in stable order (workspace, then team id).
67
+ */
68
+ export declare function collectTeamsActivity(ctx: Context, roots: readonly {
69
+ workspace: string;
70
+ stateRoot: string;
71
+ }[]): Promise<TeamActivitySnapshot[]>;
72
+ /**
73
+ * Collect every archived team under the given workspace state roots (the
74
+ * `archive/` subdirectory of each state root). Used by the historic panel
75
+ * path to restore full team detail after deletion.
76
+ * @param ctx - the plugin context.
77
+ * @param roots - `{ workspace, stateRoot }` pairs.
78
+ * @returns the archived snapshots in stable order.
79
+ */
80
+ export declare function collectArchivedTeamsActivity(ctx: Context, roots: readonly {
81
+ workspace: string;
82
+ stateRoot: string;
83
+ }[]): Promise<TeamActivitySnapshot[]>;