@nanmicoder/dsh-agent-teams 0.1.9 → 0.1.11

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.
package/lib/members.js CHANGED
@@ -318,44 +318,22 @@ export function interruptMember(ctx, captain, childId) {
318
318
  ctx.logger.warn(`agent-teams: interrupt of member ${childId} failed: ${String(error)}`);
319
319
  }
320
320
  }
321
- /** Resolve one live parent's workspace-scoped retirement index. */
322
- async function retiredForParent(ctx, parentId, stateDir) {
323
- const parent = ctx.agents.get(parentId);
324
- return parent === undefined
325
- ? new Set()
326
- : readRetiredMemberIds(join(parent.session.header.cwd ?? process.cwd(), stateDir));
327
- }
328
321
  /**
329
322
  * Install the missing per-child retirement boundary above Harness rc.6.
330
323
  *
331
324
  * Upstream `interrupt()` deliberately preserves continuable sessions and the
332
325
  * upstream seam exposes no targeted forget/retire method. The durable
333
- * AgentTeams index therefore guards all three public continuation boundaries:
334
- * retired rows disappear from `list_agents` (children and descendants), and a
335
- * direct `followup()` is rejected before it can cold-resume the member. Exact
336
- * ids keep unrelated subagents untouched; transcripts remain in persistence
337
- * for archived-team review.
326
+ * AgentTeams index therefore rejects `followup()` before it can cold-resume a
327
+ * retired member. Catalog rows deliberately remain discoverable: Harness rc.8
328
+ * uses the direct-child catalog to authorize historical transcript reads and
329
+ * `openSubagent()`, so filtering those rows would make an archived member's
330
+ * persisted conversation inaccessible. Exact ids keep unrelated subagents
331
+ * untouched while the followup boundary still prevents further model turns.
338
332
  */
