@nanmicoder/dsh-agent-teams 0.1.17 → 0.1.19
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 +7 -5
- package/README_ZH.md +8 -4
- package/lib/client/AgentTeamsCard.js +1 -1
- package/lib/client.js +1 -1
- package/lib/client.js.map +1 -1
- package/lib/harness-compat.js +106 -0
- package/lib/index.js +4 -4
- package/lib/mailbox.js +154 -0
- package/lib/members.js +97 -23
- package/lib/quality-gates.js +181 -10
- package/lib/scheduler.js +27 -15
- package/lib/snapshot.js +1 -1
- package/lib/state.js +26 -6
- package/lib/tool-names.js +1 -0
- package/lib/tools.js +312 -214
- package/lib/types/event-types.d.ts +15 -1
- package/lib/types/harness-compat.d.ts +46 -0
- package/lib/types/index.d.ts +1 -1
- package/lib/types/mailbox.d.ts +7 -0
- package/lib/types/members.d.ts +6 -4
- package/lib/types/quality-gates.d.ts +51 -1
- package/lib/types/scheduler.d.ts +1 -0
- package/lib/types/state.d.ts +7 -1
- package/lib/types/tool-names.d.ts +2 -2
- package/lib/types/types.d.ts +30 -0
- package/package.json +6 -4
- package/release-notes/v0.1.18.md +21 -0
- package/release-notes/v0.1.19.md +20 -0
|
@@ -52,6 +52,15 @@ export interface AgentTeamsTaskUpdatedData {
|
|
|
52
52
|
readonly verdict?: string;
|
|
53
53
|
readonly round?: number;
|
|
54
54
|
}
|
|
55
|
+
/** Records one captain-only contract amendment on a task. */
|
|
56
|
+
export interface AgentTeamsTaskAmendedData {
|
|
57
|
+
readonly teamId: string;
|
|
58
|
+
readonly taskId: string;
|
|
59
|
+
/** Amended contract field names (`objective`, `inScope`, …). */
|
|
60
|
+
readonly fields: readonly string[];
|
|
61
|
+
/** Why the previous contract was wrong. */
|
|
62
|
+
readonly reason: string;
|
|
63
|
+
}
|
|
55
64
|
/** Records a human halt from the captain chat. */
|
|
56
65
|
export interface AgentTeamsTeamHaltedData {
|
|
57
66
|
readonly teamId: string;
|
|
@@ -108,6 +117,11 @@ declare module '@deepseek-ai/dsh-session/types' {
|
|
|
108
117
|
* @param data - team identity, task id, and the new status/assignee/output.
|
|
109
118
|
*/
|
|
110
119
|
'agent-teams/task-updated': AgentTeamsTaskUpdatedData;
|
|
120
|
+
/**
|
|
121
|
+
* Records one captain-only contract amendment.
|
|
122
|
+
* @param data - team identity, task id, amended field names, and reason.
|
|
123
|
+
*/
|
|
124
|
+
'agent-teams/task-amended': AgentTeamsTaskAmendedData;
|
|
111
125
|
/**
|
|
112
126
|
* Records one mailbox message.
|
|
113
127
|
* @param data - team identity, sender, recipient, and content.
|
|
@@ -136,4 +150,4 @@ declare module '@deepseek-ai/dsh-session/types' {
|
|
|
136
150
|
}
|
|
137
151
|
}
|
|
138
152
|
/** The full set of `agent-teams/*` event names. */
|
|
139
|
-
export type AgentTeamsEventType = 'agent-teams/team-created' | 'agent-teams/member-added' | 'agent-teams/member-removed' | 'agent-teams/task-created' | 'agent-teams/task-updated' | 'agent-teams/message-sent' | 'agent-teams/team-halted' | 'agent-teams/team-resumed' | 'agent-teams/team-deleted' | 'agent-teams/plan-discarded';
|
|
153
|
+
export type AgentTeamsEventType = 'agent-teams/team-created' | 'agent-teams/member-added' | 'agent-teams/member-removed' | 'agent-teams/task-created' | 'agent-teams/task-updated' | 'agent-teams/task-amended' | 'agent-teams/message-sent' | 'agent-teams/team-halted' | 'agent-teams/team-resumed' | 'agent-teams/team-deleted' | 'agent-teams/plan-discarded';
|
|
@@ -18,6 +18,52 @@ export declare function sessionOwnEvents(session: Session): readonly SessionEven
|
|
|
18
18
|
export declare function installContinuableMemberSetup(ctx: Context, setup: Setup): void;
|
|
19
19
|
/** Queue a distinct host-authored turn; never substitute model-message steer. */
|
|
20
20
|
export declare function queueMemberPrompt(runtime: Context['subagents'], parent: Agent, childId: SessionId, content: ContentBlock[], signal: AbortSignal): Promise<MessageId>;
|
|
21
|
+
/** Coordination joins the nearest step, including waking an idle/cold child. */
|
|
22
|
+
export declare function steerMemberPrompt(runtime: Context['subagents'], parent: Agent, childId: SessionId, content: ContentBlock[], signal: AbortSignal, live?: Agent): Promise<MessageId>;
|
|
21
23
|
/** Guard all resumable delivery paths, preserving the native service receiver. */
|
|
22
24
|
export declare function guardSubagentDelivery(ctx: Context, isRetired: (sender: Agent, targetId: SessionId) => Promise<boolean>): void;
|
|
25
|
+
/**
|
|
26
|
+
* Names the host's `tools.restrict()` would admit for this agent's layer
|
|
27
|
+
* chain, or undefined when the host does not expose its registry view.
|
|
28
|
+
* restrict() rejects unknown names with a hard error, so the spawn path must
|
|
29
|
+
* check entries against this view before forwarding them. Source:
|
|
30
|
+
* dsh-tools view()/restrict() in 0.1.5-rc.1; older Harness generations lack
|
|
31
|
+
* the surface and keep the verbatim list.
|
|
32
|
+
*/
|
|
33
|
+
export declare function restrictableToolNames(agent: Agent): ReadonlySet<string> | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Member `toolFilter` for one spawn. Captain-only names are registered by
|
|
36
|
+
* this plugin itself and always resolvable; the depth-related entries name
|
|
37
|
+
* HOST tools and are only known under some compositions, so they must be
|
|
38
|
+
* resolved against the running host's registry: the delegation tool name is
|
|
39
|
+
* host configuration (dsh-tool-subagent `toolName`, default `subagent`,
|
|
40
|
+
* renamed per composition, e.g. `subagent_fork` in web-style profiles), and
|
|
41
|
+
* forwarding a name the host dropped aborts every member spawn (#163, #164).
|
|
42
|
+
* Depth enforcement itself does not depend on these names —
|
|
43
|
+
* installMemberDelegationGuard bounds descendant creation by parent chain.
|
|
44
|
+
*/
|
|
45
|
+
export declare function memberToolFilter(maxDepth: number | undefined, knownTools: ReadonlySet<string> | undefined): {
|
|
46
|
+
deny: string[];
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Start one member, dropping any filter name the host reports as unknown and
|
|
50
|
+
* retrying.
|
|
51
|
+
*
|
|
52
|
+
* Resolving the filter against the registry view ({@link memberToolFilter})
|
|
53
|
+
* only covers hosts that expose one. A rejected filter still leaves the member
|
|
54
|
+
* without a session for the lifetime of the team, so the start must survive the
|
|
55
|
+
* cases that resolution cannot see — no registry view, a name that is known but
|
|
56
|
+
* not restrictable, a composition that mounted differently than expected. The
|
|
57
|
+
* host names the offenders in its rejection, so they are removed and the start
|
|
58
|
+
* retried; the retry only runs while the deny list strictly shrinks, and any
|
|
59
|
+
* failure that is not an unknown-name report propagates untouched.
|
|
60
|
+
* @param start - performs one start attempt for the given `toolFilter`.
|
|
61
|
+
* @param filter - the filter to attempt first.
|
|
62
|
+
* @returns the started member.
|
|
63
|
+
*/
|
|
64
|
+
export declare function startMemberWithLenientFilter<T>(start: (filter: {
|
|
65
|
+
deny: string[];
|
|
66
|
+
}) => Promise<T>, filter: {
|
|
67
|
+
deny: string[];
|
|
68
|
+
}): Promise<T>;
|
|
23
69
|
export {};
|
package/lib/types/index.d.ts
CHANGED
|
@@ -38,7 +38,7 @@ export interface Config {
|
|
|
38
38
|
executionPrompt?: string;
|
|
39
39
|
/** Plugin-wide fallback route for unavailable member models. */
|
|
40
40
|
fallback?: import('./profiles.ts').TeamModelFallbackConfig;
|
|
41
|
-
/** Member delegation depth cap (default `
|
|
41
|
+
/** Member delegation depth cap (default `0`; `0` forbids delegation entirely). */
|
|
42
42
|
memberMaxDepth?: number;
|
|
43
43
|
/** Team size cap in members (default `8`). */
|
|
44
44
|
maxMembers?: number;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Durable delivery receipts and execution-generation filtering at step admission. */
|
|
2
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
3
|
+
import type { TeamMessage, TeamState } from './types.ts';
|
|
4
|
+
export declare function isCurrentMail(team: TeamState, message: TeamMessage): boolean;
|
|
5
|
+
export declare function mailboxPrompt(teamId: string, recipient: string, messages: readonly TeamMessage[]): string;
|
|
6
|
+
/** Only messages actually admitted to this recipient's step become read. */
|
|
7
|
+
export declare function installMailboxAdmission(ctx: Context, stateDir: string): void;
|
package/lib/types/members.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Member subagent lifecycle: spawn a continuable child per member, deliver
|
|
3
|
-
*
|
|
3
|
+
* task turns and step-boundary messages, and observe its activity.
|
|
4
4
|
*
|
|
5
5
|
* Members are durable continuable subagents of the captain, so a member keeps
|
|
6
6
|
* its conversation across turns and across harness restarts: the captain
|
|
@@ -92,7 +92,7 @@ export declare function selectFallbackRoute(current: {
|
|
|
92
92
|
};
|
|
93
93
|
};
|
|
94
94
|
/** Deliver a durable member report to the live captain at its next model step. */
|
|
95
|
-
export declare function steerCaptainReport(captain: Pick<Agent, 'steer'>, from: string, content: string): boolean;
|
|
95
|
+
export declare function steerCaptainReport(captain: Pick<Agent, 'steer'>, from: string, content: string, receipt?: string): boolean;
|
|
96
96
|
interface FailedMemberAttempt {
|
|
97
97
|
readonly captainSessionId: string;
|
|
98
98
|
readonly memberId: string;
|
|
@@ -151,7 +151,7 @@ export declare function memberWelcome(team: TeamState, memberName: string): stri
|
|
|
151
151
|
* @param stateDir - configured state directory (for the persona).
|
|
152
152
|
* @param signal - caller cancellation, forwarded to the start.
|
|
153
153
|
*/
|
|
154
|
-
export declare function spawnMember(ctx: Context, config: MemberRuntimeConfig, selections: MemberSelectionRuntime, llmSelection: MemberLlmSelection, captain: Agent, team: TeamState, member: TeamMember, stateDir: string, signal: AbortSignal): Promise<void>;
|
|
154
|
+
export declare function spawnMember(ctx: Context, config: MemberRuntimeConfig, selections: MemberSelectionRuntime, llmSelection: MemberLlmSelection, captain: Agent, team: TeamState, member: TeamMember, stateDir: string, signal: AbortSignal, initialPrompt?: string): Promise<void>;
|
|
155
155
|
/**
|
|
156
156
|
* Deliver one message to a member as its next FIFO turn. Best effort: a
|
|
157
157
|
* failure (member gone or not continuable) is logged and reported as `false`
|
|
@@ -169,7 +169,7 @@ export declare function spawnMember(ctx: Context, config: MemberRuntimeConfig, s
|
|
|
169
169
|
* @param signal - caller cancellation, forwarded to the delivery.
|
|
170
170
|
* @returns whether the member inbox accepted the message.
|
|
171
171
|
*/
|
|
172
|
-
export declare function deliverToMember(ctx: Context, captain: Agent, childId: string, text: string, signal: AbortSignal): Promise<boolean>;
|
|
172
|
+
export declare function deliverToMember(ctx: Context, captain: Agent, childId: string, text: string, signal: AbortSignal, mode?: 'queue' | 'steer'): Promise<boolean>;
|
|
173
173
|
/**
|
|
174
174
|
* Request cancellation of one live member's current turn. Best effort, fire
|
|
175
175
|
* and return; the target may keep running until it observes the signal.
|
|
@@ -191,6 +191,8 @@ export declare function interruptMember(ctx: Context, captain: Agent, childId: s
|
|
|
191
191
|
* untouched while the delivery boundary still prevents further model turns.
|
|
192
192
|
*/
|
|
193
193
|
export declare function installRetiredMemberGuard(ctx: Context, stateDir: string): void;
|
|
194
|
+
/** Bound all descendant creation, including renamed tools and code-runtime calls. */
|
|
195
|
+
export declare function installMemberDelegationGuard(ctx: Context, stateDir: string, maxDepth: number): void;
|
|
194
196
|
/**
|
|
195
197
|
* Snapshot the real driver activity for durable member ids.
|
|
196
198
|
*
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* coverage, and resume. Tools and persistence call these; they do not I/O.
|
|
4
4
|
* @module dsh-agent-teams/quality-gates
|
|
5
5
|
*/
|
|
6
|
-
import { type AcceptanceResult, type CommandResult, type FindingSeverity, type ReviewFinding, type ReviewPolicy, type ReviewVerdict, type TaskKind, type TaskStatus, type TeamState, type TeamTask } from './types.ts';
|
|
6
|
+
import { type AcceptanceResult, type CommandResult, type FindingSeverity, type ReviewFinding, type ReviewPolicy, type ReviewVerdict, type TaskKind, type TaskRevision, type TaskStatus, type TeamState, type TeamTask } from './types.ts';
|
|
7
7
|
declare const QUALITY_KINDS: readonly TaskKind[];
|
|
8
8
|
declare const WRITE_KINDS: readonly TaskKind[];
|
|
9
9
|
declare const DEFAULT_REVIEW_POLICY: Required<Pick<ReviewPolicy, 'requirementsMinRounds' | 'requirementsMaxRounds' | 'codeMaxRounds' | 'maxRepairAttempts'>>;
|
|
@@ -121,6 +121,55 @@ export declare function collectChangedPaths(gitStatusText: string): string[];
|
|
|
121
121
|
export declare function inScopeOverlap(left: readonly string[] | undefined, right: readonly string[] | undefined): string[];
|
|
122
122
|
export declare function validateCreateTask(team: TeamState, input: CreateTaskInput): ValidateCreateTaskResult;
|
|
123
123
|
export declare function evaluateQualityCompletion(task: TeamTask, update: QualityCompletionUpdate): QualityCompletionResult;
|
|
124
|
+
/**
|
|
125
|
+
* Derive the repair round's inScope from the findings that caused it.
|
|
126
|
+
*
|
|
127
|
+
* `finding.file` records where the problem was OBSERVED, but the fix often
|
|
128
|
+
* targets a different file named in `requiredFix` (docs vs sample data,
|
|
129
|
+
* config vs code). Deriving the scope from both keeps the auto-generated
|
|
130
|
+
* repair contract satisfiable; deriving from `file` alone can produce a
|
|
131
|
+
* contract where the acceptance ("edit README.md") names a path the scope
|
|
132
|
+
* forbids, so no honest completion exists and the repair dead-locks.
|
|
133
|
+
*
|
|
134
|
+
* Absolute and otherwise illegal paths are dropped (they can never match
|
|
135
|
+
* workspace-relative scope patterns anyway); when nothing legal remains,
|
|
136
|
+
* the source task's own inScope is kept as the fallback. Over-inclusion is
|
|
137
|
+
* accepted: inScope is an audit upper bound, and the requiredFix text still
|
|
138
|
+
* tells the implementer what to touch.
|
|
139
|
+
*
|
|
140
|
+
* Keep all derived paths until the generator resolves inherited exclusions;
|
|
141
|
+
* filtering first would silently discard a required fix target.
|
|
142
|
+
*/
|
|
143
|
+
export declare function repairScopeFromFindings(findings: readonly ReviewFinding[], fallback: string[] | undefined): string[] | undefined;
|
|
144
|
+
/** Captain-only amendment payload: replacement values for contract fields. */
|
|
145
|
+
export interface ContractAmendmentInput {
|
|
146
|
+
objective?: string;
|
|
147
|
+
acceptance?: string[];
|
|
148
|
+
verify?: string[];
|
|
149
|
+
inScope?: string[];
|
|
150
|
+
outOfScope?: string[];
|
|
151
|
+
}
|
|
152
|
+
export interface AmendTaskContractResult {
|
|
153
|
+
ok: boolean;
|
|
154
|
+
error?: string;
|
|
155
|
+
task?: TeamTask;
|
|
156
|
+
revision?: TaskRevision;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Controlled contract amendment (the pure rule; tooling keeps it
|
|
160
|
+
* captain-only). When a quality contract is wrong — a verify command that
|
|
161
|
+
* cannot pass, an inScope that forbids the file the objective names — the
|
|
162
|
+
* worker has no honest completion and either dead-locks or games the gate.
|
|
163
|
+
* Instead the captain may fix the contract mid-flight: every amendment is
|
|
164
|
+
* recorded on the task as a {@link TaskRevision} (previous values + reason),
|
|
165
|
+
* and once a review/requirements task has passed judgment on this task the
|
|
166
|
+
* contract is frozen. Amendments replace whole fields (lists are full
|
|
167
|
+
* replacements, not deltas); the implementer re-reads the amended contract
|
|
168
|
+
* before its next quality gate. Completion gates need no special casing:
|
|
169
|
+
* they read the task's current fields, so they naturally evaluate the
|
|
170
|
+
* amended contract.
|
|
171
|
+
*/
|
|
172
|
+
export declare function amendTaskContract(team: TeamState, task: TeamTask, input: ContractAmendmentInput, by: string, reason: string): AmendTaskContractResult;
|
|
124
173
|
export declare function planQualityFollowUp(team: TeamState, closed: TeamTask): PlanQualityFollowUpResult;
|
|
125
174
|
export declare function buildCoverageMatrix(goalItems: readonly string[], tasks: readonly TeamTask[]): CoverageRow[];
|
|
126
175
|
export declare function canDeclareDelivery(team: TeamState): DeliveryResult;
|
|
@@ -128,6 +177,7 @@ export declare function resumeTeamState(team: TeamState, reason: string): Resume
|
|
|
128
177
|
export declare function isReviewFinding(value: unknown): value is ReviewFinding;
|
|
129
178
|
export declare function isAcceptanceResult(value: unknown): value is AcceptanceResult;
|
|
130
179
|
export declare function isCommandResult(value: unknown): value is CommandResult;
|
|
180
|
+
export declare function isTaskRevision(value: unknown): value is TaskRevision;
|
|
131
181
|
/**
|
|
132
182
|
* Normalize blank optional task fields to omitted ("blank means absent").
|
|
133
183
|
* Blank string scalars are deleted; string lists have blank entries filtered
|
package/lib/types/scheduler.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export declare const DEPENDENCY_OUTPUTS_TOTAL_MAX_CHARS = 12000;
|
|
|
21
21
|
export interface SchedulerConfig {
|
|
22
22
|
readonly stateDir: string;
|
|
23
23
|
readonly executionPrompt?: string;
|
|
24
|
+
readonly dispatch?: (captain: Agent, teamId: string, memberName: string, text: string, signal: AbortSignal, mode: 'queue' | 'steer', attemptId?: string) => Promise<boolean>;
|
|
24
25
|
}
|
|
25
26
|
export interface TeamScheduler {
|
|
26
27
|
/** Try to give every genuinely idle/ready member one unit of ready work. */
|
package/lib/types/state.d.ts
CHANGED
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
* @module dsh-agent-teams/state
|
|
14
14
|
*/
|
|
15
15
|
import { type TaskStatus, type TeamMessage, type TeamState, type TeamTask } from './types.ts';
|
|
16
|
-
export { buildCoverageMatrix, canDeclareDelivery, classifyChangedPath, collectChangedPaths, defaultQualityDeliveryGraph, describeQualityLoop, evaluateQualityCompletion, hasValidQualityTaskFields, isQualityKind, normalizeBlankOptionalTaskFields, pathMatchesScope, planQualityFollowUp, qualityPlanningPrompt, resumeTeamState, sanitizeReviewAcceptance, sanitizeReviewObjective, taskKindOf, validateCreateTask, } from './quality-gates.ts';
|
|
16
|
+
export { amendTaskContract, buildCoverageMatrix, canDeclareDelivery, classifyChangedPath, collectChangedPaths, defaultQualityDeliveryGraph, describeQualityLoop, evaluateQualityCompletion, hasValidQualityTaskFields, isQualityKind, isTaskRevision, normalizeBlankOptionalTaskFields, pathMatchesScope, planQualityFollowUp, qualityPlanningPrompt, resumeTeamState, sanitizeReviewAcceptance, sanitizeReviewObjective, taskKindOf, validateCreateTask, } from './quality-gates.ts';
|
|
17
|
+
export type { ContractAmendmentInput } from './quality-gates.ts';
|
|
17
18
|
/** Mailbox key of the captain. */
|
|
18
19
|
export declare const CAPTAIN_KEY = "captain";
|
|
19
20
|
/**
|
|
@@ -149,6 +150,8 @@ export declare function appendMailbox(stateRoot: string, teamId: string, agentKe
|
|
|
149
150
|
export declare function readMailbox(stateRoot: string, teamId: string, agentKey: string, onMalformedLine?: (lineNumber: number, error: unknown) => void): Promise<TeamMessage[]>;
|
|
150
151
|
/** Read only messages that have not been acknowledged by their recipient. */
|
|
151
152
|
export declare function readUnreadMailbox(stateRoot: string, teamId: string, agentKey: string, onMalformedLine?: (lineNumber: number, error: unknown) => void): Promise<TeamMessage[]>;
|
|
153
|
+
/** Pending delivery is distinct from delivered-but-not-yet-read input. */
|
|
154
|
+
export declare function readPendingMailbox(stateRoot: string, teamId: string, agentKey: string): Promise<TeamMessage[]>;
|
|
152
155
|
/** Lease selected fallback messages to one delivery path. */
|
|
153
156
|
export declare function claimMailboxDelivery(stateRoot: string, teamId: string, agentKey: string, messageIds: readonly string[]): Promise<void>;
|
|
154
157
|
/** Release a failed delivery lease so the scheduler can retry it later. */
|
|
@@ -158,6 +161,9 @@ export declare function releaseMailboxDelivery(stateRoot: string, teamId: string
|
|
|
158
161
|
* malformed lines for diagnostics. Callers serialize this with the team lock.
|
|
159
162
|
*/
|
|
160
163
|
export declare function acknowledgeMailbox(stateRoot: string, teamId: string, agentKey: string, messageIds: readonly string[]): Promise<void>;
|
|
164
|
+
/** Acceptance by Harness is not evidence that a model step consumed input. */
|
|
165
|
+
export declare function markMailboxDelivered(stateRoot: string, teamId: string, agentKey: string, ids: readonly string[]): Promise<void>;
|
|
166
|
+
export declare function discardMailboxMessages(stateRoot: string, teamId: string, agentKey: string, ids: readonly string[]): Promise<void>;
|
|
161
167
|
/** Filesystem primitives used by {@link replaceFileAtomicOrDirect}; injectable for tests. */
|
|
162
168
|
export interface AtomicReplacePrimitives {
|
|
163
169
|
rename: (from: string, to: string) => Promise<void>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/** Stable business API names; exposure changes never rename these operations. */
|
|
2
|
-
export declare const TEAM_TOOL_NAMES: readonly ["agent_teams_create", "agent_teams_approve", "agent_teams_edit_plan", "agent_teams_add_member", "agent_teams_remove_member", "agent_teams_create_task", "agent_teams_reassign_task", "agent_teams_claim_task", "agent_teams_update_task", "agent_teams_send_message", "agent_teams_status", "agent_teams_resume", "agent_teams_delete"];
|
|
2
|
+
export declare const TEAM_TOOL_NAMES: readonly ["agent_teams_create", "agent_teams_approve", "agent_teams_edit_plan", "agent_teams_add_member", "agent_teams_remove_member", "agent_teams_create_task", "agent_teams_reassign_task", "agent_teams_claim_task", "agent_teams_update_task", "agent_teams_amend_task", "agent_teams_send_message", "agent_teams_status", "agent_teams_resume", "agent_teams_delete"];
|
|
3
3
|
export declare const MEMBER_TOOL_NAMES: readonly string[];
|
|
4
|
-
export declare const CAPTAIN_TOOL_NAMES: ("agent_teams_create" | "agent_teams_approve" | "agent_teams_edit_plan" | "agent_teams_add_member" | "agent_teams_remove_member" | "agent_teams_create_task" | "agent_teams_reassign_task" | "agent_teams_claim_task" | "agent_teams_update_task" | "agent_teams_send_message" | "agent_teams_status" | "agent_teams_resume" | "agent_teams_delete")[];
|
|
4
|
+
export declare const CAPTAIN_TOOL_NAMES: ("agent_teams_create" | "agent_teams_approve" | "agent_teams_edit_plan" | "agent_teams_add_member" | "agent_teams_remove_member" | "agent_teams_create_task" | "agent_teams_reassign_task" | "agent_teams_claim_task" | "agent_teams_update_task" | "agent_teams_amend_task" | "agent_teams_send_message" | "agent_teams_status" | "agent_teams_resume" | "agent_teams_delete")[];
|
package/lib/types/types.d.ts
CHANGED
|
@@ -52,6 +52,19 @@ export interface ReviewPolicy {
|
|
|
52
52
|
maxRepairAttempts?: number;
|
|
53
53
|
requiredReviewers?: string[];
|
|
54
54
|
}
|
|
55
|
+
/** One captain-only contract amendment recorded on a quality task. */
|
|
56
|
+
export interface TaskRevision {
|
|
57
|
+
/** Epoch ms when the amendment was applied. */
|
|
58
|
+
at: number;
|
|
59
|
+
/** Identity that applied it (`captain`). */
|
|
60
|
+
by: string;
|
|
61
|
+
/** Why the previous contract was wrong; kept for the audit trail. */
|
|
62
|
+
reason: string;
|
|
63
|
+
/** Amended contract field names (`objective`, `acceptance`, …). */
|
|
64
|
+
fields: string[];
|
|
65
|
+
/** Previous values of the amended fields; fields absent before are omitted. */
|
|
66
|
+
previous: Record<string, unknown>;
|
|
67
|
+
}
|
|
55
68
|
/** One task of a team's task list. */
|
|
56
69
|
export interface TeamTask {
|
|
57
70
|
/** Stable task id from the profile template; absent for ad-hoc tasks. */
|
|
@@ -75,6 +88,8 @@ export interface TeamTask {
|
|
|
75
88
|
attemptId?: string;
|
|
76
89
|
/** Opaque generation for a revocation/handoff that has not started its next attempt yet. */
|
|
77
90
|
handoffId?: string;
|
|
91
|
+
/** Previous activation retained until a handoff drain succeeds (retryable). */
|
|
92
|
+
handoffFromMemberId?: string;
|
|
78
93
|
/** A handoff is quiescing the old owner; the scheduler must not dispatch it yet. */
|
|
79
94
|
reassigning?: boolean;
|
|
80
95
|
/** Quality-gate kind. Missing values are treated as `work`. */
|
|
@@ -100,6 +115,8 @@ export interface TeamTask {
|
|
|
100
115
|
sourceFindingIds?: string[];
|
|
101
116
|
/** User-constraint / goal items this task claims to cover. */
|
|
102
117
|
coverageOf?: string[];
|
|
118
|
+
/** Captain-only contract amendments, oldest first (see amendTaskContract). */
|
|
119
|
+
revisions?: TaskRevision[];
|
|
103
120
|
createdAt: number;
|
|
104
121
|
updatedAt: number;
|
|
105
122
|
}
|
|
@@ -130,6 +147,14 @@ export interface TeamMember {
|
|
|
130
147
|
fallbackActive?: boolean;
|
|
131
148
|
joinedAt: number;
|
|
132
149
|
status: MemberStatus;
|
|
150
|
+
/** Execution admission is closed while a failed/pending handoff is drained. */
|
|
151
|
+
stopping?: boolean;
|
|
152
|
+
/**
|
|
153
|
+
* Last member-start failure, recorded so the captain can see why a member
|
|
154
|
+
* never acquired a session instead of observing an unexplained `unspawned`
|
|
155
|
+
* member. Cleared by the next successful start.
|
|
156
|
+
*/
|
|
157
|
+
spawnError?: string;
|
|
133
158
|
}
|
|
134
159
|
/** One mailbox message. */
|
|
135
160
|
export interface TeamMessage {
|
|
@@ -146,6 +171,11 @@ export interface TeamMessage {
|
|
|
146
171
|
deliveredAt?: number;
|
|
147
172
|
/** Set once the recipient has consumed or been shown the durable fallback. */
|
|
148
173
|
readAt?: number;
|
|
174
|
+
/** Guidance is scoped to the recipient's execution generation, when present. */
|
|
175
|
+
taskId?: string;
|
|
176
|
+
attemptId?: string;
|
|
177
|
+
/** Cancelled delivery is retained for audit but must not wake the recipient. */
|
|
178
|
+
discardedAt?: number;
|
|
149
179
|
}
|
|
150
180
|
/** Snapshot of the named profile used to seed a team. */
|
|
151
181
|
export interface TeamModelFallback {
|
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.19",
|
|
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",
|
|
@@ -225,13 +225,15 @@
|
|
|
225
225
|
"update:skills": "node scripts/update-skills.mjs",
|
|
226
226
|
"test:skills-updater": "node --test scripts/update-skills.test.mjs",
|
|
227
227
|
"verify:skill": "node scripts/sync-skill.mjs --check",
|
|
228
|
-
"verify": "node scripts/verify.mjs && node scripts/fallback-tdd.mjs && node scripts/member-failure-tdd.mjs &&
|
|
228
|
+
"verify": "node scripts/verify.mjs && node scripts/fallback-tdd.mjs && node scripts/member-failure-tdd.mjs && pnpm verify:quality-gates && node scripts/lifecycle-verify.mjs && node scripts/stress-verify.mjs && pnpm verify:web-routes && pnpm verify:release && pnpm verify:skill && pnpm verify:harness-contract && pnpm verify:http-body && pnpm verify:compatibility && pnpm verify:capabilities && pnpm verify:member-spawn-recovery",
|
|
229
|
+
"verify:quality-gates": "node scripts/quality-gates-tdd.mjs && node --test scripts/quality-gates-repair-scope.test.mjs scripts/quality-gates-amend.test.mjs",
|
|
229
230
|
"verify:web-routes": "node scripts/web-routes-verify.mjs",
|
|
230
231
|
"verify:release": "node --test scripts/release-metadata.test.mjs",
|
|
231
|
-
"verify:harness-contract": "node scripts/harness-compat-tdd.mjs && node scripts/lifecycle-verify.mjs --modern-harness && node scripts/member-failure-tdd.mjs --modern-harness && node scripts/lifecycle-verify.mjs --delivery-harness && node scripts/member-failure-tdd.mjs --delivery-harness",
|
|
232
|
+
"verify:harness-contract": "node scripts/harness-compat-tdd.mjs && node scripts/stability-tdd.mjs && node scripts/lifecycle-verify.mjs --modern-harness && node scripts/member-failure-tdd.mjs --modern-harness && node scripts/lifecycle-verify.mjs --delivery-harness && node scripts/member-failure-tdd.mjs --delivery-harness",
|
|
232
233
|
"verify:compatibility": "node scripts/compatibility.mjs && node --test scripts/compatibility.test.mjs && node scripts/doctor.mjs",
|
|
233
234
|
"verify:http-body": "node --test scripts/http-body.test.mjs",
|
|
234
235
|
"doctor": "node scripts/doctor.mjs",
|
|
235
|
-
"verify:capabilities": "node --test scripts/capabilities.test.mjs"
|
|
236
|
+
"verify:capabilities": "node --test scripts/capabilities.test.mjs",
|
|
237
|
+
"verify:member-spawn-recovery": "node --test scripts/member-spawn-recovery.test.mjs"
|
|
236
238
|
}
|
|
237
239
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# v0.1.18 — Reliable team scheduling and message delivery
|
|
2
|
+
|
|
3
|
+
npm channel: `latest`. Recommended host: DeepSeek Harness `0.1.5-rc.1`.
|
|
4
|
+
|
|
5
|
+
- Create the roster and dependency graph atomically; start members only when their first task is ready, avoiding welcome-only model turns.
|
|
6
|
+
- Deliver coordination at the next model step, preserve tool-result continuations, and discard duplicate or obsolete task messages. Suppress duplicate native success notifications after an accepted team report.
|
|
7
|
+
- Drain member descendants and queued input on archive, removal, and reassignment. Reject retired member identities on cold restore and retry incomplete cleanup.
|
|
8
|
+
- Allow dependency-fenced implementation planning while requirements are in progress, and correct or cancel tasks that have not started.
|
|
9
|
+
- Return the current attempt ID when a member omits it, so it can retry the update without restarting completed work. Keep rejection of genuinely stale attempts.
|
|
10
|
+
- Keep unfinished work from passing delivery gates; make deeper delegation an explicit choice.
|
|
11
|
+
- Preserve existing progressive tool loading, direct workflows, Harness compatibility, and light/dark theme support.
|
|
12
|
+
|
|
13
|
+
Validation includes regression tests and a four-host native runtime matrix: `0.1.5-rc.1`, `0.1.2-rc.1`, `0.1.2-alpha.5`, and `0.1.2-alpha.2`. The release workflow checks the same packaged artifact on every host before npm publication.
|
|
14
|
+
|
|
15
|
+
Pre-release real DeepSeek testing under `/tmp` exercised six members, seventeen tasks, cold continuation, and review/repair loops, finishing with 32 external assertions. This involved interrupted runs and fixes between phases; it is not a claim of a clean single-run benchmark or a measured speedup. See the [full test report](https://github.com/NanmiCoder/dsh-agent-teams/blob/v0.1.18/docs/session-latency-audit-2026-09-12/complex-test-report.md), including test limitations and the disclosed test-scope incident.
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
dsh plugin --profile web add --save-exact @nanmicoder/dsh-agent-teams@0.1.18
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Restart Harness and refresh the browser after upgrading. Updating the plugin does not update a Desktop app's embedded Harness. Before downgrading, finish or archive teams created by this release: older plugins do not understand dormant members with an empty session ID.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# AgentTeams v0.1.19
|
|
2
|
+
|
|
3
|
+
- Fix member startup when the host disables or renames its delegation tools. Missing global tool names no longer abort all member starts; unrelated startup failures remain visible in team status. Thanks to PRs #167 and #172.
|
|
4
|
+
- Derive automatic repair scope from both the observed file and paths named in `requiredFix`. Resolve conflicting exclusions inherited from the previous round after deriving that scope, so a repair can truthfully report the files it must change. Integrates PR #155 and the generated-contract portion of PR #177; manually authored exclusions keep their existing precedence.
|
|
5
|
+
- Add captain-only `agent_teams_amend_task` for correcting non-terminal quality contracts, with durable revision history and freeze checks after a passing review. Members cannot call it.
|
|
6
|
+
- Include repair-scope and amendment regressions in the standard release gate; update the captain tool-surface fixture and tolerate the known closed-session teardown race (PR #180).
|
|
7
|
+
|
|
8
|
+
## Compatibility
|
|
9
|
+
|
|
10
|
+
The supported Harness matrix is unchanged: recommended `0.1.5-rc.1`, plus `0.1.2-rc.1`, `0.1.2-alpha.5`, and `0.1.2-alpha.2`. This release does not claim support for untested newer Harness versions or every Desktop distribution.
|
|
11
|
+
|
|
12
|
+
Existing malformed terminal tasks are not rewritten automatically. Broader findings/revision linkage and stale generated acceptance criteria remain separate issues.
|
|
13
|
+
|
|
14
|
+
Update the plugin in your existing profile, then restart Harness:
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
dsh plugin --profile <your-profile> add --save-exact @nanmicoder/dsh-agent-teams@0.1.19
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
See [release verification](https://github.com/NanmiCoder/dsh-agent-teams/tree/main/docs/releases/v0.1.19) for real-provider scenarios, evidence boundaries, and publication results.
|