@nanmicoder/dsh-agent-teams 0.1.11 → 0.1.13
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 +5 -3
- package/README_ZH.md +5 -3
- package/lib/client/ActivityPanel.js +76 -61
- package/lib/client/AgentTeamsCard.js +2 -2
- package/lib/client/activity-monitor.js +38 -13
- package/lib/client/index.js +7 -3
- package/lib/client/locales.js +165 -0
- package/lib/client.js +337 -127
- package/lib/client.js.map +1 -1
- package/lib/index.js +3 -3
- package/lib/scheduler.js +49 -11
- package/lib/types/client/ActivityPanel.d.ts +4 -2
- package/lib/types/client/AgentTeamsCard.d.ts +1 -1
- package/lib/types/client/activity-monitor.d.ts +18 -6
- package/lib/types/client/index.d.ts +8 -1
- package/lib/types/client/locales.d.ts +169 -0
- package/lib/types/scheduler.d.ts +4 -1
- package/package.json +1 -1
- package/release-notes/v0.1.12.md +54 -0
- package/release-notes/v0.1.13.md +60 -0
package/lib/index.js
CHANGED
|
@@ -44,9 +44,9 @@ function usageSectionText(toolNames) {
|
|
|
44
44
|
1. Call agent_teams_create with a team name and the goal as description. You become the captain and may lead one team at a time.
|
|
45
45
|
2. Call agent_teams_add_member once per role the goal needs (researcher, engineer, reviewer, ...). Members are durable subagents: they wait for your messages, then work a full turn. By default a member on your current provider/model snapshots your current reasoning effort; a member routed to a different provider or model automatically uses that target model's default effort. Never ask the user to choose these per member; only pass provider/model when the user explicitly requests a different route for that role, and reasoning_effort only when the user explicitly requests a particular effort ("default" explicitly selects the target model's default).
|
|
46
46
|
3. Break the goal into tasks with agent_teams_create_task and wire dependencies. Assign role-specific work when useful; unassigned ready work belongs to the shared pool. The scheduler automatically claims one ready task for each truly idle member and wakes it, including across later rounds.
|
|
47
|
-
4. Lead by delegation: monitor with agent_teams_status, send guidance with agent_teams_send_message, and let idle teammates execute ready work. Do not duplicate a teammate's work merely because its turn is slow.
|
|
48
|
-
5. If work
|
|
49
|
-
6. Tasks carry attempt_id capabilities. Members must use the current attempt_id for updates; stale-attempt errors mean ownership changed.
|
|
47
|
+
4. Lead by delegation: monitor with agent_teams_status, send guidance with agent_teams_send_message, and let idle teammates execute ready work. Do not duplicate a teammate's work merely because its turn is slow. If the user requires every member to contribute or report, create one task per required contribution (or message each member directly); never wait for an unassigned member to produce work it was never given.
|
|
48
|
+
5. If the user explicitly asks to pause a running member, its open attempt remains parked after interruption; after answering the user, send that same member guidance with agent_teams_send_message so it continues the same attempt. Do not interrupt members for an ordinary user question that did not request a pause. If work must change owner, restart from scratch, or be taken over, call agent_teams_reassign_task first. Reassign to another idle member, retry with the same member, or use assignee=captain before doing it yourself. Reassignment revokes the old attempt and waits for that member to quiesce, preventing late results from overwriting the new attempt.
|
|
49
|
+
6. Tasks carry attempt_id capabilities. Members must use the current attempt_id for updates; stale-attempt errors mean ownership changed. Check status after progress notifications until every required task is terminal and every member is idle/ready; do not busy-poll or require reports from members with no assigned work.
|
|
50
50
|
7. Present the team's results to the user, then agent_teams_delete the team unless the user wants to keep working with it.
|
|
51
51
|
|
|
52
52
|
Tools: ${toolNames}`;
|
package/lib/scheduler.js
CHANGED
|
@@ -5,7 +5,10 @@
|
|
|
5
5
|
* continuable agents instead expose explicit idle/running edges, so this
|
|
6
6
|
* scheduler closes the same loop without keeping a polling turn alive: every
|
|
7
7
|
* idle edge and every task-graph mutation attempts one atomic claim and wakes
|
|
8
|
-
* the selected durable member.
|
|
8
|
+
* the selected durable member. A resident member that becomes idle while it
|
|
9
|
+
* still owns an open attempt is parked: only an explicit captain reassignment
|
|
10
|
+
* may rotate that capability. Automatic retry is reserved for cold recovery,
|
|
11
|
+
* when the durable owner is no longer resident in the live Agent registry.
|
|
9
12
|
* @module dsh-agent-teams/scheduler
|
|
10
13
|
*/
|
|
11
14
|
import { join } from 'node:path';
|
|
@@ -22,8 +25,11 @@ function liveCaptain(ctx, captainSessionId, supplied) {
|
|
|
22
25
|
return supplied;
|
|
23
26
|
return ctx.agents.get(captainSessionId);
|
|
24
27
|
}
|
|
28
|
+
function liveMember(ctx, member) {
|
|
29
|
+
return ctx.agents.get(member.id);
|
|
30
|
+
}
|
|
25
31
|
function isMemberAvailable(ctx, member) {
|
|
26
|
-
const live = ctx
|
|
32
|
+
const live = liveMember(ctx, member);
|
|
27
33
|
return live === undefined || live.status === 'idle';
|
|
28
34
|
}
|
|
29
35
|
function ownedOpenTask(tasks, memberName) {
|
|
@@ -59,6 +65,13 @@ function fallbackMailboxPrompt(messages) {
|
|
|
59
65
|
/** Install one scheduler and its member activity observer. */
|
|
60
66
|
export function installTeamScheduler(ctx, config) {
|
|
61
67
|
const memberQueues = new Map();
|
|
68
|
+
// An idle edge in this process proves that the resident member ended its
|
|
69
|
+
// turn while the current attempt was still open. Remember that capability
|
|
70
|
+
// even after Harness disposes the continuable AgentHandle: later status or
|
|
71
|
+
// graph kicks must keep it parked. A cold process starts with an empty map,
|
|
72
|
+
// so durable open attempts are still recovered after restart.
|
|
73
|
+
const parkedAttempts = new Map();
|
|
74
|
+
const memberQueueKey = (stateRoot, teamId, memberName) => (`${stateRoot}\u0000${teamId}\u0000${memberName}`);
|
|
62
75
|
const serializeMember = async (key, operation) => {
|
|
63
76
|
const previous = memberQueues.get(key) ?? Promise.resolve();
|
|
64
77
|
let release;
|
|
@@ -92,7 +105,7 @@ export function installTeamScheduler(ctx, config) {
|
|
|
92
105
|
},
|
|
93
106
|
async kickMember(workspace, teamId, memberName, suppliedCaptain) {
|
|
94
107
|
const stateRoot = stateRootOf(workspace, config);
|
|
95
|
-
const queueKey =
|
|
108
|
+
const queueKey = memberQueueKey(stateRoot, teamId, memberName);
|
|
96
109
|
await serializeMember(queueKey, async () => {
|
|
97
110
|
let team = await readTeam(stateRoot, teamId);
|
|
98
111
|
if (team === undefined)
|
|
@@ -124,12 +137,20 @@ export function installTeamScheduler(ctx, config) {
|
|
|
124
137
|
const currentMember = fresh.members.find(candidate => candidate.name === memberName && candidate.status !== 'removed');
|
|
125
138
|
if (currentMember === undefined || currentMember.id === '' || !isMemberAvailable(ctx, currentMember))
|
|
126
139
|
return undefined;
|
|
127
|
-
|
|
128
|
-
//
|
|
129
|
-
//
|
|
130
|
-
//
|
|
131
|
-
|
|
132
|
-
|
|
140
|
+
const owned = ownedOpenTask(fresh.tasks, currentMember.name);
|
|
141
|
+
// A resident idle member can intentionally leave an attempt open
|
|
142
|
+
// while waiting for guidance, or because the user paused its turn.
|
|
143
|
+
// Re-dispatching here would revoke still-valid work on every idle
|
|
144
|
+
// edge and every status kick. The idle observer remembers that exact
|
|
145
|
+
// capability across normal continuable disposal; only an unobserved
|
|
146
|
+
// durable capability (cold process recovery) or a legacy open task
|
|
147
|
+
// with no capability is retried.
|
|
148
|
+
const parkedAttemptId = parkedAttempts.get(currentMember.id);
|
|
149
|
+
const recoverOwned = owned !== undefined
|
|
150
|
+
&& (owned.attemptId === undefined || owned.attemptId !== parkedAttemptId);
|
|
151
|
+
const task = recoverOwned ? owned : owned === undefined
|
|
152
|
+
? nextReadyTask(fresh.tasks, currentMember.name)
|
|
153
|
+
: undefined;
|
|
133
154
|
if (task === undefined) {
|
|
134
155
|
if (currentMember.status !== 'idle') {
|
|
135
156
|
currentMember.status = 'idle';
|
|
@@ -139,6 +160,7 @@ export function installTeamScheduler(ctx, config) {
|
|
|
139
160
|
}
|
|
140
161
|
const previousAssignee = task.assignee;
|
|
141
162
|
const attemptId = beginTaskAttempt(task, currentMember.name);
|
|
163
|
+
parkedAttempts.delete(currentMember.id);
|
|
142
164
|
currentMember.status = 'working';
|
|
143
165
|
await writeTeam(stateRoot, fresh);
|
|
144
166
|
return {
|
|
@@ -184,17 +206,33 @@ export function installTeamScheduler(ctx, config) {
|
|
|
184
206
|
const workspace = agent.session.header.cwd ?? process.cwd();
|
|
185
207
|
const stateRoot = stateRootOf(workspace, config);
|
|
186
208
|
const located = await findTeamByParticipant(stateRoot, agent.id);
|
|
187
|
-
if (located === undefined
|
|
209
|
+
if (located === undefined) {
|
|
210
|
+
parkedAttempts.delete(agent.id);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
if (located.captainSessionId === agent.id)
|
|
188
214
|
return;
|
|
189
215
|
const member = located.members.find(candidate => candidate.id === agent.id && candidate.status !== 'removed');
|
|
190
|
-
if (member === undefined)
|
|
216
|
+
if (member === undefined) {
|
|
217
|
+
parkedAttempts.delete(agent.id);
|
|
191
218
|
return;
|
|
219
|
+
}
|
|
192
220
|
await withTeamLock(teamLockKey(stateRoot, located.id), async () => {
|
|
193
221
|
const fresh = await readTeam(stateRoot, located.id);
|
|
194
222
|
const current = fresh?.members.find(candidate => candidate.id === agent.id && candidate.status !== 'removed');
|
|
195
223
|
if (fresh === undefined || current === undefined)
|
|
196
224
|
return;
|
|
197
225
|
const next = status === 'running' ? 'working' : 'idle';
|
|
226
|
+
if (next === 'idle') {
|
|
227
|
+
const owned = ownedOpenTask(fresh.tasks, current.name);
|
|
228
|
+
if (owned?.attemptId === undefined)
|
|
229
|
+
parkedAttempts.delete(agent.id);
|
|
230
|
+
else
|
|
231
|
+
parkedAttempts.set(agent.id, owned.attemptId);
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
parkedAttempts.delete(agent.id);
|
|
235
|
+
}
|
|
198
236
|
if (current.status === next)
|
|
199
237
|
return;
|
|
200
238
|
current.status = next;
|
|
@@ -16,12 +16,14 @@
|
|
|
16
16
|
* always-available monitor.
|
|
17
17
|
* @module dsh-agent-teams/client/activity
|
|
18
18
|
*/
|
|
19
|
+
import type { PropsLocale } from '@deepseek-ai/dsh-client-ui-slots';
|
|
19
20
|
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
20
21
|
import type { ObservableSnapshot, SessionListState } from '@deepseek-ai/dsh-client-runtime/client';
|
|
21
22
|
/** The top-right activity floater. Teams follow the current session: live
|
|
22
23
|
* snapshots and historic card summaries are only shown while their captain
|
|
23
24
|
* session is the one currently open. */
|
|
24
|
-
export
|
|
25
|
+
export type ActivityPanelProps = {
|
|
25
26
|
readonly sessionsList: ObservableSnapshot<SessionListState>;
|
|
26
27
|
readonly openMember: (parentId: SessionId, childId: SessionId) => void;
|
|
27
|
-
}
|
|
28
|
+
} & PropsLocale<'agentTeams'>;
|
|
29
|
+
export declare function ActivityPanel({ sessionsList, openMember, t }: ActivityPanelProps): import("react").JSX.Element | null;
|
|
@@ -20,4 +20,4 @@ export interface AgentTeamsCardInjected {
|
|
|
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, openMember, sessionId }: AgentTeamsCardProps): import("react").JSX.Element;
|
|
23
|
+
export declare function AgentTeamsCard({ node, openMember, sessionId, t }: AgentTeamsCardProps): import("react").JSX.Element;
|
|
@@ -71,6 +71,13 @@ export declare function getActivitySnapshotsSnapshot(): ActivitySnapshots;
|
|
|
71
71
|
export declare function updateActivitySnapshots(update: Partial<ActivitySnapshots>): void;
|
|
72
72
|
/** Poll cadence for the live host snapshot route. */
|
|
73
73
|
export declare const ACTIVITY_POLL_MS = 1000;
|
|
74
|
+
/**
|
|
75
|
+
* Low-frequency probe cadence while a cardless discovery session still owns
|
|
76
|
+
* no team. The probe keeps the panel able to pick up a team created later in
|
|
77
|
+
* that session (e.g. a run_code-wrapped agent_teams_create) without turning
|
|
78
|
+
* every ordinary session into a one-second filesystem scan.
|
|
79
|
+
*/
|
|
80
|
+
export declare const ACTIVITY_PROBE_MS = 5000;
|
|
74
81
|
/** Host route serving live and archived team snapshots. */
|
|
75
82
|
export declare const ACTIVITY_STATE_URL = "/plugins/dsh-agent-teams/state";
|
|
76
83
|
interface ActivityFetchResponse {
|
|
@@ -105,12 +112,17 @@ export interface ActivityPollingController {
|
|
|
105
112
|
* Start the single polling loop for the current session's requested targets.
|
|
106
113
|
*
|
|
107
114
|
* With neither targets nor a discovery session this is deliberately inert.
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
115
|
+
* Explicit card targets poll at the live cadence from the start. A discovery
|
|
116
|
+
* session performs an immediate live+archive restore pass, then — while it
|
|
117
|
+
* still owns no team — probes on a low-frequency cadence, so a team created
|
|
118
|
+
* later in that session (e.g. a run_code-wrapped agent_teams_create) is
|
|
119
|
+
* discovered without a manual reload, without turning every ordinary session
|
|
120
|
+
* into a one-second filesystem scan. The moment a team for the discovery
|
|
121
|
+
* session appears, the controller upgrades to the live one-second cadence for
|
|
122
|
+
* the rest of its lifetime. The caller — the session view, which stops the
|
|
123
|
+
* controller when the session is no longer current — bounds the lifetime, and
|
|
124
|
+
* archive state is refreshed when a target or a previously discovered live
|
|
125
|
+
* team disappears.
|
|
114
126
|
*/
|
|
115
127
|
export declare function startActivityPolling(monitorTargets: readonly ActivityMonitorTarget[], runtime?: ActivityPollingRuntime): ActivityPollingController;
|
|
116
128
|
export {};
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
/** Browser plugin for the AgentTeams activity floater and conversation card. */
|
|
2
2
|
import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';
|
|
3
|
-
|
|
3
|
+
import { type AgentTeamsLocaleKey } from './locales.ts';
|
|
4
|
+
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
5
|
+
interface LocaleNamespaceMap {
|
|
6
|
+
/** AgentTeams conversation card and activity monitor copy. */
|
|
7
|
+
agentTeams: AgentTeamsLocaleKey;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/** Required services: conversation nodes, slots, sessions navigation, and locale. */
|
|
4
11
|
export declare const inject: string[];
|
|
5
12
|
/**
|
|
6
13
|
* Register the activity monitor in the shell's additive overlay and the
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/** `agentTeams` namespace dictionaries for every plugin-owned Web surface. */
|
|
2
|
+
/** Dictionary namespace owned by the AgentTeams client plugin. */
|
|
3
|
+
export declare const AGENT_TEAMS_LOCALE_NAMESPACE = "agentTeams";
|
|
4
|
+
/** Simplified Chinese dictionary (the key-set source of truth). */
|
|
5
|
+
export declare const zh: {
|
|
6
|
+
'card.memberCount': string;
|
|
7
|
+
'action.openActivityPanel': string;
|
|
8
|
+
'activity.panelButton': string;
|
|
9
|
+
'activity.badgeAria': string;
|
|
10
|
+
'activity.panelAria': string;
|
|
11
|
+
'activity.title': string;
|
|
12
|
+
'activity.float': string;
|
|
13
|
+
'activity.dockRight': string;
|
|
14
|
+
'activity.collapse': string;
|
|
15
|
+
'activity.empty': string;
|
|
16
|
+
'format.listSeparator': string;
|
|
17
|
+
'task.status.pending': string;
|
|
18
|
+
'task.status.claimed': string;
|
|
19
|
+
'task.status.inProgress': string;
|
|
20
|
+
'task.status.completed': string;
|
|
21
|
+
'task.status.failed': string;
|
|
22
|
+
'task.status.cancelled': string;
|
|
23
|
+
'member.state.working': string;
|
|
24
|
+
'member.state.failed': string;
|
|
25
|
+
'member.state.waiting': string;
|
|
26
|
+
'member.state.delivered': string;
|
|
27
|
+
'member.state.left': string;
|
|
28
|
+
'member.state.removed': string;
|
|
29
|
+
'member.state.pending': string;
|
|
30
|
+
'member.state.unassigned': string;
|
|
31
|
+
'member.status.executing': string;
|
|
32
|
+
'member.status.working': string;
|
|
33
|
+
'member.status.waitingOn': string;
|
|
34
|
+
'member.status.waitingPrerequisite': string;
|
|
35
|
+
'member.status.waitingAssignment': string;
|
|
36
|
+
'member.status.delivered': string;
|
|
37
|
+
'member.status.idle': string;
|
|
38
|
+
'member.status.unknown': string;
|
|
39
|
+
'task.assignee.unclaimed': string;
|
|
40
|
+
'task.summary.waitingBreakdown': string;
|
|
41
|
+
'task.summary.allDelivered': string;
|
|
42
|
+
'task.summary.blockedAndRunning': string;
|
|
43
|
+
'task.summary.more': string;
|
|
44
|
+
'task.summary.running': string;
|
|
45
|
+
'task.summary.ready': string;
|
|
46
|
+
'task.summary.blocked': string;
|
|
47
|
+
'task.summary.waitingSchedule': string;
|
|
48
|
+
'progress.aria': string;
|
|
49
|
+
'progress.title': string;
|
|
50
|
+
'progress.running': string;
|
|
51
|
+
'progress.blocked': string;
|
|
52
|
+
'progress.delivered': string;
|
|
53
|
+
'dependency.aria': string;
|
|
54
|
+
'dependency.parallel': string;
|
|
55
|
+
'dependency.title': string;
|
|
56
|
+
'dependency.hint.parallel': string;
|
|
57
|
+
'dependency.hint.chain': string;
|
|
58
|
+
'dependency.hint.pinned': string;
|
|
59
|
+
'task.runningAria': string;
|
|
60
|
+
'task.detail.completed': string;
|
|
61
|
+
'task.detail.noPrerequisite': string;
|
|
62
|
+
'task.detail.ready': string;
|
|
63
|
+
'task.detail.waitingOn': string;
|
|
64
|
+
'task.detail.noDownstream': string;
|
|
65
|
+
'task.detail.unlocks': string;
|
|
66
|
+
'team.ended': string;
|
|
67
|
+
'team.stats.members': string;
|
|
68
|
+
'team.stats.completed': string;
|
|
69
|
+
'team.stats.messages': string;
|
|
70
|
+
'delegation.aria': string;
|
|
71
|
+
'captain.name': string;
|
|
72
|
+
'captain.role': string;
|
|
73
|
+
'captain.summary': string;
|
|
74
|
+
'captain.state.working': string;
|
|
75
|
+
'captain.state.collected': string;
|
|
76
|
+
'captain.state.waiting': string;
|
|
77
|
+
'members.toggle': string;
|
|
78
|
+
'members.collapse': string;
|
|
79
|
+
'members.expand': string;
|
|
80
|
+
'members.empty': string;
|
|
81
|
+
'assignment.label': string;
|
|
82
|
+
'assignment.empty': string;
|
|
83
|
+
'archive.label': string;
|
|
84
|
+
};
|
|
85
|
+
/** AgentTeams namespace key union. */
|
|
86
|
+
export type AgentTeamsLocaleKey = keyof typeof zh;
|
|
87
|
+
/** English dictionary, checked complete against the Chinese source key set. */
|
|
88
|
+
export declare const en: {
|
|
89
|
+
'card.memberCount': string;
|
|
90
|
+
'action.openActivityPanel': string;
|
|
91
|
+
'activity.panelButton': string;
|
|
92
|
+
'activity.badgeAria': string;
|
|
93
|
+
'activity.panelAria': string;
|
|
94
|
+
'activity.title': string;
|
|
95
|
+
'activity.float': string;
|
|
96
|
+
'activity.dockRight': string;
|
|
97
|
+
'activity.collapse': string;
|
|
98
|
+
'activity.empty': string;
|
|
99
|
+
'format.listSeparator': string;
|
|
100
|
+
'task.status.pending': string;
|
|
101
|
+
'task.status.claimed': string;
|
|
102
|
+
'task.status.inProgress': string;
|
|
103
|
+
'task.status.completed': string;
|
|
104
|
+
'task.status.failed': string;
|
|
105
|
+
'task.status.cancelled': string;
|
|
106
|
+
'member.state.working': string;
|
|
107
|
+
'member.state.failed': string;
|
|
108
|
+
'member.state.waiting': string;
|
|
109
|
+
'member.state.delivered': string;
|
|
110
|
+
'member.state.left': string;
|
|
111
|
+
'member.state.removed': string;
|
|
112
|
+
'member.state.pending': string;
|
|
113
|
+
'member.state.unassigned': string;
|
|
114
|
+
'member.status.executing': string;
|
|
115
|
+
'member.status.working': string;
|
|
116
|
+
'member.status.waitingOn': string;
|
|
117
|
+
'member.status.waitingPrerequisite': string;
|
|
118
|
+
'member.status.waitingAssignment': string;
|
|
119
|
+
'member.status.delivered': string;
|
|
120
|
+
'member.status.idle': string;
|
|
121
|
+
'member.status.unknown': string;
|
|
122
|
+
'task.assignee.unclaimed': string;
|
|
123
|
+
'task.summary.waitingBreakdown': string;
|
|
124
|
+
'task.summary.allDelivered': string;
|
|
125
|
+
'task.summary.blockedAndRunning': string;
|
|
126
|
+
'task.summary.more': string;
|
|
127
|
+
'task.summary.running': string;
|
|
128
|
+
'task.summary.ready': string;
|
|
129
|
+
'task.summary.blocked': string;
|
|
130
|
+
'task.summary.waitingSchedule': string;
|
|
131
|
+
'progress.aria': string;
|
|
132
|
+
'progress.title': string;
|
|
133
|
+
'progress.running': string;
|
|
134
|
+
'progress.blocked': string;
|
|
135
|
+
'progress.delivered': string;
|
|
136
|
+
'dependency.aria': string;
|
|
137
|
+
'dependency.parallel': string;
|
|
138
|
+
'dependency.title': string;
|
|
139
|
+
'dependency.hint.parallel': string;
|
|
140
|
+
'dependency.hint.chain': string;
|
|
141
|
+
'dependency.hint.pinned': string;
|
|
142
|
+
'task.runningAria': string;
|
|
143
|
+
'task.detail.completed': string;
|
|
144
|
+
'task.detail.noPrerequisite': string;
|
|
145
|
+
'task.detail.ready': string;
|
|
146
|
+
'task.detail.waitingOn': string;
|
|
147
|
+
'task.detail.noDownstream': string;
|
|
148
|
+
'task.detail.unlocks': string;
|
|
149
|
+
'team.ended': string;
|
|
150
|
+
'team.stats.members': string;
|
|
151
|
+
'team.stats.completed': string;
|
|
152
|
+
'team.stats.messages': string;
|
|
153
|
+
'delegation.aria': string;
|
|
154
|
+
'captain.name': string;
|
|
155
|
+
'captain.role': string;
|
|
156
|
+
'captain.summary': string;
|
|
157
|
+
'captain.state.working': string;
|
|
158
|
+
'captain.state.collected': string;
|
|
159
|
+
'captain.state.waiting': string;
|
|
160
|
+
'members.toggle': string;
|
|
161
|
+
'members.collapse': string;
|
|
162
|
+
'members.expand': string;
|
|
163
|
+
'members.empty': string;
|
|
164
|
+
'assignment.label': string;
|
|
165
|
+
'assignment.empty': string;
|
|
166
|
+
'archive.label': string;
|
|
167
|
+
};
|
|
168
|
+
/** Translation function consumed by pure view helpers. */
|
|
169
|
+
export type AgentTeamsTranslate = (key: AgentTeamsLocaleKey, params?: Record<string, unknown>) => string;
|
package/lib/types/scheduler.d.ts
CHANGED
|
@@ -5,7 +5,10 @@
|
|
|
5
5
|
* continuable agents instead expose explicit idle/running edges, so this
|
|
6
6
|
* scheduler closes the same loop without keeping a polling turn alive: every
|
|
7
7
|
* idle edge and every task-graph mutation attempts one atomic claim and wakes
|
|
8
|
-
* the selected durable member.
|
|
8
|
+
* the selected durable member. A resident member that becomes idle while it
|
|
9
|
+
* still owns an open attempt is parked: only an explicit captain reassignment
|
|
10
|
+
* may rotate that capability. Automatic retry is reserved for cold recovery,
|
|
11
|
+
* when the durable owner is no longer resident in the live Agent registry.
|
|
9
12
|
* @module dsh-agent-teams/scheduler
|
|
10
13
|
*/
|
|
11
14
|
import type { Context } from '@deepseek-ai/cordis';
|
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.13",
|
|
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",
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# AgentTeams v0.1.12
|
|
2
|
+
|
|
3
|
+
This release adds host-native English and Simplified Chinese localization to the AgentTeams Web UI.
|
|
4
|
+
|
|
5
|
+
## New & Improved
|
|
6
|
+
|
|
7
|
+
- **Official Harness locale integration**: the plugin registers its own `agentTeams` namespace with the Harness locale service instead of inspecting or rewriting host DOM.
|
|
8
|
+
- **Complete localized Web surfaces**: the conversation card and activity panel now translate task and member states, dynamic summaries, progress labels, dependency guidance, archive markers, controls, and accessibility text.
|
|
9
|
+
- **Live language switching**: changing the Harness language updates the active AgentTeams card and panel immediately without a page reload or a separate plugin setting.
|
|
10
|
+
- **Consistent fallback behavior**: English remains the fallback for missing locale entries, and dictionary keys and placeholders are verified as a release contract.
|
|
11
|
+
|
|
12
|
+
The `/agent-teams` slash-command description and input hint remain stable English metadata because the current Harness command protocol does not expose a locale namespace.
|
|
13
|
+
|
|
14
|
+
## Verification
|
|
15
|
+
|
|
16
|
+
- Ran a real DeepSeek API workflow in an isolated `/tmp` Git project with one captain, two members, two dependent tasks, durable messaging, generated artifacts, and a successful project verification command.
|
|
17
|
+
- Verified English → Chinese → English live switching in the real Harness Web UI, including panel folding, dock/floating mode, task dependencies, and member transcript navigation.
|
|
18
|
+
- Passed type checking, production build, offline verification, lifecycle verification, the eight-member complex stress suite, and the Skill mirror check.
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
dsh plugin --profile web add @nanmicoder/dsh-agent-teams
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
<details>
|
|
27
|
+
<summary><b>中文版本 / Chinese Version</b></summary>
|
|
28
|
+
|
|
29
|
+
# AgentTeams v0.1.12
|
|
30
|
+
|
|
31
|
+
本次更新为 AgentTeams Web UI 增加基于宿主官方能力的简体中文与英文多语言支持。
|
|
32
|
+
|
|
33
|
+
## 新增与改进
|
|
34
|
+
|
|
35
|
+
- **接入 Harness 官方多语言服务**:插件注册独立的 `agentTeams` 命名空间,不读取或改写宿主 DOM。
|
|
36
|
+
- **完整覆盖 Web 界面**:对话卡片与活动面板中的任务/成员状态、动态摘要、进度、依赖提示、归档标识、操作按钮及无障碍文案均已适配。
|
|
37
|
+
- **语言实时切换**:修改 Harness 语言后,当前 AgentTeams 卡片和面板无需刷新即可同步更新,也不需要插件自己的语言设置。
|
|
38
|
+
- **稳定回退与发布校验**:缺失文案按官方机制回退到英文,发布验证会检查中英文字典的键和模板参数保持一致。
|
|
39
|
+
|
|
40
|
+
由于当前 Harness 命令协议尚未提供 locale namespace,`/agent-teams` 在 slash 菜单中的描述和输入提示暂时保留稳定的英文元数据。
|
|
41
|
+
|
|
42
|
+
## 验证
|
|
43
|
+
|
|
44
|
+
- 在隔离的 `/tmp` Git 项目中使用真实 DeepSeek API 完成队长、两名成员、两个依赖任务、持久消息、真实产物及项目校验的完整链路。
|
|
45
|
+
- 在真实 Harness Web UI 中验证英文 → 中文 → 英文实时切换,以及面板收起、停靠/浮动、任务依赖和成员记录跳转。
|
|
46
|
+
- 通过类型检查、生产构建、离线验证、生命周期验证、八成员复杂压力测试及 Skill 镜像检查。
|
|
47
|
+
|
|
48
|
+
## 安装
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
dsh plugin --profile web add @nanmicoder/dsh-agent-teams
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
</details>
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# AgentTeams v0.1.13
|
|
2
|
+
|
|
3
|
+
This release makes long-running AgentTeams sessions calmer, more predictable, and easier to observe.
|
|
4
|
+
|
|
5
|
+
## Fixed & Improved
|
|
6
|
+
|
|
7
|
+
- **No retry storms while checking progress**: an idle member with an open task attempt now stays parked instead of restarting the same work whenever the captain checks status.
|
|
8
|
+
- **Explicit pause and resume**: a captain message resumes a parked member with the same task capability, while reassignment still revokes the previous attempt safely.
|
|
9
|
+
- **Activity panel discovery**: teams created after the first page discovery pass appear without a manual reload.
|
|
10
|
+
- **Lower idle overhead**: ordinary cardless sessions probe every five seconds and upgrade to the one-second live cadence only after a team is discovered.
|
|
11
|
+
- **Clearer delegation guidance**: the captain is instructed to create work for every required contributor and to avoid busy polling or waiting on unassigned members.
|
|
12
|
+
|
|
13
|
+
## Verification
|
|
14
|
+
|
|
15
|
+
- Passed production build, offline verification, lifecycle verification, the eight-member complex stress suite, and the Skill mirror check.
|
|
16
|
+
- Ran three independent four-member workflows with real DeepSeek models in a `/tmp` workspace; all assigned tasks completed in all three runs.
|
|
17
|
+
- Verified parked-member resume, task dependency gates, member-to-member reassignment, captain takeover, archive readback, live language switching, panel persistence, and idle polling cadence in the real Harness Web UI.
|
|
18
|
+
|
|
19
|
+
## Known Limitation
|
|
20
|
+
|
|
21
|
+
- After a hard DSH restart, the team, members, tasks, and dependency graph are restored, but unfinished members may remain in **Ready to continue** instead of resuming automatically. The captain can explicitly resume or reassign them; automatic cold-restart continuation will be addressed separately.
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
dsh plugin --profile web add @nanmicoder/dsh-agent-teams
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
<details>
|
|
30
|
+
<summary><b>中文版本 / Chinese Version</b></summary>
|
|
31
|
+
|
|
32
|
+
# AgentTeams v0.1.13
|
|
33
|
+
|
|
34
|
+
本次更新让长时间运行的 AgentTeams 协作更安静、更可预测,也更容易观察。
|
|
35
|
+
|
|
36
|
+
## 修复与改进
|
|
37
|
+
|
|
38
|
+
- **查询进度不再触发重复工作**:成员空闲但仍持有未完成任务时会保持暂停,不会因为队长查询状态而重新执行同一件事。
|
|
39
|
+
- **明确的暂停与继续语义**:队长发消息可让暂停成员沿用原任务能力继续执行;任务转派仍会安全撤销旧 attempt。
|
|
40
|
+
- **活动面板自动发现团队**:首次页面探测之后才创建的团队,也能自动出现在面板中,无需手动刷新。
|
|
41
|
+
- **降低普通会话开销**:没有团队卡片的普通会话每 5 秒低频探测一次,发现团队后才升级为每秒实时轮询。
|
|
42
|
+
- **更清晰的派工指导**:要求每位必须参与的成员都有明确任务,并避免高频查询或等待未分配工作的成员。
|
|
43
|
+
|
|
44
|
+
## 验证
|
|
45
|
+
|
|
46
|
+
- 通过生产构建、离线验证、生命周期验证、八成员复杂压力测试及 Skill 镜像检查。
|
|
47
|
+
- 在 `/tmp` workspace 中使用真实 DeepSeek 模型连续运行 3 轮独立四人团队流程,三轮所有已分配任务均完成。
|
|
48
|
+
- 在真实 Harness Web UI 中验证成员暂停继续、任务依赖、成员间转派、队长接管、归档读取、语言实时切换、面板状态保持及普通会话轮询频率。
|
|
49
|
+
|
|
50
|
+
## 已知限制
|
|
51
|
+
|
|
52
|
+
- DSH 硬重启后,团队、成员、任务和依赖图能够恢复,但未完成成员可能停在“待继续执行”,不会自动恢复工作。队长可以显式继续或转派;冷重启自动续跑将在后续版本单独处理。
|
|
53
|
+
|
|
54
|
+
## 安装
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
dsh plugin --profile web add @nanmicoder/dsh-agent-teams
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
</details>
|