339
333
  export function installRetiredMemberGuard(ctx, stateDir) {
340
334
  const runtime = ctx.subagents;
341
335
  ctx.effect(() => {
342
- const listChildren = runtime.listChildren;
343
- const listDescendants = runtime.listDescendants;
344
336
  const followup = runtime.followup;
345
- const guardedChildren = async (parentId, signal) => {
346
- const [entries, retired] = await Promise.all([
347
- listChildren.call(runtime, parentId, signal),
348
- retiredForParent(ctx, parentId, stateDir),
349
- ]);
350
- return entries.filter(entry => !retired.has(entry.id));
351
- };
352
- const guardedDescendants = async (rootId, signal) => {
353
- const [entries, retired] = await Promise.all([
354
- listDescendants.call(runtime, rootId, signal),
355
- retiredForParent(ctx, rootId, stateDir),
356
- ]);
357
- return entries.filter(entry => !retired.has(entry.id));
358
- };
359
337
  const guardedFollowup = async (parent, childId, content, options) => {
360
338
  const retired = await readRetiredMemberIds(join(parent.session.header.cwd ?? process.cwd(), stateDir));
361
339
  if (retired.has(childId)) {
@@ -363,36 +341,32 @@ export function installRetiredMemberGuard(ctx, stateDir) {
363
341
  }
364
342
  return followup.call(runtime, parent, childId, content, options);
365
343
  };
366
- runtime.listChildren = guardedChildren;
367
- runtime.listDescendants = guardedDescendants;
368
344
  runtime.followup = guardedFollowup;
369
345
  return () => {
370
- if (runtime.listChildren === guardedChildren)
371
- runtime.listChildren = listChildren;
372
- if (runtime.listDescendants === guardedDescendants)
373
- runtime.listDescendants = listDescendants;
374
346
  if (runtime.followup === guardedFollowup)
375
347
  runtime.followup = followup;
376
348
  };
377
349
  }, 'agent-teams: retired member guard');
378
350
  }
379
351
  /**
380
- * Snapshot each direct continuable child's real driver activity under the
381
- * captain's session. `listChildren().activity` is only session residency, so
382
- * live children are refined through the Agent registry exactly like Harness's
383
- * shipped `list_agents` tool.
384
- * @param ctx - the plugin context (injects `subagents`).
385
- * @param captainSessionId - the captain's session id.
386
- * @returns child id → activity, missing entries are unknown children.
352
+ * Snapshot the real driver activity for durable member ids.
353
+ *
354
+ * The team record is the membership authority, so this path intentionally no
355
+ * longer depends on `listChildren()`'s versioned projection shape. Harness
356
+ * rc.8 changed those rows to branded `SessionId` values plus residency-only
357
+ * `activity`; neither is needed to answer whether the live Agent driver is
358
+ * running, idle, or absent/ready.
359
+ * @param ctx - the plugin context (injects `agents`).
360
+ * @param memberIds - child ids restored from the durable team record.
361
+ * @returns child id → live activity.
387
362
  */
388
- export async function memberActivity(ctx, captainSessionId) {
389
- const entries = await ctx.subagents.listChildren(brandedSessionId(captainSessionId));
363
+ export function memberActivity(ctx, memberIds) {
390
364
  const activity = new Map();
391
- for (const entry of entries) {
392
- if (entry.kind !== 'child')
365
+ for (const id of memberIds) {
366
+ if (id === '')
393
367
  continue;
394
- const live = ctx.agents.get(entry.id);
395
- activity.set(entry.id, live === undefined ? 'ready' : live.status);
368
+ const live = ctx.agents.get(brandedSessionId(id));
369
+ activity.set(id, live === undefined ? 'ready' : live.status);
396
370
  }
397
371
  return activity;
398
372
  }
package/lib/snapshot.js CHANGED
@@ -9,6 +9,7 @@
9
9
  */
10
10
  import { readdir } from 'node:fs/promises';
11
11
  import { join } from 'node:path';
12
+ import { memberActivity } from "./members.js";
12
13
  import { CAPTAIN_KEY, listArchivedTeamIds, readArchivedTeam, readUnreadMailbox, readTeam, taskDepthsById, taskVisualState, } from "./state.js";
13
14
  /** The current task of a member: its first unfinished owned task. */
14
15
  function currentTaskOf(memberName, tasks) {
@@ -32,21 +33,9 @@ export async function assembleTeamSnapshot(ctx, stateRoot, workspace, state, opt
32
33
  const roster = options.includeRemoved === true
33
34
  ? state.members
34
35
  : state.members.filter((member) => member.status !== 'removed');
35
- const activity = new Map();
36
- if (options.historic !== true) {
37
- try {
38
- const children = await ctx.subagents.listChildren(state.captainSessionId);
39
- for (const entry of children) {
40
- if (entry.kind === 'child') {
41
- const live = ctx.agents.get(entry.id);
42
- activity.set(entry.id, live === undefined ? 'ready' : live.status);
43
- }
44
- }
45
- }
46
- catch (error) {
47
- ctx.logger.warn(`agent-teams: activity listing failed for ${state.name}: ${String(error)}`);
48
- }
49
- }
36
+ const activity = options.historic === true
37
+ ? new Map()
38
+ : memberActivity(ctx, roster.map((member) => member.id));
50
39
  const unreadByMember = new Map();
51
40
  for (const member of roster) {
52
41
  try {
package/lib/tools.js CHANGED
@@ -871,7 +871,7 @@ export function registerAgentTeamsTools(ctx, config) {
871
871
  await scheduler.kickTeam(workspace, located.id, caller);
872
872
  }
873
873
  const { team, identity } = await withTeamLock(teamLockKey(stateRoot, located.id), () => requireFreshParticipant(stateRoot, located.id, caller.id));
874
- const activity = await memberActivity(ctx, team.captainSessionId);
874
+ const activity = memberActivity(ctx, team.members.map((member) => member.id));
875
875
  const members = team.members
876
876
  .filter((member) => member.status !== 'removed')
877
877
  .map((member) => ({
@@ -1,17 +1,19 @@
1
1
  /**
2
2
  * AgentTeams activity panel: the top-right floater monitoring every team.
3
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
4
+ * Modeled on the Claude Code desktop SessionActivityPanel: a shell-overlay
5
+ * panel that docks at the conversation's top-right edge by default, can be
6
+ * dragged into a floating window, resized, and folded into an activity badge.
7
+ * On wide viewports the docked panel makes the conversation column yield
8
+ * space; narrow viewports keep a simple inset overlay. It
7
9
  * polls the host `/plugins/dsh-agent-teams/state` route for
8
10
  * server-side snapshots (durable files + live subagent activity), with a
9
11
  * collapsed badge that auto-expands once when activity appears. Archived
10
12
  * teams stay available for the owning conversation after live work ends.
11
13
  *
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.
14
+ * The floater mounts in ui-layout's additive `shell.overlay`; it is not a
15
+ * conversation node — the in-conversation panel was removed in favor of this
16
+ * always-available monitor.
15
17
  * @module dsh-agent-teams/client/activity
16
18
  */
17
19
  import type { SessionId } from '@deepseek-ai/dsh-session/types';
@@ -19,7 +21,7 @@ import type { ObservableSnapshot, SessionListState } from '@deepseek-ai/dsh-clie
19
21
  /** The top-right activity floater. Teams follow the current session: live
20
22
  * snapshots and historic card summaries are only shown while their captain
21
23
  * session is the one currently open. */
22
- export declare function ActivityPanel({ sessionsList, openSession }: {
24
+ export declare function ActivityPanel({ sessionsList, openMember }: {
23
25
  readonly sessionsList: ObservableSnapshot<SessionListState>;
24
- readonly openSession: (id: SessionId) => void;
26
+ readonly openMember: (parentId: SessionId, childId: SessionId) => void;
25
27
  }): import("react").JSX.Element | null;
@@ -15,9 +15,9 @@ import type { SessionId } from '@deepseek-ai/dsh-session/types';
15
15
  export declare const OPEN_PANEL_EVENT = "agent-teams:open-panel";
16
16
  /** Navigation action injected from the plugin's own SessionsService access. */
17
17
  export interface AgentTeamsCardInjected {
18
- readonly openSession: (id: SessionId) => void;
18
+ readonly openMember: (parentId: SessionId, childId: SessionId) => void;
19
19
  }
20
20
  /** Complete keyed Chat renderer props. */
21
21
  export type AgentTeamsCardProps = PropsRuntime<'conversation.chat.node', 'agent-teams'> & PropsLocale<'agentTeams'> & AgentTeamsCardInjected;
22
22
  /** Render one durable team as a compact conversation card. */
23
- export declare function AgentTeamsCard({ node, openSession, sessionId }: AgentTeamsCardProps): import("react").JSX.Element;
23
+ export declare function AgentTeamsCard({ node, openMember, sessionId }: AgentTeamsCardProps): import("react").JSX.Element;
@@ -39,10 +39,10 @@ export declare function usesParallelTaskGrid<T extends RelationshipTask>(tasks:
39
39
  /**
40
40
  * Whether an expanded activity panel still belongs to the current session.
41
41
  *
42
- * The panel is mounted through a body portal, so React does not remount it
43
- * when the conversation route changes. Ownership keeps an expanded panel
44
- * from leaking onto the new-session screen (or another conversation) while
45
- * its local open state is being reset.
42
+ * The panel is mounted in the root-scoped shell overlay, so React does not
43
+ * remount it when the conversation route changes. Ownership keeps an expanded
44
+ * panel from leaking onto the new-session screen (or another conversation)
45
+ * while its local open state is being reset.
46
46
  */
47
47
  export declare function activityPanelExpandedForSession(open: boolean, owner: string | undefined, current: string | undefined): boolean;
48
48
  /**
@@ -79,6 +79,12 @@ interface ActivityFetchResponse {
79
79
  }
80
80
  /** Injectable browser primitives used by the poll controller and its tests. */
81
81
  export interface ActivityPollingRuntime {
82
+ /**
83
+ * Current captain session to discover after a cold client/host restart.
84
+ * This one-time scope restores teams whose older conversation log has no
85
+ * AgentTeams card capable of registering an explicit monitor target.
86
+ */
87
+ readonly discoverySessionId?: string;
82
88
  readonly fetchState?: (url: string, init: {
83
89
  readonly cache: 'no-store';
84
90
  readonly signal: AbortSignal;
@@ -98,9 +104,13 @@ export interface ActivityPollingController {
98
104
  /**
99
105
  * Start the single polling loop for the current session's requested targets.
100
106
  *
101
- * With no targets this is deliberately inert: installing the plugin must not
102
- * touch the state route. Live state is polled at the normal cadence; archive
103
- * state is fetched only as a one-time fallback for targets no longer live.
107
+ * With neither targets nor a discovery session this is deliberately inert.
108
+ * A discovery session performs one live+archive pass after selection/restart;
109
+ * it keeps polling only while that captain still owns a live team. This
110
+ * restores legacy/cardless history without turning every ordinary session
111
+ * into a permanent one-second filesystem scan. Explicit card targets retain
112
+ * the normal cadence, and archive state is refreshed when a target or a
113
+ * previously discovered live team disappears.
104
114
  */
105
115
  export declare function startActivityPolling(monitorTargets: readonly ActivityMonitorTarget[], runtime?: ActivityPollingRuntime): ActivityPollingController;
106
116
  export {};
@@ -3,9 +3,8 @@ import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';
3
3
  /** Required services: conversation nodes, slots, and sessions navigation. */
4
4
  export declare const inject: string[];
5
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.
6
+ * Register the activity monitor in the shell's additive overlay and the
7
+ * in-conversation team card. The card's activity button re-opens a folded
8
+ * monitor via a window event — the recovery path for an old session.
10
9
  */
11
10
  export declare function apply(ctx: ClientContext): void;
@@ -0,0 +1,49 @@
1
+ /** Pure persisted geometry rules for the AgentTeams shell-overlay panel. */
2
+ export type PanelMode = 'docked' | 'floating';
3
+ export type PanelHeightMode = 'auto' | 'manual';
4
+ export type PanelResizeEdge = 'left' | 'bottom' | 'corner';
5
+ /** User-owned panel state persisted between browser sessions. */
6
+ export interface PanelLayout {
7
+ readonly mode: PanelMode;
8
+ readonly x: number;
9
+ readonly y: number;
10
+ readonly width: number;
11
+ readonly height: number;
12
+ readonly heightMode: PanelHeightMode;
13
+ }
14
+ /** The shell-overlay box and the right edge of its current conversation. */
15
+ export interface PanelBounds {
16
+ readonly width: number;
17
+ readonly height: number;
18
+ readonly anchorRight: number;
19
+ }
20
+ export declare const PANEL_LAYOUT_STORAGE_KEY = "dsh-agent-teams:activity-panel:v1";
21
+ export declare const PANEL_COMPACT_BREAKPOINT = 960;
22
+ export declare const PANEL_DEFAULT_WIDTH = 388;
23
+ export declare const PANEL_DEFAULT_HEIGHT = 640;
24
+ export declare const PANEL_MIN_WIDTH = 320;
25
+ export declare const PANEL_MAX_WIDTH = 640;
26
+ export declare const PANEL_MIN_HEIGHT = 360;
27
+ export declare const PANEL_DOCK_TOP = 64;
28
+ export declare const PANEL_DOCK_RIGHT = 18;
29
+ export declare const PANEL_DOCK_BOTTOM = 48;
30
+ export declare const PANEL_FLOAT_MARGIN = 12;
31
+ export declare const DEFAULT_PANEL_LAYOUT: PanelLayout;
32
+ /** Decode one versioned localStorage value, rejecting partial/corrupt state. */
33
+ export declare function parsePanelLayout(value: string | null): PanelLayout;
34
+ /** Whether the panel should become a simple inset overlay with no gestures. */
35
+ export declare function compactPanelForBounds(bounds: PanelBounds): boolean;
36
+ /** Docked and compact panels always fit content; floating panels may be user-sized. */
37
+ export declare function panelUsesAutoHeight(layout: PanelLayout, bounds: PanelBounds): boolean;
38
+ /** CSS max-height ceiling that keeps an auto-height panel inside its shell. */
39
+ export declare function panelMaximumHeight(layout: PanelLayout, bounds: PanelBounds): number;
40
+ /** Resolve persisted state into a visible rectangle inside the current shell. */
41
+ export declare function resolvePanelGeometry(layout: PanelLayout, bounds: PanelBounds): PanelLayout;
42
+ /** Undock without a visual jump by adopting the panel's resolved rectangle. */
43
+ export declare function floatPanelLayout(geometry: PanelLayout, bounds: PanelBounds): PanelLayout;
44
+ /** Return to the right dock, preserving width and restoring content-fit height. */
45
+ export declare function dockPanelLayout(layout: PanelLayout, bounds: PanelBounds): PanelLayout;
46
+ /** Translate a floating panel and clamp it back into the visible shell. */
47
+ export declare function movePanelLayout(start: PanelLayout, dx: number, dy: number, bounds: PanelBounds): PanelLayout;
48
+ /** Resize while keeping the edge opposite the active handle stationary. */
49
+ export declare function resizePanelLayout(start: PanelLayout, edge: PanelResizeEdge, dx: number, dy: number, bounds: PanelBounds): PanelLayout;
@@ -0,0 +1,22 @@
1
+ /** Version-tolerant navigation into durable AgentTeams member transcripts. */
2
+ import type { SessionId, SubagentAddress } from '@deepseek-ai/dsh-client-runtime/client';
3
+ /** Narrow sessions-service face used by the activity panel and team card. */
4
+ export interface AgentTeamsSessionNavigator {
5
+ /** Legacy/ordinary session navigation. */
6
+ open(id: SessionId): void;
7
+ /** rc.8 addressed subagent navigation. */
8
+ openSubagent?(address: SubagentAddress): void;
9
+ /** Refresh the exact parent's durable direct-child catalog. */
10
+ refreshSubagents?(parentSessionId: SessionId): Promise<void>;
11
+ /** Reuse an address already retained by the client runtime when available. */
12
+ subagentAddress?(id: SessionId): SubagentAddress | undefined;
13
+ }
14
+ /**
15
+ * Open one member's persisted transcript.
16
+ *
17
+ * Harness rc.8 intentionally removed cold subagents from the ordinary session
18
+ * list. They must first be rediscovered in their parent's catalog, then opened
19
+ * with the exact parent/child/mode address. Older runtimes have only `open()`;
20
+ * the fallback preserves the plugin's rc.6 peer range.
21
+ */
22
+ export declare function openAgentTeamMember(sessions: AgentTeamsSessionNavigator, parentSessionId: SessionId, childSessionId: SessionId): Promise<'subagent' | 'session'>;
@@ -8,18 +8,16 @@
8
8
  * `/agent-teams` command. The web GUI's slash menu (the Harness
9
9
  * `ui-commands` client) lists it from the host catalog with the input
10
10
  * hint; the argued line is claimed client-side and executed through
11
- * `command.execute` WITHOUT ever reaching the model. The handler queues
12
- * one explicit activation message as an ordinary follow-up turn
13
- * (`agent.followup`), so the captain protocol starts deterministically
14
- * no "use AgentTeams" phrasing required.
11
+ * `command.execute`. The handler replays that exact line as an ordinary
12
+ * user follow-up (`agent.followup`) so it remains visible in the chat; the
13
+ * gesture boundary then adds the deterministic activation message.
15
14
  * 2. **Gesture boundary** — a `agent/pre-step` listener recognizes a leading
16
15
  * `/agent-teams` token in genuine user messages and injects the same
17
16
  * activation message. This covers surfaces with no command adjudication
18
- * (headless CLI, API, pasted text in plain composers) and is a no-op for
19
- * the command path, whose line is consumed before it can become a prompt.
20
- * Mid-sentence mentions stay ordinary prose; only `source.kind === 'user'`
21
- * messages are scanned, so injected or external text cannot forge the
22
- * gesture.
17
+ * (headless CLI, API, pasted text in plain composers) and also handles the
18
+ * exact user line replayed by the host command. Mid-sentence mentions stay
19
+ * ordinary prose; only `source.kind === 'user'` messages are scanned, so
20
+ * injected or external text cannot forge the gesture.
23
21
  *
24
22
  * @module dsh-agent-teams/command
25
23
  */
@@ -30,8 +28,8 @@ export declare const AGENT_TEAMS_COMMAND = "agent-teams";
30
28
  declare module '@deepseek-ai/dsh-llm' {
31
29
  interface MessageSourceMap {
32
30
  /**
33
- * A deterministic `/agent-teams` activation: the goal the user supplied,
34
- * delivered as an ordinary follow-up turn instead of the raw slash line.
31
+ * A deterministic `/agent-teams` activation injected after the visible
32
+ * user-authored slash line.
35
33
  */
36
34
  'agent-teams-command': {
37
35
  readonly kind: 'agent-teams-command';
@@ -55,10 +53,11 @@ export declare function buildActivationDirective(goal: string): string;
55
53
  export declare function invokedAgentTeamsGoal(messages: readonly UserMessage[]): string | undefined;
56
54
  /**
57
55
  * Register the closed-namespace `/agent-teams` host command. The handler
58
- * runs against the receiving agent without sending the slash line to the
59
- * model: it queues the activation message as an ordinary follow-up turn and
60
- * wakes the driver. The registration rides the calling context's fiber, so
61
- * a disposed scope (HMR, plugin removal) unregisters the command.
56
+ * preserves the exact submitted slash line as an ordinary user follow-up;
57
+ * the pre-step gesture boundary injects the activation directive and wakes
58
+ * the captain deterministically. The registration rides the calling
59
+ * context's fiber, so a disposed scope (HMR, plugin removal) unregisters the
60
+ * command.
62
61
  * @param ctx - host context providing the `commands` registry.
63
62
  */
64
63
  export declare function registerAgentTeamsCommand(ctx: Context): void;
@@ -123,20 +123,24 @@ export declare function interruptMember(ctx: Context, captain: Agent, childId: s
123
123
  *
124
124
  * Upstream `interrupt()` deliberately preserves continuable sessions and the
125
125
  * upstream seam exposes no targeted forget/retire method. The durable
126
- * AgentTeams index therefore guards all three public continuation boundaries:
127
- * retired rows disappear from `list_agents` (children and descendants), and a
128
- * direct `followup()` is rejected before it can cold-resume the member. Exact
129
- * ids keep unrelated subagents untouched; transcripts remain in persistence
130
- * for archived-team review.
126
+ * AgentTeams index therefore rejects `followup()` before it can cold-resume a
127
+ * retired member. Catalog rows deliberately remain discoverable: Harness rc.8
128
+ * uses the direct-child catalog to authorize historical transcript reads and
129
+ * `openSubagent()`, so filtering those rows would make an archived member's
130
+ * persisted conversation inaccessible. Exact ids keep unrelated subagents
131
+ * untouched while the followup boundary still prevents further model turns.
131
132
  */
132
133
  export declare function installRetiredMemberGuard(ctx: Context, stateDir: string): void;
133
134
  /**
134
- * Snapshot each direct continuable child's real driver activity under the
135
- * captain's session. `listChildren().activity` is only session residency, so
136
- * live children are refined through the Agent registry exactly like Harness's
137
- * shipped `list_agents` tool.
138
- * @param ctx - the plugin context (injects `subagents`).
139
- * @param captainSessionId - the captain's session id.
140
- * @returns child id → activity, missing entries are unknown children.
135
+ * Snapshot the real driver activity for durable member ids.
136
+ *
137
+ * The team record is the membership authority, so this path intentionally no
138
+ * longer depends on `listChildren()`'s versioned projection shape. Harness
139
+ * rc.8 changed those rows to branded `SessionId` values plus residency-only
140
+ * `activity`; neither is needed to answer whether the live Agent driver is
141
+ * running, idle, or absent/ready.
142
+ * @param ctx - the plugin context (injects `agents`).
143
+ * @param memberIds - child ids restored from the durable team record.
144
+ * @returns child id → live activity.
141
145
  */
142
- export declare function memberActivity(ctx: Context, captainSessionId: string): Promise<Map<string, 'running' | 'idle' | 'ready'>>;
146
+ export declare function memberActivity(ctx: Context, memberIds: readonly string[]): Map<string, 'running' | 'idle' | 'ready'>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nanmicoder/dsh-agent-teams",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "AgentTeams for DeepSeek Harness: multi-agent team collaboration (captain, members, tasks with dependencies, messaging) driven by natural language, with a tree monitor in the web GUI",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -21,7 +21,9 @@
21
21
  "lib",
22
22
  "assets/agent-teams",
23
23
  "assets/readme",
24
+ "assets/ui.png",
24
25
  "cordis.patch.yml",
26
+ "release-notes",
25
27
  "README.md",
26
28
  "README_ZH.md"
27
29
  ],
@@ -64,19 +66,12 @@
64
66
  "inject": [
65
67
  "@deepseek-ai/dsh-client-locale",
66
68
  "@deepseek-ai/dsh-client-runtime",
67
- "@deepseek-ai/dsh-client-ui-conversation"
69
+ "@deepseek-ai/dsh-client-ui-conversation",
70
+ "@deepseek-ai/dsh-client-ui-layout"
68
71
  ],
69
72
  "platform": "web"
70
73
  }
71
74
  },
72
- "dshClient": {
73
- "inject": [
74
- "@deepseek-ai/dsh-client-locale",
75
- "@deepseek-ai/dsh-client-runtime",
76
- "@deepseek-ai/dsh-client-ui-conversation"
77
- ],
78
- "platform": "web"
79
- },
80
75
  "scripts": {
81
76
  "build": "tsc -p tsconfig.json && tsc -p tsconfig.client.json && tsdown",
82
77
  "typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.client.json --noEmit",
@@ -91,6 +86,7 @@
91
86
  "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6",
92
87
  "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6",
93
88
  "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.6",
89
+ "@deepseek-ai/dsh-client-ui-layout": "^0.1.0-rc.6",
94
90
  "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6",
95
91
  "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6",
96
92
  "@deepseek-ai/dsh-commands": "^0.1.0-rc.6",
@@ -118,6 +114,9 @@
118
114
  "@deepseek-ai/dsh-client-ui-conversation": {
119
115
  "optional": true
120
116
  },
117
+ "@deepseek-ai/dsh-client-ui-layout": {
118
+ "optional": true
119
+ },
121
120
  "@deepseek-ai/dsh-client-ui-primitives": {
122
121
  "optional": true
123
122
  },
@@ -151,19 +150,20 @@
151
150
  },
152
151
  "devDependencies": {
153
152
  "@deepseek-ai/cordis": "^4.0.1",
154
- "@deepseek-ai/dsh-agent": "0.1.0-rc.6",
155
- "@deepseek-ai/dsh-client-locale": "0.1.0-rc.6",
156
- "@deepseek-ai/dsh-client-runtime": "0.1.0-rc.6",
157
- "@deepseek-ai/dsh-client-ui-conversation": "0.1.0-rc.6",
158
- "@deepseek-ai/dsh-client-ui-primitives": "0.1.0-rc.6",
159
- "@deepseek-ai/dsh-client-ui-slots": "0.1.0-rc.6",
160
- "@deepseek-ai/dsh-commands": "0.1.0-rc.6",
161
- "@deepseek-ai/dsh-llm": "0.1.0-rc.6",
162
- "@deepseek-ai/dsh-session": "0.1.0-rc.6",
163
- "@deepseek-ai/dsh-subagent": "0.1.0-rc.6",
164
- "@deepseek-ai/dsh-system-prompt": "0.1.0-rc.6",
165
- "@deepseek-ai/dsh-tools": "0.1.0-rc.6",
166
- "@deepseek-ai/dsh-workspace": "0.1.0-rc.6",
153
+ "@deepseek-ai/dsh-agent": "0.1.0-rc.8",
154
+ "@deepseek-ai/dsh-client-locale": "0.1.0-rc.8",
155
+ "@deepseek-ai/dsh-client-runtime": "0.1.0-rc.8",
156
+ "@deepseek-ai/dsh-client-ui-conversation": "0.1.0-rc.8",
157
+ "@deepseek-ai/dsh-client-ui-layout": "0.1.0-rc.8",
158
+ "@deepseek-ai/dsh-client-ui-primitives": "0.1.0-rc.8",
159
+ "@deepseek-ai/dsh-client-ui-slots": "0.1.0-rc.8",
160
+ "@deepseek-ai/dsh-commands": "0.1.0-rc.8",
161
+ "@deepseek-ai/dsh-llm": "0.1.0-rc.8",
162
+ "@deepseek-ai/dsh-session": "0.1.0-rc.8",
163
+ "@deepseek-ai/dsh-subagent": "0.1.0-rc.8",
164
+ "@deepseek-ai/dsh-system-prompt": "0.1.0-rc.8",
165
+ "@deepseek-ai/dsh-tools": "0.1.0-rc.8",
166
+ "@deepseek-ai/dsh-workspace": "0.1.0-rc.8",
167
167
  "@deepseek-ai/schemastery": "^3.18.1",
168
168
  "@types/node": "^24.13.3",
169
169
  "@types/react": "~18.3.1",
@@ -0,0 +1,48 @@
1
+ # AgentTeams v0.1.10
2
+
3
+ This release makes the AgentTeams activity panel easier to place and size, fixes the `/agent-teams` conversation history, and gives the whale roles a cleaner visual treatment. It is tested against DeepSeek Harness `0.1.0-rc.8`.
4
+
5
+ ## New & Improved
6
+
7
+ - **Movable and resizable activity panel**: switch between docked and floating layouts, drag the floating panel by its header, and resize it from the supported edges and corner. Position, size, and dock mode persist across refreshes.
8
+ - **Content-aware height**: the panel grows with its content and only introduces internal scrolling after reaching the viewport safety limit, avoiding a large empty area for smaller teams.
9
+ - **Cleaner role portraits**: captain and member artwork now uses transparent, uncropped character silhouettes with clearer sizing, lighter state stickers, and a compact unread indicator.
10
+
11
+ ## Fixes
12
+
13
+ - Preserved the exact `/agent-teams ...` input as the normal user message in the main conversation.
14
+ - Kept command context injections below the user message in chronological order.
15
+ - Removed the duplicate slash-command result row while retaining the durable command events.
16
+
17
+ ## Installation
18
+
19
+ ```sh
20
+ dsh plugin --profile web add @nanmicoder/dsh-agent-teams
21
+ ```
22
+
23
+ <details>
24
+ <summary><b>中文版本 / Chinese Version</b></summary>
25
+
26
+ # AgentTeams v0.1.10
27
+
28
+ 本次更新重点改善 AgentTeams 活动面板的摆放与尺寸体验,修复 `/agent-teams` 在主会话中的消息展示,并重新整理鲸鱼角色头像的视觉层级。已基于 DeepSeek Harness `0.1.0-rc.8` 完成验证。
29
+
30
+ ## 新增与改进
31
+
32
+ - **活动面板支持移动和缩放**:可在停靠与浮动布局之间切换;浮动态可以拖动标题栏,并从支持的边缘和右下角调整尺寸。面板位置、尺寸和停靠模式会在刷新后恢复。
33
+ - **高度跟随内容**:面板先根据团队内容自然增长,达到视口安全上限后才启用内部滚动,小团队不再出现大块空白。
34
+ - **角色头像更清晰**:队长和成员改为透明、无裁切的完整角色剪影,统一头像尺寸,减轻状态贴纸,并使用更轻量的未读提示。
35
+
36
+ ## 修复
37
+
38
+ - 将用户输入的完整 `/agent-teams ...` 原文保留为主会话中的普通用户消息。
39
+ - 上下文注入按时间顺序显示在用户消息下方。
40
+ - 移除重复的 slash command 结果行,同时保留持久化命令事件。
41
+
42
+ ## 安装
43
+
44
+ ```sh
45
+ dsh plugin --profile web add @nanmicoder/dsh-agent-teams
46
+ ```
47
+
48
+ </details>
@@ -0,0 +1,52 @@
1
+ # AgentTeams v0.1.11
2
+
3
+ This release restores AgentTeams activity and member history after a DeepSeek Harness client or host restart. It fixes the rc.8 compatibility regressions reported in [#60](https://github.com/NanmiCoder/dsh-agent-teams/issues/60) and [#61](https://github.com/NanmiCoder/dsh-agent-teams/issues/61).
4
+
5
+ ## Fixes
6
+
7
+ - **Cold-start activity recovery**: selecting a captain session now performs a lightweight live and archived team discovery pass, so older sessions without an AgentTeams conversation card restore their activity panel after restart.
8
+ - **Reliable member activity**: live `running / idle / ready` state is resolved from the durable team roster and Agent registry instead of depending on the versioned `listChildren()` projection shape.
9
+ - **Persistent member history**: retired AgentTeams members remain discoverable in the Harness subagent catalog for transcript review while direct follow-up remains blocked.
10
+ - **rc.8 transcript navigation**: activity-panel and conversation-card member links refresh the parent catalog and use addressed `openSubagent()` navigation, with a fallback for older Harness runtimes.
11
+
12
+ ## Verification
13
+
14
+ - Reproduced the full captain/member/task/archive lifecycle in a real `/tmp` workspace on the Harness web client.
15
+ - Verified cold restart recovery without opening the built-in subagent catalog first.
16
+ - Verified archived member navigation and complete persisted task history.
17
+ - Passed type checking, production build, offline verification, lifecycle verification, and the eight-member complex stress suite.
18
+
19
+ ## Installation
20
+
21
+ ```sh
22
+ dsh plugin --profile web add @nanmicoder/dsh-agent-teams
23
+ ```
24
+
25
+ <details>
26
+ <summary><b>中文版本 / Chinese Version</b></summary>
27
+
28
+ # AgentTeams v0.1.11
29
+
30
+ 本次更新修复 DeepSeek Harness 客户端或 host 重启后 AgentTeams 活动面板与成员历史消失的问题,对应 [#60](https://github.com/NanmiCoder/dsh-agent-teams/issues/60) 和 [#61](https://github.com/NanmiCoder/dsh-agent-teams/issues/61) 中报告的 rc.8 兼容性回归。
31
+
32
+ ## 修复
33
+
34
+ - **冷启动活动恢复**:选择队长会话时会执行一次轻量的活动团队与历史归档发现;即使旧会话没有 AgentTeams 对话卡片,重启后也能恢复活动面板。
35
+ - **可靠的成员活动状态**:从持久化团队成员表和 Agent registry 解析真实的 `running / idle / ready`,不再依赖容易变化的 `listChildren()` 投影结构。
36
+ - **成员历史持续可见**:已退休的 AgentTeams 成员继续保留在 Harness 子代理目录中供历史记录查看,但直接 follow-up 仍会被拒绝。
37
+ - **rc.8 历史会话导航**:活动面板和对话卡片会先刷新父级目录,再通过带父子地址的 `openSubagent()` 打开成员记录;旧版 Harness 继续使用兼容回退。
38
+
39
+ ## 验证
40
+
41
+ - 在 Harness Web 客户端的真实 `/tmp` workspace 中完成队长、成员、任务和归档全流程复现。
42
+ - 验证未预先打开内置子代理目录时的冷重启恢复。
43
+ - 验证归档成员导航及完整持久化任务历史。
44
+ - 通过类型检查、生产构建、离线验证、生命周期验证及八成员复杂压力测试。
45
+
46
+ ## 安装
47
+
48
+ ```sh
49
+ dsh plugin --profile web add @nanmicoder/dsh-agent-teams
50
+ ```
51
+
52
+ </details>