@nanmicoder/dsh-agent-teams 0.1.5 → 0.1.6
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/README.md +6 -5
- package/README_ZH.md +6 -5
- package/lib/client/ActivityPanel.js +93 -38
- package/lib/client/activity-model.js +63 -0
- package/lib/client.js +478 -367
- package/lib/client.js.map +1 -1
- package/lib/index.js +6 -4
- package/lib/members.js +73 -10
- package/lib/scheduler.js +212 -0
- package/lib/snapshot.js +32 -19
- package/lib/state.js +174 -3
- package/lib/tools.js +287 -29
- package/lib/types/client/ActivityPanel.d.ts +1 -0
- package/lib/types/client/activity-model.d.ts +34 -0
- package/lib/types/event-types.d.ts +2 -0
- package/lib/types/members.d.ts +17 -4
- package/lib/types/scheduler.d.ts +23 -0
- package/lib/types/snapshot.d.ts +10 -2
- package/lib/types/state.d.ts +24 -0
- package/lib/types/types.d.ts +15 -1
- package/package.json +2 -2
package/lib/types/members.d.ts
CHANGED
|
@@ -115,11 +115,24 @@ export declare function deliverToMember(ctx: Context, captain: Agent, childId: s
|
|
|
115
115
|
*/
|
|
116
116
|
export declare function interruptMember(ctx: Context, captain: Agent, childId: string): void;
|
|
117
117
|
/**
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
118
|
+
* Install the missing per-child retirement boundary above Harness rc.6.
|
|
119
|
+
*
|
|
120
|
+
* Upstream `interrupt()` deliberately preserves continuable sessions and the
|
|
121
|
+
* upstream seam exposes no targeted forget/retire method. The durable
|
|
122
|
+
* AgentTeams index therefore guards all three public continuation boundaries:
|
|
123
|
+
* retired rows disappear from `list_agents` (children and descendants), and a
|
|
124
|
+
* direct `followup()` is rejected before it can cold-resume the member. Exact
|
|
125
|
+
* ids keep unrelated subagents untouched; transcripts remain in persistence
|
|
126
|
+
* for archived-team review.
|
|
127
|
+
*/
|
|
128
|
+
export declare function installRetiredMemberGuard(ctx: Context, stateDir: string): void;
|
|
129
|
+
/**
|
|
130
|
+
* Snapshot each direct continuable child's real driver activity under the
|
|
131
|
+
* captain's session. `listChildren().activity` is only session residency, so
|
|
132
|
+
* live children are refined through the Agent registry exactly like Harness's
|
|
133
|
+
* shipped `list_agents` tool.
|
|
121
134
|
* @param ctx - the plugin context (injects `subagents`).
|
|
122
135
|
* @param captainSessionId - the captain's session id.
|
|
123
136
|
* @returns child id → activity, missing entries are unknown children.
|
|
124
137
|
*/
|
|
125
|
-
export declare function memberActivity(ctx: Context, captainSessionId: string): Promise<Map<string, 'running' | '
|
|
138
|
+
export declare function memberActivity(ctx: Context, captainSessionId: string): Promise<Map<string, 'running' | 'idle' | 'ready'>>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event-driven shared task scheduler.
|
|
3
|
+
*
|
|
4
|
+
* Claude Code teammates keep polling the shared task list after a turn. DSH
|
|
5
|
+
* continuable agents instead expose explicit idle/running edges, so this
|
|
6
|
+
* scheduler closes the same loop without keeping a polling turn alive: every
|
|
7
|
+
* idle edge and every task-graph mutation attempts one atomic claim and wakes
|
|
8
|
+
* the selected durable member.
|
|
9
|
+
* @module dsh-agent-teams/scheduler
|
|
10
|
+
*/
|
|
11
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
12
|
+
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
13
|
+
export interface SchedulerConfig {
|
|
14
|
+
readonly stateDir: string;
|
|
15
|
+
}
|
|
16
|
+
export interface TeamScheduler {
|
|
17
|
+
/** Try to give every genuinely idle/ready member one unit of ready work. */
|
|
18
|
+
kickTeam(workspace: string, teamId: string, captain?: Agent): Promise<void>;
|
|
19
|
+
/** Try to flush fallback mail or give one member one ready task. */
|
|
20
|
+
kickMember(workspace: string, teamId: string, memberName: string, captain?: Agent): Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
/** Install one scheduler and its member activity observer. */
|
|
23
|
+
export declare function installTeamScheduler(ctx: Context, config: SchedulerConfig): TeamScheduler;
|
package/lib/types/snapshot.d.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* @module dsh-agent-teams/snapshot
|
|
9
9
|
*/
|
|
10
10
|
import type { Context } from '@deepseek-ai/cordis';
|
|
11
|
-
import type { TeamState } from './types.ts';
|
|
11
|
+
import type { MemberStatus, TeamState } from './types.ts';
|
|
12
12
|
/** Visual task state for the activity panel. */
|
|
13
13
|
export type VisualTaskState = 'blocked' | 'open' | 'running' | 'completed';
|
|
14
14
|
/** One member row of the activity snapshot. */
|
|
@@ -16,6 +16,7 @@ export interface TeamActivityMember {
|
|
|
16
16
|
readonly id: string;
|
|
17
17
|
readonly name: string;
|
|
18
18
|
readonly role: string;
|
|
19
|
+
readonly status: MemberStatus;
|
|
19
20
|
readonly activity: 'working' | 'idle' | 'unknown';
|
|
20
21
|
readonly progress: number;
|
|
21
22
|
readonly done: number;
|
|
@@ -50,6 +51,13 @@ export interface TeamActivitySnapshot {
|
|
|
50
51
|
readonly messageCount: number;
|
|
51
52
|
readonly captainInbox: readonly TeamActivityMessage[];
|
|
52
53
|
}
|
|
54
|
+
/** Snapshot projection switches for live and archived teams. */
|
|
55
|
+
export interface TeamSnapshotOptions {
|
|
56
|
+
/** Historic review must retain members that were marked removed at shutdown. */
|
|
57
|
+
readonly includeRemoved?: boolean;
|
|
58
|
+
/** Archived teams have no meaningful live activity after their sessions stop. */
|
|
59
|
+
readonly historic?: boolean;
|
|
60
|
+
}
|
|
53
61
|
/**
|
|
54
62
|
* Assemble one team snapshot from its durable files plus live activity.
|
|
55
63
|
* @param ctx - the plugin context (injects `subagents`, used for activity).
|
|
@@ -58,7 +66,7 @@ export interface TeamActivitySnapshot {
|
|
|
58
66
|
* @param state - the durable team record.
|
|
59
67
|
* @returns the panel snapshot.
|
|
60
68
|
*/
|
|
61
|
-
export declare function assembleTeamSnapshot(ctx: Context, stateRoot: string, workspace: string, state: TeamState): Promise<TeamActivitySnapshot>;
|
|
69
|
+
export declare function assembleTeamSnapshot(ctx: Context, stateRoot: string, workspace: string, state: TeamState, options?: TeamSnapshotOptions): Promise<TeamActivitySnapshot>;
|
|
62
70
|
/**
|
|
63
71
|
* Collect every team under the given workspace state roots.
|
|
64
72
|
* @param ctx - the plugin context.
|
package/lib/types/state.d.ts
CHANGED
|
@@ -61,6 +61,15 @@ export declare const TASK_TRANSITIONS: Readonly<Record<TaskStatus, readonly Task
|
|
|
61
61
|
* @returns the transition error, or undefined when allowed.
|
|
62
62
|
*/
|
|
63
63
|
export declare function transitionError(current: TaskStatus, next: TaskStatus): string | undefined;
|
|
64
|
+
/** Activate the task's current generation for one owner and return its capability id. */
|
|
65
|
+
export declare function activateTaskAttempt(task: TeamTask, assignee: string): string;
|
|
66
|
+
/** Start a fresh task generation for one owner. */
|
|
67
|
+
export declare function beginTaskAttempt(task: TeamTask, assignee: string): string;
|
|
68
|
+
/**
|
|
69
|
+
* Revoke the current worker immediately. Clearing its capability makes old
|
|
70
|
+
* updates stale; a separate handoff generation serializes async quiescence.
|
|
71
|
+
*/
|
|
72
|
+
export declare function invalidateTaskAttempt(task: TeamTask, nextAssignee?: string, reassigning?: boolean): void;
|
|
64
73
|
/**
|
|
65
74
|
* Create the team directory structure and the initial team record.
|
|
66
75
|
* @param stateRoot - resolved absolute state root directory.
|
|
@@ -89,6 +98,10 @@ export declare function readTeamSync(stateRoot: string, teamId: string): TeamSta
|
|
|
89
98
|
* @param state - the record to persist.
|
|
90
99
|
*/
|
|
91
100
|
export declare function writeTeam(stateRoot: string, state: TeamState): Promise<void>;
|
|
101
|
+
/** Read the durable set of member session ids retired by remove/delete. */
|
|
102
|
+
export declare function readRetiredMemberIds(stateRoot: string): Promise<Set<string>>;
|
|
103
|
+
/** Atomically add session ids to the durable retired-member deny-list. */
|
|
104
|
+
export declare function recordRetiredMemberIds(stateRoot: string, memberIds: readonly string[]): Promise<void>;
|
|
92
105
|
/**
|
|
93
106
|
* Find the team owned by one captain session (at most one per captain).
|
|
94
107
|
* @param stateRoot - resolved absolute state root directory.
|
|
@@ -125,6 +138,17 @@ export declare function appendMailbox(stateRoot: string, teamId: string, agentKe
|
|
|
125
138
|
* @returns the messages, empty when the mailbox does not exist yet.
|
|
126
139
|
*/
|
|
127
140
|
export declare function readMailbox(stateRoot: string, teamId: string, agentKey: string, onMalformedLine?: (lineNumber: number, error: unknown) => void): Promise<TeamMessage[]>;
|
|
141
|
+
/** Read only messages that have not been acknowledged by their recipient. */
|
|
142
|
+
export declare function readUnreadMailbox(stateRoot: string, teamId: string, agentKey: string, onMalformedLine?: (lineNumber: number, error: unknown) => void): Promise<TeamMessage[]>;
|
|
143
|
+
/** Lease selected fallback messages to one delivery path. */
|
|
144
|
+
export declare function claimMailboxDelivery(stateRoot: string, teamId: string, agentKey: string, messageIds: readonly string[]): Promise<void>;
|
|
145
|
+
/** Release a failed delivery lease so the scheduler can retry it later. */
|
|
146
|
+
export declare function releaseMailboxDelivery(stateRoot: string, teamId: string, agentKey: string, messageIds: readonly string[]): Promise<void>;
|
|
147
|
+
/**
|
|
148
|
+
* Mark selected durable mailbox records delivered/read while preserving
|
|
149
|
+
* malformed lines for diagnostics. Callers serialize this with the team lock.
|
|
150
|
+
*/
|
|
151
|
+
export declare function acknowledgeMailbox(stateRoot: string, teamId: string, agentKey: string, messageIds: readonly string[]): Promise<void>;
|
|
128
152
|
/**
|
|
129
153
|
* Remove a team's whole directory (members should be interrupted first).
|
|
130
154
|
* @param stateRoot - resolved absolute state root directory.
|
package/lib/types/types.d.ts
CHANGED
|
@@ -20,12 +20,20 @@ export interface TeamTask {
|
|
|
20
20
|
/** What needs to be done. */
|
|
21
21
|
description?: string;
|
|
22
22
|
status: TaskStatus;
|
|
23
|
-
/** Member name the task is assigned to; unassigned tasks await a claim. */
|
|
23
|
+
/** Member name (or `captain`) the task is assigned to; unassigned tasks await a claim. */
|
|
24
24
|
assignee?: string;
|
|
25
25
|
/** Task ids that must reach `completed` before this task can be claimed. */
|
|
26
26
|
dependencies: string[];
|
|
27
27
|
/** The worker's written result, set when the task completes or fails. */
|
|
28
28
|
output?: string;
|
|
29
|
+
/** Monotonic execution generation. Reassignment/retry invalidates every older attempt. */
|
|
30
|
+
attempt?: number;
|
|
31
|
+
/** Capability for the current claimed/in-progress attempt. Members must present it when updating. */
|
|
32
|
+
attemptId?: string;
|
|
33
|
+
/** Opaque generation for a revocation/handoff that has not started its next attempt yet. */
|
|
34
|
+
handoffId?: string;
|
|
35
|
+
/** A handoff is quiescing the old owner; the scheduler must not dispatch it yet. */
|
|
36
|
+
reassigning?: boolean;
|
|
29
37
|
createdAt: number;
|
|
30
38
|
updatedAt: number;
|
|
31
39
|
}
|
|
@@ -57,6 +65,12 @@ export interface TeamMessage {
|
|
|
57
65
|
to: string;
|
|
58
66
|
content: string;
|
|
59
67
|
ts: number;
|
|
68
|
+
/** Process-local delivery lease; prevents fallback and direct delivery racing. */
|
|
69
|
+
deliveryClaimedAt?: number;
|
|
70
|
+
/** Set after the durable message was accepted by the recipient's live Harness inbox. */
|
|
71
|
+
deliveredAt?: number;
|
|
72
|
+
/** Set once the recipient has consumed or been shown the durable fallback. */
|
|
73
|
+
readAt?: number;
|
|
60
74
|
}
|
|
61
75
|
/** The full durable team record. */
|
|
62
76
|
export interface TeamState {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nanmicoder/dsh-agent-teams",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
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",
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.client.json --noEmit",
|
|
83
83
|
"sync:skill": "node scripts/sync-skill.mjs",
|
|
84
84
|
"verify:skill": "node scripts/sync-skill.mjs --check",
|
|
85
|
-
"verify": "node scripts/verify.mjs && pnpm verify:skill",
|
|
85
|
+
"verify": "node scripts/verify.mjs && node scripts/lifecycle-verify.mjs && node scripts/stress-verify.mjs && pnpm verify:skill",
|
|
86
86
|
"prepublishOnly": "pnpm build && pnpm verify"
|
|
87
87
|
},
|
|
88
88
|
"peerDependencies": {
|