@nanmicoder/dsh-agent-teams 0.1.13 → 0.1.14

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.
@@ -18,6 +18,7 @@
18
18
  */
19
19
  import type { Context } from '@deepseek-ai/cordis';
20
20
  import z from '@deepseek-ai/schemastery';
21
+ import { type TeamProfileConfig } from './profiles.ts';
21
22
  export declare const name = "agent-teams";
22
23
  export declare const inject: string[];
23
24
  /** Plugin configuration. */
@@ -31,10 +32,16 @@ export interface Config {
31
32
  memberProvider?: string;
32
33
  /** Optional model override applied to every member. */
33
34
  memberModel?: string;
35
+ /** Prompt injected into member personas and automatic task assignments. */
36
+ executionPrompt?: string;
37
+ /** Plugin-wide fallback route for unavailable member models. */
38
+ fallback?: import('./profiles.ts').TeamModelFallbackConfig;
34
39
  /** Member delegation depth cap (default `1`; `0` forbids delegation entirely). */
35
40
  memberMaxDepth?: number;
36
41
  /** Team size cap in members (default `8`). */
37
42
  maxMembers?: number;
43
+ /** Named multi-role team profiles. */
44
+ profiles?: Record<string, TeamProfileConfig>;
38
45
  /** Prompt-section order for the usage policy (default `117`, after delegation policy). */
39
46
  promptSectionOrder?: number;
40
47
  /**
@@ -45,4 +52,6 @@ export interface Config {
45
52
  slashCommand?: boolean;
46
53
  }
47
54
  export declare const Config: z<Config>;
55
+ /** The model-facing usage policy: when and how to drive AgentTeams. */
56
+ export declare function usageSectionText(toolNames: string, profilesText?: string): string;
48
57
  export declare function apply(ctx: Context, config: Config): void;
@@ -13,13 +13,22 @@
13
13
  */
14
14
  import type { Context } from '@deepseek-ai/cordis';
15
15
  import { type Agent } from '@deepseek-ai/dsh-agent';
16
- import type { TeamMember, TeamState } from './types.ts';
16
+ import { type TeamMember, type TeamState } from './types.ts';
17
+ /** Persona snapshot of a profile protocol; the full text lives on team.json. */
18
+ export declare const PERSONA_PROTOCOL_MAX_CHARS = 400;
17
19
  /** Runtime knobs for member spawning, resolved from plugin config. */
18
20
  export interface MemberRuntimeConfig {
19
21
  /** Registered `ctx.subagents` provider name (must support continuable + persona). */
20
22
  provider: string;
21
23
  /** Child delegation depth cap (0 forbids delegation entirely). */
22
24
  maxDepth?: number;
25
+ /** Plugin-wide execution prompt. */
26
+ executionPrompt?: string;
27
+ /** Plugin-wide fallback route. */
28
+ fallback?: {
29
+ provider: string;
30
+ model: string;
31
+ };
23
32
  }
24
33
  /** Durable provider/model/reasoning snapshot for one member. */
25
34
  export interface MemberLlmSelection {
@@ -29,6 +38,11 @@ export interface MemberLlmSelection {
29
38
  model: string;
30
39
  /** Adapter-owned reasoning effort, absent when the target has no explicit/default effort. */
31
40
  reasoningEffort?: string;
41
+ /** Configured second-choice route. */
42
+ fallback?: {
43
+ provider: string;
44
+ model: string;
45
+ };
32
46
  }
33
47
  /** Optional member-level route requested by the captain. */
34
48
  export interface MemberLlmSelectionRequest {
@@ -40,12 +54,40 @@ export interface MemberLlmSelectionRequest {
40
54
  defaultModel?: string;
41
55
  /** Explicit reasoning effort; "default" selects the target model's default effort. */
42
56
  reasoningEffort?: string;
57
+ /** Configured fallback route. */
58
+ fallback?: {
59
+ provider: string;
60
+ model: string;
61
+ };
43
62
  }
44
63
  /** Process-local bridge between spawn admission and synchronous child setup. */
45
64
  export interface MemberSelectionRuntime {
46
65
  /** Make one selection visible while Harness materializes the fresh child. */
47
66
  withPending<T>(parentSessionId: string, label: string, selection: MemberLlmSelection, operation: () => Promise<T>): Promise<T>;
48
67
  }
68
+ /**
69
+ * Validate a resolved roster against every provider catalog before any child
70
+ * session is created. Catalogs are advisory when empty (some adapters accept
71
+ * dynamic model ids), but a non-empty catalog is authoritative enough to
72
+ * catch a typo that would otherwise boot a child and fail on its first turn.
73
+ */
74
+ export declare function validateMemberLlmSelections(ctx: Context, selections: readonly MemberLlmSelection[], signal?: AbortSignal): Promise<void>;
75
+ export declare function isFallbackFailureCode(code: string): boolean;
76
+ /** Pure state transition used by the request-error handler and TDD tests. */
77
+ export declare function selectFallbackRoute(current: {
78
+ provider: string;
79
+ model: string;
80
+ }, fallback: {
81
+ provider: string;
82
+ model: string;
83
+ } | undefined, failureCode: string, alreadySwitched: boolean): {
84
+ retry: boolean;
85
+ switched: boolean;
86
+ selection: {
87
+ provider: string;
88
+ model: string;
89
+ };
90
+ };
49
91
  /**
50
92
  * Resolve one member's complete model selection. Ordinary members snapshot the
51
93
  * captain's current request route and reasoning effort. When provider or model
@@ -67,17 +109,20 @@ export declare function installMemberSelectionRuntime(ctx: Context, stateDir: st
67
109
  /**
68
110
  * The member's system prompt (persona), shadowing the deployment persona for
69
111
  * that child. Self-contained: it replaces the whole persona section.
112
+ * Frozen at spawn: draft must already carry the Team goal and profile protocol.
70
113
  * @param team - the team the member joined.
71
114
  * @param member - the member record (name/role are read before spawning).
72
115
  * @param stateDir - configured state directory, so the member can locate the
73
116
  * team files with its own file tools.
74
117
  */
75
- export declare function memberPersona(team: TeamState, member: TeamMember, stateDir: string): string;
118
+ export declare function memberPersona(team: TeamState, member: TeamMember, stateDir: string, executionPrompt?: string): string;
76
119
  /**
77
120
  * The initial user message delivered when the member is created.
121
+ * Counts non-terminal tasks already assigned to this member on the in-memory draft.
78
122
  * @param team - the team the member joined.
123
+ * @param memberName - canonical member name used to count assigned pending work.
79
124
  */
80
- export declare function memberWelcome(team: TeamState): string;
125
+ export declare function memberWelcome(team: TeamState, memberName: string): string;
81
126
  /**
82
127
  * Spawn one member as a durable continuable subagent of the captain and fill
83
128
  * `member.id` with its child session id. On failure nothing is persisted.
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Named team-profile templates: config types, normalization, invocation
3
+ * parsing, and prompt rendering.
4
+ *
5
+ * Pure functions only — no I/O, no spawn. Runtime create/spawn stays in
6
+ * `tools.ts`; this module only turns a config map + a profile name into a
7
+ * validated, topologically ordered template (or parses `--profile` flags).
8
+ *
9
+ * @module dsh-agent-teams/profiles
10
+ */
11
+ /** Hard cap on named profiles so the usage prompt cannot grow without bound. */
12
+ export declare const MAX_TEAM_PROFILES = 16;
13
+ /** Hard cap on seed tasks per profile. The software-delivery example has 13. */
14
+ export declare const MAX_PROFILE_TASKS = 32;
15
+ /** Protocol excerpt length in the usage / prompt listing. */
16
+ export declare const PROFILE_PROTOCOL_PROMPT_LIMIT = 240;
17
+ /** One member row in a named team-profile template (unresolved). */
18
+ export interface TeamModelFallbackConfig {
19
+ provider: string;
20
+ model: string;
21
+ }
22
+ export interface TeamProfileMemberConfig {
23
+ name: string;
24
+ role?: string;
25
+ provider?: string;
26
+ model?: string;
27
+ reasoning_effort?: string;
28
+ executionPrompt?: string;
29
+ fallback?: TeamModelFallbackConfig;
30
+ }
31
+ /** One seed-task row in a named team-profile template (unresolved). */
32
+ export interface TeamProfileTaskConfig {
33
+ id: string;
34
+ subject: string;
35
+ description?: string;
36
+ assignee?: string;
37
+ dependencies?: string[];
38
+ }
39
+ /** One named team-profile template from plugin config. */
40
+ export interface TeamProfileConfig {
41
+ description?: string;
42
+ protocol?: string;
43
+ executionPrompt?: string;
44
+ fallback?: TeamModelFallbackConfig;
45
+ members: TeamProfileMemberConfig[];
46
+ /**
47
+ * `captain` means the profile supplies people and guardrails only; the
48
+ * Captain derives the task graph from the user's goal at runtime.
49
+ * `seed` preserves a fixed template workflow for explicitly scripted teams.
50
+ */
51
+ taskPlanning?: 'captain' | 'seed';
52
+ tasks?: TeamProfileTaskConfig[];
53
+ reviewPolicy?: import('./types.ts').ReviewPolicy;
54
+ }
55
+ /** A profile member after trim / pairing / reserved-name checks. */
56
+ export interface NormalizedProfileMember {
57
+ name: string;
58
+ role?: string;
59
+ provider?: string;
60
+ model?: string;
61
+ reasoningEffort?: string;
62
+ executionPrompt?: string;
63
+ fallback?: TeamModelFallbackConfig;
64
+ }
65
+ /** A profile seed task after assignee canonicalization; `sourceIndex` is the YAML order. */
66
+ export interface NormalizedProfileTask {
67
+ id: string;
68
+ subject: string;
69
+ description?: string;
70
+ assignee?: string;
71
+ dependencies: string[];
72
+ sourceIndex: number;
73
+ }
74
+ /** A fully validated, topologically ordered team profile. */
75
+ export interface NormalizedTeamProfile {
76
+ name: string;
77
+ description?: string;
78
+ protocol?: string;
79
+ executionPrompt?: string;
80
+ fallback?: TeamModelFallbackConfig;
81
+ taskPlanning: 'captain' | 'seed';
82
+ members: NormalizedProfileMember[];
83
+ tasks: NormalizedProfileTask[];
84
+ reviewPolicy?: import('./types.ts').ReviewPolicy;
85
+ }
86
+ /** The goal + optional named profile extracted from a slash / gesture line. */
87
+ export interface AgentTeamsInvocation {
88
+ goal: string;
89
+ profile?: string;
90
+ }
91
+ /** One configured profile after key trim, for listing / lookup. */
92
+ export interface ListedTeamProfile {
93
+ name: string;
94
+ config: TeamProfileConfig;
95
+ }
96
+ /**
97
+ * Trim every profile key once, reject empty / colliding keys, and reject
98
+ * more than {@link MAX_TEAM_PROFILES} entries. Does not validate profile
99
+ * bodies — that belongs to {@link resolveTeamProfile}.
100
+ */
101
+ export declare function listConfiguredProfiles(profiles: Record<string, TeamProfileConfig> | undefined | null): ListedTeamProfile[];
102
+ /**
103
+ * Render the usage-prompt listing. One line per profile: name, member count,
104
+ * task count, protocol excerpt (at most 240 characters). Returns `''` when
105
+ * nothing is configured so callers can omit the capability entirely.
106
+ */
107
+ export declare function formatProfilesForPrompt(profiles: Record<string, TeamProfileConfig> | undefined | null): string;
108
+ /**
109
+ * Walk `rawInput` from the front and eat standalone profile flags. Only
110
+ * `--profile <name>`, `--profile=<name>`, and `profile=<name>` count; the
111
+ * first ordinary token stops the scan so a mid-sentence `profile=` stays in
112
+ * the goal. A leading ordinary token is never treated as a profile name.
113
+ *
114
+ * `--profile "name"` strips one matching pair of quotes. Repeat flags and a
115
+ * `--profile` with no name throw.
116
+ */
117
+ export declare function parseProfileInvocation(rawInput: string): AgentTeamsInvocation;
118
+ /**
119
+ * Normalize and pre-validate one named profile. Failures throw before any
120
+ * caller should create a directory or spawn members.
121
+ */
122
+ export declare function resolveTeamProfile(profiles: Record<string, TeamProfileConfig>, profileName: string, maxMembers: number): NormalizedTeamProfile;
123
+ /** Public lookup used by activation text and status rendering. */
124
+ export declare function resolveProfileTaskPlanning(config: TeamProfileConfig | undefined): 'captain' | 'seed';
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Pure quality-gate rules: contracts, path audit, completion, follow-up,
3
+ * coverage, and resume. Tools and persistence call these; they do not I/O.
4
+ * @module dsh-agent-teams/quality-gates
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';
7
+ declare const QUALITY_KINDS: readonly TaskKind[];
8
+ declare const WRITE_KINDS: readonly TaskKind[];
9
+ declare const DEFAULT_REVIEW_POLICY: Required<Pick<ReviewPolicy, 'requirementsMinRounds' | 'requirementsMaxRounds' | 'codeMaxRounds' | 'maxRepairAttempts'>>;
10
+ export type PathClassification = 'in_scope' | 'out_of_scope' | 'undeclared' | 'illegal';
11
+ export interface CreateTaskInput {
12
+ subject: string;
13
+ description?: string;
14
+ dependencies?: string[];
15
+ assignee?: string;
16
+ kind?: TaskKind;
17
+ round?: number;
18
+ objective?: string;
19
+ inScope?: string[];
20
+ outOfScope?: string[];
21
+ acceptance?: string[];
22
+ verify?: string[];
23
+ deliverables?: string[];
24
+ nonGoals?: string[];
25
+ reviewedTaskId?: string;
26
+ sourceTaskId?: string;
27
+ sourceFindingIds?: string[];
28
+ coverageOf?: string[];
29
+ resume?: boolean;
30
+ resumeReason?: string;
31
+ }
32
+ export interface ValidateCreateTaskResult {
33
+ ok: boolean;
34
+ error?: string;
35
+ kind?: TaskKind;
36
+ task?: Partial<TeamTask>;
37
+ team?: TeamState;
38
+ }
39
+ export interface QualityCompletionUpdate {
40
+ status?: TaskStatus;
41
+ output?: string;
42
+ verdict?: ReviewVerdict;
43
+ findings?: ReviewFinding[];
44
+ changedPaths?: string[];
45
+ acceptanceResults?: AcceptanceResult[];
46
+ commandsRun?: CommandResult[];
47
+ }
48
+ export interface QualityCompletionResult {
49
+ ok: boolean;
50
+ error?: string;
51
+ requiredStatus?: TaskStatus;
52
+ }
53
+ export interface PlannedFollowUpTask {
54
+ id?: string;
55
+ kind: TaskKind;
56
+ subject?: string;
57
+ assignee?: string;
58
+ dependencies?: string[];
59
+ round?: number;
60
+ objective?: string;
61
+ inScope?: string[];
62
+ outOfScope?: string[];
63
+ acceptance?: string[];
64
+ verify?: string[];
65
+ sourceTaskId?: string;
66
+ sourceFindingIds?: string[];
67
+ reviewedTaskId?: string;
68
+ }
69
+ export interface PlanQualityFollowUpResult {
70
+ created: PlannedFollowUpTask[];
71
+ tasks: PlannedFollowUpTask[];
72
+ escalated?: boolean;
73
+ status?: 'escalated';
74
+ }
75
+ export interface CoverageRow {
76
+ goal_item: string;
77
+ task_ids: string[];
78
+ status: 'missing' | 'in_progress' | 'passed' | 'blocked';
79
+ evidence?: string;
80
+ }
81
+ export interface DeliveryResult {
82
+ ok: boolean;
83
+ blockers: string[];
84
+ }
85
+ export interface ResumeTeamResult {
86
+ ok?: boolean;
87
+ status: 'resumed' | 'already_running' | 'rejected';
88
+ team?: TeamState;
89
+ error?: string;
90
+ }
91
+ export type QualityLoopState = 'running' | 'halted' | 'escalated' | 'deliverable' | 'blocked';
92
+ export interface QualityLoopSnapshot {
93
+ state: QualityLoopState;
94
+ halted: boolean;
95
+ escalated: boolean;
96
+ deliverable: boolean;
97
+ summary: string;
98
+ }
99
+ export interface QualityGraphDraft {
100
+ subject: string;
101
+ kind: TaskKind;
102
+ assignee?: string;
103
+ dependencies: string[];
104
+ objective: string;
105
+ acceptance: string[];
106
+ inScope?: string[];
107
+ verify?: string[];
108
+ coverageOf?: string[];
109
+ }
110
+ export declare const DEFAULT_REVIEW_ACCEPTANCE: readonly ["The latest implementation meets the user goal", "No unresolved blocker or high findings"];
111
+ export declare const DEFAULT_REVIEW_OBJECTIVE = "Review whether the latest implementation satisfies the user goal";
112
+ export declare function taskKindOf(task: Pick<TeamTask, 'kind'> | undefined): TaskKind;
113
+ export declare function isQualityKind(kind: TaskKind | undefined): boolean;
114
+ export declare function resolveReviewPolicy(policy: ReviewPolicy | undefined): Required<typeof DEFAULT_REVIEW_POLICY> & ReviewPolicy;
115
+ export declare function isReviewPolicy(value: unknown): value is ReviewPolicy;
116
+ /** Normalize a workspace-relative POSIX path. `undefined` means illegal. */
117
+ export declare function normalizeWorkspacePath(path: string): string | undefined;
118
+ export declare function pathMatchesScope(path: string, pattern: string): boolean;
119
+ export declare function classifyChangedPath(path: string, inScope?: readonly string[], outOfScope?: readonly string[]): PathClassification;
120
+ export declare function collectChangedPaths(gitStatusText: string): string[];
121
+ export declare function inScopeOverlap(left: readonly string[] | undefined, right: readonly string[] | undefined): string[];
122
+ export declare function validateCreateTask(team: TeamState, input: CreateTaskInput): ValidateCreateTaskResult;
123
+ export declare function evaluateQualityCompletion(task: TeamTask, update: QualityCompletionUpdate): QualityCompletionResult;
124
+ export declare function planQualityFollowUp(team: TeamState, closed: TeamTask): PlanQualityFollowUpResult;
125
+ export declare function buildCoverageMatrix(goalItems: readonly string[], tasks: readonly TeamTask[]): CoverageRow[];
126
+ export declare function canDeclareDelivery(team: TeamState): DeliveryResult;
127
+ export declare function resumeTeamState(team: TeamState, reason: string): ResumeTeamResult;
128
+ export declare function isReviewFinding(value: unknown): value is ReviewFinding;
129
+ export declare function isAcceptanceResult(value: unknown): value is AcceptanceResult;
130
+ export declare function isCommandResult(value: unknown): value is CommandResult;
131
+ export declare function hasValidQualityTaskFields(value: Record<string, unknown>): boolean;
132
+ export declare function isTaskKind(value: unknown): value is TaskKind;
133
+ export declare function isReviewVerdict(value: unknown): value is ReviewVerdict;
134
+ export declare function isFindingSeverity(value: unknown): value is FindingSeverity;
135
+ export declare function looksLikeGateTestContract(value: string | undefined): boolean;
136
+ export declare function sanitizeReviewObjective(value: string | undefined, fallback?: string): string;
137
+ export declare function sanitizeReviewAcceptance(values: readonly string[] | undefined): string[];
138
+ export declare function defaultQualityDeliveryGraph(input: {
139
+ goal: string;
140
+ implementer?: string;
141
+ reviewer?: string;
142
+ analyst?: string;
143
+ tester?: string;
144
+ integrator?: string;
145
+ }): QualityGraphDraft[];
146
+ export declare function qualityPlanningPrompt(): string;
147
+ export declare function describeQualityLoop(team: TeamState): QualityLoopSnapshot;
148
+ export { QUALITY_KINDS, WRITE_KINDS };
@@ -13,8 +13,14 @@
13
13
  */
14
14
  import type { Context } from '@deepseek-ai/cordis';
15
15
  import type { Agent } from '@deepseek-ai/dsh-agent';
16
+ import type { TeamTask } from './types.ts';
17
+ /** Per-dependency output cap in the assignment prompt. */
18
+ export declare const DEPENDENCY_OUTPUT_MAX_CHARS = 2000;
19
+ /** Combined dependency-output budget in the assignment prompt. */
20
+ export declare const DEPENDENCY_OUTPUTS_TOTAL_MAX_CHARS = 12000;
16
21
  export interface SchedulerConfig {
17
22
  readonly stateDir: string;
23
+ readonly executionPrompt?: string;
18
24
  }
19
25
  export interface TeamScheduler {
20
26
  /** Try to give every genuinely idle/ready member one unit of ready work. */
@@ -22,5 +28,43 @@ export interface TeamScheduler {
22
28
  /** Try to flush fallback mail or give one member one ready task. */
23
29
  kickMember(workspace: string, teamId: string, memberName: string, captain?: Agent): Promise<void>;
24
30
  }
31
+ /** One completed recursive dependency shown to the assignee. */
32
+ export interface DependencyOutput {
33
+ readonly id: string;
34
+ readonly subject: string;
35
+ readonly profileSeedId?: string;
36
+ readonly output?: string;
37
+ }
38
+ export interface DispatchTicket {
39
+ readonly taskId: string;
40
+ readonly memberName: string;
41
+ readonly memberId: string;
42
+ readonly attempt: number;
43
+ readonly attemptId: string;
44
+ readonly previousAssignee?: string;
45
+ readonly subject: string;
46
+ readonly description?: string;
47
+ readonly teamDescription?: string;
48
+ readonly profileProtocol?: string;
49
+ readonly profileSeedId?: string;
50
+ readonly dependencyOutputs: readonly DependencyOutput[];
51
+ readonly executionPrompt?: string;
52
+ readonly kind?: string;
53
+ readonly round?: number;
54
+ readonly objective?: string;
55
+ readonly inScope?: readonly string[];
56
+ readonly outOfScope?: readonly string[];
57
+ readonly acceptance?: readonly string[];
58
+ readonly verify?: readonly string[];
59
+ readonly reviewedTaskId?: string;
60
+ }
61
+ /**
62
+ * Recursively collect `status=completed` ancestors of `taskId` in topological
63
+ * order (dependencies before dependents). Cycles stop that branch only.
64
+ */
65
+ export declare function collectCompletedDependencyOutputs(tasks: readonly TeamTask[], taskId: string, warn?: (message: string) => void): DependencyOutput[];
66
+ /** Format completed-dependency outputs with per-item and total truncation. */
67
+ export declare function formatDependencyOutputs(items: readonly DependencyOutput[]): string;
68
+ export declare function assignmentPrompt(ticket: DispatchTicket, stateDir: string, teamId: string): string;
25
69
  /** Install one scheduler and its member activity observer. */
26
70
  export declare function installTeamScheduler(ctx: Context, config: SchedulerConfig): TeamScheduler;
@@ -10,12 +10,16 @@
10
10
  import type { Context } from '@deepseek-ai/cordis';
11
11
  import type { MemberStatus, TeamState } from './types.ts';
12
12
  /** Visual task state for the activity panel. */
13
- export type VisualTaskState = 'blocked' | 'open' | 'running' | 'completed';
13
+ export type VisualTaskState = 'blocked' | 'open' | 'running' | 'completed' | 'failed' | 'cancelled';
14
14
  /** One member row of the activity snapshot. */
15
15
  export interface TeamActivityMember {
16
16
  readonly id: string;
17
17
  readonly name: string;
18
18
  readonly role: string;
19
+ readonly provider: string;
20
+ readonly model: string;
21
+ readonly reasoningEffort: string;
22
+ readonly executionPrompt: string;
19
23
  readonly status: MemberStatus;
20
24
  readonly activity: 'working' | 'idle' | 'unknown';
21
25
  readonly progress: number;
@@ -28,11 +32,16 @@ export interface TeamActivityMember {
28
32
  export interface TeamActivityTask {
29
33
  readonly id: string;
30
34
  readonly subject: string;
35
+ readonly description: string;
31
36
  readonly status: string;
32
37
  readonly state: VisualTaskState;
33
38
  readonly assignee: string;
39
+ readonly model: string;
34
40
  readonly dependencies: readonly string[];
35
41
  readonly depth: number;
42
+ readonly kind?: string;
43
+ readonly round?: number;
44
+ readonly verdict?: string;
36
45
  }
37
46
  /** One captain-inbox preview row. */
38
47
  export interface TeamActivityMessage {
@@ -46,6 +55,9 @@ export interface TeamActivitySnapshot {
46
55
  readonly name: string;
47
56
  readonly description?: string;
48
57
  readonly captainSessionId: string;
58
+ readonly phase: 'staged' | 'running';
59
+ readonly planReviewState?: 'awaiting_review' | 'awaiting_feedback';
60
+ readonly halted?: boolean;
49
61
  readonly members: readonly TeamActivityMember[];
50
62
  readonly tasks: readonly TeamActivityTask[];
51
63
  readonly messageCount: number;
@@ -58,6 +70,11 @@ export interface TeamSnapshotOptions {
58
70
  /** Archived teams have no meaningful live activity after their sessions stop. */
59
71
  readonly historic?: boolean;
60
72
  }
73
+ /** Compact `provider/model` route for the activity panel, or just the model. */
74
+ export declare function memberModelRoute(member: {
75
+ provider?: string;
76
+ model?: string;
77
+ } | undefined): string;
61
78
  /**
62
79
  * Assemble one team snapshot from its durable files plus live activity.
63
80
  * @param ctx - the plugin context (injects `subagents`, used for activity).
@@ -12,7 +12,8 @@
12
12
  * `fs` service offers no directory deletion.
13
13
  * @module dsh-agent-teams/state
14
14
  */
15
- import type { TaskStatus, TeamMessage, TeamState, TeamTask } from './types.ts';
15
+ import { type TaskStatus, type TeamMessage, type TeamState, type TeamTask } from './types.ts';
16
+ export { buildCoverageMatrix, canDeclareDelivery, classifyChangedPath, collectChangedPaths, defaultQualityDeliveryGraph, describeQualityLoop, evaluateQualityCompletion, hasValidQualityTaskFields, isQualityKind, pathMatchesScope, planQualityFollowUp, qualityPlanningPrompt, resumeTeamState, sanitizeReviewAcceptance, sanitizeReviewObjective, taskKindOf, validateCreateTask, } from './quality-gates.ts';
16
17
  /** Mailbox key of the captain. */
17
18
  export declare const CAPTAIN_KEY = "captain";
18
19
  /**
@@ -69,6 +70,8 @@ export declare function beginTaskAttempt(task: TeamTask, assignee: string): stri
69
70
  * Revoke the current worker immediately. Clearing its capability makes old
70
71
  * updates stale; a separate handoff generation serializes async quiescence.
71
72
  */
73
+ /** Cancel one unfinished task without returning it to the ready pool. */
74
+ export declare function cancelUnfinishedTask(task: TeamTask, output?: string): void;
72
75
  export declare function invalidateTaskAttempt(task: TeamTask, nextAssignee?: string, reassigning?: boolean): void;
73
76
  /**
74
77
  * Create the team directory structure and the initial team record.
@@ -178,6 +181,7 @@ export interface AtomicReplaceOptions {
178
181
  * @returns nothing once the file has been replaced by one of the two paths.
179
182
  */
180
183
  export declare function replaceFileAtomicOrDirect(temporary: string, file: string, content: string, primitives: AtomicReplacePrimitives, options?: AtomicReplaceOptions): Promise<void>;
184
+ export declare function isTeamTask(value: unknown): value is TeamTask;
181
185
  /**
182
186
  * Remove a team's whole directory (members should be interrupted first).
183
187
  * @param stateRoot - resolved absolute state root directory.
@@ -208,10 +212,11 @@ export declare function readArchivedTeam(stateRoot: string, teamId: string): Pro
208
212
  */
209
213
  export declare function listArchivedTeamIds(stateRoot: string): Promise<string[]>;
210
214
  /** Visual task state for the activity panel. */
211
- export type VisualTaskState = 'blocked' | 'open' | 'running' | 'completed';
215
+ export type VisualTaskState = 'blocked' | 'open' | 'running' | 'completed' | 'failed' | 'cancelled';
212
216
  /**
213
217
  * The visual state of one task: `running` while in_progress, `completed`
214
- * when done, `blocked` while any dependency is unfinished, else `open`.
218
+ * when done, `failed`/`cancelled` when terminal without success, `blocked`
219
+ * while any dependency is unfinished, else `open`.
215
220
  */
216
221
  export declare function taskVisualState(status: string, dependencies: readonly string[], tasks: readonly TeamTask[]): VisualTaskState;
217
222
  /**
@@ -10,6 +10,7 @@
10
10
  */
11
11
  import type { Context } from '@deepseek-ai/cordis';
12
12
  import type { Agent } from '@deepseek-ai/dsh-agent';
13
+ import { type TeamState, type TeamTask } from './types.ts';
13
14
  /** Resolved plugin config consumed by the tools. */
14
15
  export interface ToolsConfig {
15
16
  /** State directory name under the captain's workspace. */
@@ -18,23 +19,86 @@ export interface ToolsConfig {
18
19
  memberProvider: string;
19
20
  /** Optional member model override. */
20
21
  memberModel?: string;
22
+ /** Prompt injected into member personas and assignments. */
23
+ executionPrompt?: string;
24
+ /** Plugin fallback route. */
25
+ fallback?: import('./profiles.ts').TeamModelFallbackConfig;
21
26
  /** Member delegation depth cap. */
22
27
  memberMaxDepth?: number;
23
28
  /** Team size cap (members). */
24
29
  maxMembers: number;
30
+ /** Named team profiles from the active DSH profile. */
31
+ profiles: Record<string, import('./profiles.ts').TeamProfileConfig>;
25
32
  }
26
- /**
27
- * Deliver a durable member report at the captain's nearest model boundary.
28
- *
29
- * `Agent.steer()` targets the next step while the captain is running, wakes a
30
- * new turn when it is idle, and lets the Agent runtime reclassify an aborted
31
- * activity to `next-turn`. This prevents reports from waiting behind the
32
- * captain's entire orchestration turn.
33
- */
33
+ /** Browser/UI mutations allowed while a plan is waiting for approval. */
34
+ export type StagedPlanMutation = {
35
+ action: 'update_member';
36
+ memberName: string;
37
+ role?: string | null;
38
+ provider: string;
39
+ model: string;
40
+ reasoningEffort?: string | null;
41
+ executionPrompt?: string | null;
42
+ } | {
43
+ action: 'update_task';
44
+ taskId: string;
45
+ subject: string;
46
+ description?: string | null;
47
+ assignee?: string | null;
48
+ dependencies: string[];
49
+ } | {
50
+ action: 'add_task';
51
+ subject: string;
52
+ description?: string | null;
53
+ assignee?: string | null;
54
+ dependencies: string[];
55
+ } | {
56
+ action: 'remove_task';
57
+ taskId: string;
58
+ } | {
59
+ action: 'remove_member';
60
+ memberName: string;
61
+ };
62
+ /** Runtime bridge shared by model-facing tools and the Web staging surface. */
63
+ export interface AgentTeamsRuntime {
64
+ updateStagedPlan(captain: Agent, teamId: string, mutation: StagedPlanMutation, signal?: AbortSignal): Promise<TeamState>;
65
+ updateStagedPlanBatch(captain: Agent, teamId: string, mutations: readonly StagedPlanMutation[], signal?: AbortSignal): Promise<TeamState>;
66
+ approveStagedTeam(captain: Agent, teamId: string, signal?: AbortSignal): Promise<{
67
+ teamId: string;
68
+ members: number;
69
+ tasks: number;
70
+ }>;
71
+ continueStagedPlanning(captain: Agent, teamId: string): Promise<{
72
+ teamId: string;
73
+ alreadyWaiting: boolean;
74
+ }>;
75
+ discardStagedTeam(captain: Agent, teamId: string): Promise<{
76
+ teamId: string;
77
+ }>;
78
+ }
79
+ export declare function haltTeamWork(input: {
80
+ ctx: Context;
81
+ stateRoot: string;
82
+ teamId: string;
83
+ captain: Agent;
84
+ signal?: AbortSignal;
85
+ }): Promise<{
86
+ teamName: string;
87
+ cancelledTasks: number;
88
+ alreadyHalted: boolean;
89
+ }>;
34
90
  export declare function steerCaptainReport(captain: Pick<Agent, 'steer'>, from: string, content: string): boolean;
91
+ /** Context queued after the human rejects a staged plan. */
92
+ export declare function stagedPlanDiscardContext(teamName: string): string;
93
+ /** Model-facing continuation that turns the review UI back into a conversation. */
94
+ export declare function stagedPlanFeedbackContext(teamName: string): string;
35
95
  /**
36
96
  * Register every `agent_teams_*` tool into the shared tools registry.
37
97
  * @param ctx - the plugin context (injects `tools`).
38
98
  * @param config - resolved tool config.
39
99
  */
40
- export declare function registerAgentTeamsTools(ctx: Context, config: ToolsConfig): void;
100
+ export declare function registerAgentTeamsTools(ctx: Context, config: ToolsConfig): AgentTeamsRuntime;
101
+ export declare function applyQualityFollowUp(team: TeamState, closed: TeamTask): {
102
+ created: TeamTask[];
103
+ escalated: boolean;
104
+ };