@nanmicoder/dsh-agent-teams 0.1.2 → 0.1.4
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 +91 -50
- package/README_ZH.md +134 -0
- package/assets/readme/hero.svg +73 -0
- package/lib/client.js +95 -95
- package/lib/index.js +2 -2
- package/lib/members.js +152 -5
- package/lib/state.js +28 -0
- package/lib/tools.js +35 -9
- package/lib/types/members.d.ts +43 -4
- package/lib/types/state.d.ts +10 -0
- package/lib/types/types.d.ts +5 -1
- package/package.json +37 -21
package/lib/tools.js
CHANGED
|
@@ -13,7 +13,7 @@ import { defineTool } from '@deepseek-ai/dsh-tools';
|
|
|
13
13
|
import { join } from 'node:path';
|
|
14
14
|
import { appendTeamEvent, captainSessionOf } from "./events.js";
|
|
15
15
|
import { appendMailbox, archiveTeamDir, CAPTAIN_KEY, createMessage, createTeamDir, findTeamByCaptain, findTeamByParticipant, readMailbox, readTeam, sanitizeKey, transitionError, unsatisfiedDependencies, withTeamLock, writeTeam, } from "./state.js";
|
|
16
|
-
import { deliverToMember, interruptMember, memberActivity, spawnMember, } from "./members.js";
|
|
16
|
+
import { deliverToMember, installMemberSelectionRuntime, interruptMember, memberActivity, resolveMemberLlmSelection, spawnMember, } from "./members.js";
|
|
17
17
|
/** The caller agent, or a loud failure for non-agent callers. */
|
|
18
18
|
function requireCaptain(exec) {
|
|
19
19
|
if (!exec.agent) {
|
|
@@ -126,6 +126,7 @@ export function steerCaptainReport(captain, from, content) {
|
|
|
126
126
|
* @param config - resolved tool config.
|
|
127
127
|
*/
|
|
128
128
|
export function registerAgentTeamsTools(ctx, config) {
|
|
129
|
+
const memberSelections = installMemberSelectionRuntime(ctx, config.stateDir);
|
|
129
130
|
ctx.tools.register(defineTool({
|
|
130
131
|
name: 'agent_teams_create',
|
|
131
132
|
description: 'Create a new AgentTeams team: you (the calling agent) become the captain. A captain leads one team at a time; create tasks and members afterwards with agent_teams_add_member and agent_teams_create_task.',
|
|
@@ -191,11 +192,12 @@ export function registerAgentTeamsTools(ctx, config) {
|
|
|
191
192
|
}));
|
|
192
193
|
ctx.tools.register(defineTool({
|
|
193
194
|
name: 'agent_teams_add_member',
|
|
194
|
-
description: 'Add a member
|
|
195
|
+
description: 'Add a durable continuable member. By default it snapshots the captain\'s current LLM provider, model, and reasoning effort with no user prompt. Supply provider/model only for an explicitly requested role-specific route. The member waits for messages, works on assigned tasks, and can message the team.',
|
|
195
196
|
parameters: {
|
|
196
197
|
name: { type: 'string', required: true, description: 'Unique member name inside the team.' },
|
|
197
198
|
role: { type: 'string', description: 'Role of the member (e.g. researcher, engineer, reviewer).' },
|
|
198
|
-
|
|
199
|
+
provider: { type: 'string', description: 'Optional LLM provider route. Use only when the user explicitly requests a different provider; requires model.' },
|
|
200
|
+
model: { type: 'string', description: 'Optional model override. Omit for the captain\'s current model (or the configured memberModel default).' },
|
|
199
201
|
},
|
|
200
202
|
output: {
|
|
201
203
|
schema: {
|
|
@@ -204,12 +206,15 @@ export function registerAgentTeamsTools(ctx, config) {
|
|
|
204
206
|
properties: {
|
|
205
207
|
member_name: { type: 'string', required: true },
|
|
206
208
|
member_id: { type: 'string', required: true },
|
|
209
|
+
provider: { type: 'string', required: true },
|
|
210
|
+
model: { type: 'string', required: true },
|
|
211
|
+
reasoning_effort: { type: 'string' },
|
|
207
212
|
status: { type: 'string', required: true },
|
|
208
213
|
},
|
|
209
214
|
},
|
|
210
215
|
render: (args, value) => [{
|
|
211
216
|
type: 'text',
|
|
212
|
-
text: `Member "${value.member_name}" added (subagent id ${value.member_id}, status ${value.status}).`,
|
|
217
|
+
text: `Member "${value.member_name}" added (subagent id ${value.member_id}, ${value.provider}/${value.model}${value.reasoning_effort === undefined ? '' : `, reasoning ${value.reasoning_effort}`}, status ${value.status}).`,
|
|
213
218
|
}],
|
|
214
219
|
},
|
|
215
220
|
async execute(args, exec) {
|
|
@@ -232,15 +237,22 @@ export function registerAgentTeamsTools(ctx, config) {
|
|
|
232
237
|
if (fresh.members.filter((candidate) => candidate.status !== 'removed').length >= config.maxMembers) {
|
|
233
238
|
throw new Error(`team "${fresh.name}" is at its member cap (${config.maxMembers})`);
|
|
234
239
|
}
|
|
240
|
+
const selection = await resolveMemberLlmSelection(ctx, captain, {
|
|
241
|
+
provider: args.provider,
|
|
242
|
+
model: args.model,
|
|
243
|
+
defaultModel: config.memberModel,
|
|
244
|
+
}, exec.signal);
|
|
235
245
|
const member = {
|
|
236
246
|
id: '',
|
|
237
247
|
name: memberName,
|
|
238
248
|
role: args.role,
|
|
239
|
-
|
|
249
|
+
provider: selection.provider,
|
|
250
|
+
model: selection.model,
|
|
251
|
+
reasoningEffort: selection.reasoningEffort,
|
|
240
252
|
joinedAt: Date.now(),
|
|
241
253
|
status: 'idle',
|
|
242
254
|
};
|
|
243
|
-
await spawnMember(ctx, memberRuntime(config), captain, fresh, member, config.stateDir, exec.signal);
|
|
255
|
+
await spawnMember(ctx, memberRuntime(config), memberSelections, selection, captain, fresh, member, config.stateDir, exec.signal);
|
|
244
256
|
fresh.members.push(member);
|
|
245
257
|
await writeTeam(stateRoot, fresh);
|
|
246
258
|
appendTeamEvent(ctx, captainSessionOf(ctx, fresh.captainSessionId, captain.session), 'agent-teams/member-added', {
|
|
@@ -249,7 +261,16 @@ export function registerAgentTeamsTools(ctx, config) {
|
|
|
249
261
|
name: member.name,
|
|
250
262
|
...member.role !== undefined ? { role: member.role } : {},
|
|
251
263
|
});
|
|
252
|
-
return {
|
|
264
|
+
return {
|
|
265
|
+
member_name: member.name,
|
|
266
|
+
member_id: member.id,
|
|
267
|
+
provider: selection.provider,
|
|
268
|
+
model: selection.model,
|
|
269
|
+
...selection.reasoningEffort === undefined
|
|
270
|
+
? {}
|
|
271
|
+
: { reasoning_effort: selection.reasoningEffort },
|
|
272
|
+
status: member.status,
|
|
273
|
+
};
|
|
253
274
|
});
|
|
254
275
|
},
|
|
255
276
|
}));
|
|
@@ -620,7 +641,9 @@ export function registerAgentTeamsTools(ctx, config) {
|
|
|
620
641
|
.map((member) => ({
|
|
621
642
|
name: member.name,
|
|
622
643
|
role: member.role ?? '',
|
|
644
|
+
provider: member.provider ?? '',
|
|
623
645
|
model: member.model ?? '',
|
|
646
|
+
reasoning_effort: member.reasoningEffort ?? '',
|
|
624
647
|
status: member.status,
|
|
625
648
|
activity: member.id !== '' ? (activity.get(member.id) ?? 'unknown') : 'unspawned',
|
|
626
649
|
}));
|
|
@@ -718,7 +741,6 @@ export function registerAgentTeamsTools(ctx, config) {
|
|
|
718
741
|
function memberRuntime(config) {
|
|
719
742
|
return {
|
|
720
743
|
provider: config.memberProvider,
|
|
721
|
-
model: config.memberModel,
|
|
722
744
|
maxDepth: config.memberMaxDepth,
|
|
723
745
|
};
|
|
724
746
|
}
|
|
@@ -729,7 +751,11 @@ function renderStatus(value) {
|
|
|
729
751
|
`Team "${team.team_name}"${team.description ? ` — ${team.description}` : ''}`,
|
|
730
752
|
`Viewing as: ${team.viewer}`,
|
|
731
753
|
`Members (${team.members.length}):`,
|
|
732
|
-
...team.members.map((member) =>
|
|
754
|
+
...team.members.map((member) => {
|
|
755
|
+
const route = member.provider && member.model ? ` · ${member.provider}/${member.model}` : '';
|
|
756
|
+
const effort = member.reasoning_effort ? ` · reasoning ${member.reasoning_effort}` : '';
|
|
757
|
+
return ` - ${member.name} [${member.role}] ${member.status}/${member.activity}${route}${effort}`;
|
|
758
|
+
}),
|
|
733
759
|
`Tasks (${team.tasks.length}):`,
|
|
734
760
|
...team.tasks.map((task) => {
|
|
735
761
|
const deps = task.dependencies.length > 0 ? ` (deps: ${task.dependencies.join(',')})` : '';
|
package/lib/types/members.d.ts
CHANGED
|
@@ -12,17 +12,54 @@
|
|
|
12
12
|
* @module dsh-agent-teams/members
|
|
13
13
|
*/
|
|
14
14
|
import type { Context } from '@deepseek-ai/cordis';
|
|
15
|
-
import type
|
|
15
|
+
import { type Agent } from '@deepseek-ai/dsh-agent';
|
|
16
16
|
import type { TeamMember, TeamState } from './types.ts';
|
|
17
17
|
/** Runtime knobs for member spawning, resolved from plugin config. */
|
|
18
18
|
export interface MemberRuntimeConfig {
|
|
19
19
|
/** Registered `ctx.subagents` provider name (must support continuable + persona). */
|
|
20
20
|
provider: string;
|
|
21
|
-
/** Optional model override applied to every member. */
|
|
22
|
-
model?: string;
|
|
23
21
|
/** Child delegation depth cap (0 forbids delegation entirely). */
|
|
24
22
|
maxDepth?: number;
|
|
25
23
|
}
|
|
24
|
+
/** Durable provider/model/reasoning snapshot for one member. */
|
|
25
|
+
export interface MemberLlmSelection {
|
|
26
|
+
/** Registered LLM provider route. */
|
|
27
|
+
provider: string;
|
|
28
|
+
/** Provider-owned model id. */
|
|
29
|
+
model: string;
|
|
30
|
+
/** Adapter-owned reasoning effort, absent when the target has no explicit/default effort. */
|
|
31
|
+
reasoningEffort?: string;
|
|
32
|
+
}
|
|
33
|
+
/** Optional member-level route requested by the captain. */
|
|
34
|
+
export interface MemberLlmSelectionRequest {
|
|
35
|
+
/** Explicit LLM provider route; requires an explicit model. */
|
|
36
|
+
provider?: string;
|
|
37
|
+
/** Explicit model id; otherwise the plugin default or captain model is used. */
|
|
38
|
+
model?: string;
|
|
39
|
+
/** Plugin-level member model default. */
|
|
40
|
+
defaultModel?: string;
|
|
41
|
+
}
|
|
42
|
+
/** Process-local bridge between spawn admission and synchronous child setup. */
|
|
43
|
+
export interface MemberSelectionRuntime {
|
|
44
|
+
/** Make one selection visible while Harness materializes the fresh child. */
|
|
45
|
+
withPending<T>(parentSessionId: string, label: string, selection: MemberLlmSelection, operation: () => Promise<T>): Promise<T>;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Resolve one member's complete model selection. Ordinary members snapshot the
|
|
49
|
+
* captain's current request route and reasoning effort. An explicit member
|
|
50
|
+
* provider/model or plugin-level model replaces only that route; the current
|
|
51
|
+
* captain effort remains the inherited policy and is validated against the
|
|
52
|
+
* target model before a child is created.
|
|
53
|
+
*/
|
|
54
|
+
export declare function resolveMemberLlmSelection(ctx: Context, captain: Agent, request: MemberLlmSelectionRequest, signal?: AbortSignal): Promise<MemberLlmSelection>;
|
|
55
|
+
/**
|
|
56
|
+
* Install the member selection bridge for every fresh or cold-resumed
|
|
57
|
+
* continuable child. Fresh creation reads the pending in-memory selection;
|
|
58
|
+
* cold resume restores the same selection from the owning team's durable
|
|
59
|
+
* record. Legacy members without a complete saved route retain Harness's
|
|
60
|
+
* descriptor provider/model behavior.
|
|
61
|
+
*/
|
|
62
|
+
export declare function installMemberSelectionRuntime(ctx: Context, stateDir: string): MemberSelectionRuntime;
|
|
26
63
|
/**
|
|
27
64
|
* The member's system prompt (persona), shadowing the deployment persona for
|
|
28
65
|
* that child. Self-contained: it replaces the whole persona section.
|
|
@@ -42,13 +79,15 @@ export declare function memberWelcome(team: TeamState): string;
|
|
|
42
79
|
* `member.id` with its child session id. On failure nothing is persisted.
|
|
43
80
|
* @param ctx - the plugin context (injects `subagents`).
|
|
44
81
|
* @param config - member runtime knobs.
|
|
82
|
+
* @param selections - fresh/cold child model-selection bridge.
|
|
83
|
+
* @param llmSelection - resolved provider/model/reasoning snapshot.
|
|
45
84
|
* @param captain - the exact live captain agent (the calling agent).
|
|
46
85
|
* @param team - the team record (read-only here).
|
|
47
86
|
* @param member - the member draft whose `id` is filled on success.
|
|
48
87
|
* @param stateDir - configured state directory (for the persona).
|
|
49
88
|
* @param signal - caller cancellation, forwarded to the start.
|
|
50
89
|
*/
|
|
51
|
-
export declare function spawnMember(ctx: Context, config: MemberRuntimeConfig, captain: Agent, team: TeamState, member: TeamMember, stateDir: string, signal: AbortSignal): Promise<void>;
|
|
90
|
+
export declare function spawnMember(ctx: Context, config: MemberRuntimeConfig, selections: MemberSelectionRuntime, llmSelection: MemberLlmSelection, captain: Agent, team: TeamState, member: TeamMember, stateDir: string, signal: AbortSignal): Promise<void>;
|
|
52
91
|
/**
|
|
53
92
|
* Deliver one message to a member as its next FIFO turn. Best effort: a
|
|
54
93
|
* failure (member gone or not continuable) is logged and reported as `false`
|
package/lib/types/state.d.ts
CHANGED
|
@@ -73,6 +73,16 @@ export declare function createTeamDir(stateRoot: string, state: TeamState): Prom
|
|
|
73
73
|
* @param teamId - the team's sanitized id.
|
|
74
74
|
*/
|
|
75
75
|
export declare function readTeam(stateRoot: string, teamId: string): Promise<TeamState | undefined>;
|
|
76
|
+
/**
|
|
77
|
+
* Synchronously read one team record while a continuable child is being
|
|
78
|
+
* composed. Harness requires child setup contributions to be synchronous;
|
|
79
|
+
* this narrow boundary lets a cold-resumed member restore its durable model
|
|
80
|
+
* selection before its first request can be published.
|
|
81
|
+
* @param stateRoot - resolved absolute state root directory.
|
|
82
|
+
* @param teamId - the team's sanitized id.
|
|
83
|
+
* @returns the team record, or `undefined` when absent.
|
|
84
|
+
*/
|
|
85
|
+
export declare function readTeamSync(stateRoot: string, teamId: string): TeamState | undefined;
|
|
76
86
|
/**
|
|
77
87
|
* Persist one team record (inside the caller's lock).
|
|
78
88
|
* @param stateRoot - resolved absolute state root directory.
|
package/lib/types/types.d.ts
CHANGED
|
@@ -39,8 +39,12 @@ export interface TeamMember {
|
|
|
39
39
|
name: string;
|
|
40
40
|
/** Role description, e.g. `researcher`, `engineer`, `reviewer`. */
|
|
41
41
|
role?: string;
|
|
42
|
-
/**
|
|
42
|
+
/** Resolved LLM provider route captured when this member was created. */
|
|
43
|
+
provider?: string;
|
|
44
|
+
/** Resolved model captured when this member was created. */
|
|
43
45
|
model?: string;
|
|
46
|
+
/** Resolved reasoning effort captured from the captain's current session. */
|
|
47
|
+
reasoningEffort?: string;
|
|
44
48
|
joinedAt: number;
|
|
45
49
|
status: MemberStatus;
|
|
46
50
|
}
|
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.4",
|
|
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",
|
|
@@ -20,8 +20,10 @@
|
|
|
20
20
|
"files": [
|
|
21
21
|
"lib",
|
|
22
22
|
"assets/agent-teams",
|
|
23
|
+
"assets/readme",
|
|
23
24
|
"cordis.patch.yml",
|
|
24
|
-
"README.md"
|
|
25
|
+
"README.md",
|
|
26
|
+
"README_ZH.md"
|
|
25
27
|
],
|
|
26
28
|
"license": "MIT",
|
|
27
29
|
"author": {
|
|
@@ -83,30 +85,44 @@
|
|
|
83
85
|
"verify": "node scripts/verify.mjs && pnpm verify:skill",
|
|
84
86
|
"prepublishOnly": "pnpm build && pnpm verify"
|
|
85
87
|
},
|
|
86
|
-
"dependencies": {},
|
|
87
88
|
"peerDependencies": {
|
|
88
89
|
"@deepseek-ai/cordis": "^4.0.1-rc.1",
|
|
89
|
-
"@deepseek-ai/dsh-agent": "^0.0
|
|
90
|
-
"@deepseek-ai/dsh-client-locale": "^0.0
|
|
91
|
-
"@deepseek-ai/dsh-client-runtime": "^0.0
|
|
92
|
-
"@deepseek-ai/dsh-client-ui-conversation": "^0.0
|
|
93
|
-
"@deepseek-ai/dsh-client-ui-primitives": "^0.0
|
|
94
|
-
"@deepseek-ai/dsh-client-ui-slots": "^0.0
|
|
95
|
-
"@deepseek-ai/dsh-llm": "^0.0
|
|
96
|
-
"@deepseek-ai/dsh-session": "^0.0
|
|
97
|
-
"@deepseek-ai/dsh-subagent": "^0.0
|
|
98
|
-
"@deepseek-ai/dsh-system-prompt": "^0.0
|
|
99
|
-
"@deepseek-ai/dsh-tools": "^0.0
|
|
100
|
-
"
|
|
101
|
-
"
|
|
90
|
+
"@deepseek-ai/dsh-agent": "^0.1.0-rc.6",
|
|
91
|
+
"@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6",
|
|
92
|
+
"@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6",
|
|
93
|
+
"@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.6",
|
|
94
|
+
"@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6",
|
|
95
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6",
|
|
96
|
+
"@deepseek-ai/dsh-llm": "^0.1.0-rc.6",
|
|
97
|
+
"@deepseek-ai/dsh-session": "^0.1.0-rc.6",
|
|
98
|
+
"@deepseek-ai/dsh-subagent": "^0.1.0-rc.6",
|
|
99
|
+
"@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6",
|
|
100
|
+
"@deepseek-ai/dsh-tools": "^0.1.0-rc.6",
|
|
101
|
+
"@deepseek-ai/schemastery": "^3.18.1-rc.1",
|
|
102
|
+
"react": "^18.2.0"
|
|
102
103
|
},
|
|
103
104
|
"devDependencies": {
|
|
105
|
+
"@deepseek-ai/cordis": "^4.0.1",
|
|
106
|
+
"@deepseek-ai/dsh-agent": "0.1.0-rc.6",
|
|
107
|
+
"@deepseek-ai/dsh-client-locale": "0.1.0-rc.6",
|
|
108
|
+
"@deepseek-ai/dsh-client-runtime": "0.1.0-rc.6",
|
|
109
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.1.0-rc.6",
|
|
110
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.1.0-rc.6",
|
|
111
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.1.0-rc.6",
|
|
112
|
+
"@deepseek-ai/dsh-llm": "0.1.0-rc.6",
|
|
113
|
+
"@deepseek-ai/dsh-session": "0.1.0-rc.6",
|
|
114
|
+
"@deepseek-ai/dsh-subagent": "0.1.0-rc.6",
|
|
115
|
+
"@deepseek-ai/dsh-system-prompt": "0.1.0-rc.6",
|
|
116
|
+
"@deepseek-ai/dsh-tools": "0.1.0-rc.6",
|
|
117
|
+
"@deepseek-ai/dsh-workspace": "0.1.0-rc.6",
|
|
118
|
+
"@deepseek-ai/schemastery": "^3.18.1",
|
|
119
|
+
"@types/node": "^24.13.3",
|
|
104
120
|
"@types/react": "~18.3.1",
|
|
105
|
-
"@types/react-dom": "^
|
|
121
|
+
"@types/react-dom": "^18.3.7",
|
|
106
122
|
"lightningcss": "^1.33.0",
|
|
107
|
-
"tsdown": "0.22.2",
|
|
108
|
-
"typescript": "^5.9.3",
|
|
109
123
|
"react": "^18.2.0",
|
|
110
|
-
"react-dom": "^18.2.0"
|
|
124
|
+
"react-dom": "^18.2.0",
|
|
125
|
+
"tsdown": "0.22.2",
|
|
126
|
+
"typescript": "^5.9.3"
|
|
111
127
|
}
|
|
112
|
-
}
|
|
128
|
+
}
|