@qilin-agent/experimental-agent-team 0.0.0-stage → 3.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/LICENSE +21 -0
  2. package/README.i18n.yaml +103 -0
  3. package/README.md +225 -2
  4. package/README.zh.md +226 -0
  5. package/lib/index.js +1782 -0
  6. package/lib/typert.host.d.ts +3 -0
  7. package/lib/typert.host.js +875 -0
  8. package/lib/typert.remote-client.d.ts +30 -0
  9. package/lib/typert.remote-client.js +141 -0
  10. package/lib/types/activity.d.ts +23 -0
  11. package/lib/types/activity.js +85 -0
  12. package/lib/types/client.d.ts +8 -0
  13. package/lib/types/client.js +3 -0
  14. package/lib/types/error.d.ts +13 -0
  15. package/lib/types/error.js +23 -0
  16. package/lib/types/index.d.ts +148 -0
  17. package/lib/types/index.js +340 -0
  18. package/lib/types/journal.d.ts +39 -0
  19. package/lib/types/journal.js +63 -0
  20. package/lib/types/lifecycle.d.ts +45 -0
  21. package/lib/types/lifecycle.js +103 -0
  22. package/lib/types/persisted.d.ts +20 -0
  23. package/lib/types/persisted.js +20 -0
  24. package/lib/types/projection.d.ts +66 -0
  25. package/lib/types/projection.js +327 -0
  26. package/lib/types/remote.d.ts +31 -0
  27. package/lib/types/remote.js +22 -0
  28. package/lib/types/roster.d.ts +107 -0
  29. package/lib/types/roster.js +441 -0
  30. package/lib/types/session-message.d.ts +11 -0
  31. package/lib/types/session-message.js +23 -0
  32. package/lib/types/task-board.d.ts +53 -0
  33. package/lib/types/task-board.js +235 -0
  34. package/lib/types/task-graph.d.ts +21 -0
  35. package/lib/types/task-graph.js +62 -0
  36. package/lib/types/task-view.d.ts +21 -0
  37. package/lib/types/task-view.js +57 -0
  38. package/lib/types/types.d.ts +212 -0
  39. package/lib/types/types.js +26 -0
  40. package/lib/types/validation.d.ts +16 -0
  41. package/lib/types/validation.js +33 -0
  42. package/locale/en.json +6 -0
  43. package/locale/zh.json +6 -0
  44. package/package.json +83 -3
@@ -0,0 +1,66 @@
1
+ /** Team state projected incrementally from committed Session events, with a durable-only client view. */
2
+ import { z } from 'zod';
3
+ import type { SessionEvent, SessionId } from '@qilin-agent/session';
4
+ import type { TeamId, TeamMemberSnapshot, TeamMessageId, TeamMessageSnapshot, TeamProjection, TeamTaskSnapshot } from './types.ts';
5
+ /**
6
+ * Current Team state selected by durable Team identity. Every applied Team
7
+ * event produces a new state object and replaces only the collection it
8
+ * touched; untouched collections keep their references.
9
+ */
10
+ export interface TeamState {
11
+ readonly id: TeamId;
12
+ readonly members: readonly TeamMemberSnapshot[];
13
+ readonly tasks: readonly TeamTaskSnapshot[];
14
+ readonly messages: readonly TeamMessageSnapshot[];
15
+ readonly delivered: readonly TeamMessageId[];
16
+ readonly nextTaskNumber: number;
17
+ }
18
+ /**
19
+ * Construct empty state for one Team identity.
20
+ * @param rootId - root Session identity.
21
+ * @returns empty Team state.
22
+ */
23
+ export declare function emptyTeamState(rootId: SessionId): TeamProjectionState;
24
+ /** Checkpoint-safe state for the Team owned by the projected Session. */
25
+ export interface TeamProjectionState extends TeamState {
26
+ readonly failure?: string;
27
+ }
28
+ declare module '@qilin-agent/session-projection/types' {
29
+ interface SessionProjectionStateMap {
30
+ agentTeam: TeamProjectionState;
31
+ }
32
+ }
33
+ /** Whether one event belongs to the Team domain. */
34
+ export type TeamEventType = 'team/member' | 'team/task' | 'team/message/queued' | 'team/message/delivered';
35
+ /** One event owned by the Team domain. */
36
+ type TeamSessionEvent = SessionEvent<TeamEventType>;
37
+ /**
38
+ * Test whether a Session event belongs to the Team domain.
39
+ * @param event - candidate Session event.
40
+ * @returns whether the event has a Team-owned type.
41
+ */
42
+ export declare function isTeamEvent(event: SessionEvent): event is TeamSessionEvent;
43
+ declare function applyProjectionEvent(state: TeamProjectionState, event: SessionEvent): TeamProjectionState;
44
+ /**
45
+ * Durable client view of one Team state. Mailbox-only state changes reuse the
46
+ * previous view reference, so the live drive publishes nothing for them.
47
+ * A failure is terminal: later events retain the failed state reference and
48
+ * do not republish its view.
49
+ * @param state - current Team state.
50
+ * @returns the roster and non-deleted task board, plus any projection failure.
51
+ */
52
+ export declare function teamProjectionView(state: TeamProjectionState): TeamProjection;
53
+ /** Team projection selected by the projected Session identity; the wire view carries durable roster and task state only. */
54
+ export declare const teamProjectionDefinition: {
55
+ key: "agentTeam";
56
+ stateVersion: number;
57
+ stateSchema: z.ZodType<TeamProjectionState, unknown, z.core.$ZodTypeInternals<TeamProjectionState, unknown>>;
58
+ init: (header: import("@qilin-agent/session").SessionHeader) => TeamProjectionState;
59
+ apply: typeof applyProjectionEvent;
60
+ wire: {
61
+ viewSchema: z.ZodType<TeamProjection, unknown, z.core.$ZodTypeInternals<TeamProjection, unknown>>;
62
+ view: typeof teamProjectionView;
63
+ };
64
+ };
65
+ export {};
66
+ //# sourceMappingURL=projection.d.ts.map
@@ -0,0 +1,327 @@
1
+ /** Team state projected incrementally from committed Session events, with a durable-only client view. */
2
+ import { z } from 'zod';
3
+ import { brandString } from '@qilin-agent/brand';
4
+ import { TeamId as toTeamId, TeamMessageId as toTeamMessageId, TeamTaskId as toTeamTaskId, } from "./types.js";
5
+ import { assertTaskGraphCandidate } from "./task-graph.js";
6
+ import { projectTaskView } from "./task-view.js";
7
+ const nonNegativeSafeInteger = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
8
+ const positiveSafeInteger = nonNegativeSafeInteger.min(1);
9
+ const sessionIdSchema = z.string().min(1).transform(value => brandString(value));
10
+ const teamIdSchema = z.string().min(1).transform(value => toTeamId(value));
11
+ const numericTaskIdPattern = /^task-(\d+)$/u;
12
+ const teamTaskIdSchema = z.string().min(1).refine((value) => {
13
+ const match = numericTaskIdPattern.exec(value);
14
+ return match === null || Number.isSafeInteger(Number(match[1]));
15
+ }, { message: 'numeric task id suffix must be a safe integer' }).transform(value => toTeamTaskId(value));
16
+ const teamMessageIdSchema = z.string().min(1).transform(value => toTeamMessageId(value));
17
+ const coreContentBlockTypes = new Set(['text', 'reasoning', 'image', 'tool-call', 'tool-result']);
18
+ const imageAttachmentSchema = z.object({
19
+ attachmentId: z.string().min(1),
20
+ mediaType: z.enum(['image/png', 'image/jpeg', 'image/webp', 'image/gif']),
21
+ bytes: nonNegativeSafeInteger,
22
+ width: positiveSafeInteger,
23
+ height: positiveSafeInteger,
24
+ name: z.string().optional(),
25
+ }).strict();
26
+ // Validate the listed variants; retired tool-result tags cannot enter the
27
+ // merge-extensible fallback for JSON-decoded plugin content.
28
+ const contentBlockSchema = z.lazy(() => z.union([
29
+ z.object({ type: z.literal('text'), text: z.string() }).strict(),
30
+ z.object({ type: z.literal('reasoning'), text: z.string() }).strict(),
31
+ z.object({ type: z.literal('image'), attachment: imageAttachmentSchema }).strict(),
32
+ z.object({
33
+ type: z.literal('tool-call'),
34
+ id: z.string().min(1),
35
+ name: z.string(),
36
+ arguments: z.string(),
37
+ }).strict(),
38
+ // Keep unknown JSON objects by reference; loose-object parsing drops their own __proto__ keys.
39
+ z.custom((value) => {
40
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
41
+ return false;
42
+ const type = value.type;
43
+ return typeof type === 'string' && type.length > 0 && !coreContentBlockTypes.has(type);
44
+ }),
45
+ ]));
46
+ const teamMemberSnapshotSchema = z.object({
47
+ id: sessionIdSchema,
48
+ name: z.string(),
49
+ description: z.string(),
50
+ provider: z.string(),
51
+ context: z.enum(['fresh', 'fork']),
52
+ phase: z.enum(['provisioning', 'active', 'failed']),
53
+ error: z.string().optional(),
54
+ }).strict();
55
+ const teamTaskSnapshotSchema = z.object({
56
+ id: teamTaskIdSchema,
57
+ revision: positiveSafeInteger,
58
+ subject: z.string(),
59
+ description: z.string(),
60
+ status: z.enum(['pending', 'in_progress', 'completed', 'deleted']),
61
+ ownerId: sessionIdSchema.optional(),
62
+ blockedBy: z.array(teamTaskIdSchema),
63
+ writeScopes: z.array(z.string()),
64
+ }).strict();
65
+ const teamMessageSnapshotSchema = z.object({
66
+ id: teamMessageIdSchema,
67
+ senderId: sessionIdSchema,
68
+ senderName: z.string(),
69
+ targetId: sessionIdSchema,
70
+ content: z.array(contentBlockSchema),
71
+ }).strict();
72
+ const teamEventSelectorSchema = z.object({
73
+ version: nonNegativeSafeInteger,
74
+ teamId: teamIdSchema,
75
+ }).loose();
76
+ const teamMemberEventSchema = z.object({
77
+ version: z.literal(2),
78
+ teamId: teamIdSchema,
79
+ member: teamMemberSnapshotSchema,
80
+ }).strict();
81
+ const teamTaskEventSchema = z.object({
82
+ version: z.literal(2),
83
+ teamId: teamIdSchema,
84
+ task: teamTaskSnapshotSchema,
85
+ }).strict();
86
+ const teamMessageQueuedEventSchema = z.object({
87
+ version: z.literal(2),
88
+ teamId: teamIdSchema,
89
+ message: teamMessageSnapshotSchema,
90
+ }).strict();
91
+ const teamMessageDeliveredEventSchema = z.object({
92
+ version: z.literal(2),
93
+ teamId: teamIdSchema,
94
+ messageId: teamMessageIdSchema,
95
+ targetId: sessionIdSchema,
96
+ }).strict();
97
+ /**
98
+ * Construct empty state for one Team identity.
99
+ * @param rootId - root Session identity.
100
+ * @returns empty Team state.
101
+ */
102
+ export function emptyTeamState(rootId) {
103
+ return {
104
+ id: toTeamId(rootId),
105
+ members: [],
106
+ tasks: [],
107
+ messages: [],
108
+ delivered: [],
109
+ nextTaskNumber: 1,
110
+ };
111
+ }
112
+ const teamProjectionEntrySchema = z.object({
113
+ id: teamIdSchema,
114
+ members: z.array(teamMemberSnapshotSchema),
115
+ tasks: z.array(teamTaskSnapshotSchema),
116
+ messages: z.array(teamMessageSnapshotSchema),
117
+ delivered: z.array(teamMessageIdSchema),
118
+ nextTaskNumber: positiveSafeInteger,
119
+ failure: z.string().optional(),
120
+ }).strict();
121
+ /**
122
+ * Test whether a Session event belongs to the Team domain.
123
+ * @param event - candidate Session event.
124
+ * @returns whether the event has a Team-owned type.
125
+ */
126
+ export function isTeamEvent(event) {
127
+ return event.type === 'team/member'
128
+ || event.type === 'team/task'
129
+ || event.type === 'team/message/queued'
130
+ || event.type === 'team/message/delivered';
131
+ }
132
+ /** Decode one persisted Team value and retain the schema failure as its cause. */
133
+ function parsePersisted(type, schema, value) {
134
+ try {
135
+ return schema.parse(value);
136
+ }
137
+ catch (error) {
138
+ throw new Error(`persisted Agent Teams ${type} payload is invalid`, { cause: error });
139
+ }
140
+ }
141
+ /** Decode the complete current-version payload selected by one Team event type. */
142
+ function parseCurrentTeamEvent(event) {
143
+ switch (event.type) {
144
+ case 'team/member':
145
+ return { ...event, data: parsePersisted(event.type, teamMemberEventSchema, event.data) };
146
+ case 'team/task':
147
+ return { ...event, data: parsePersisted(event.type, teamTaskEventSchema, event.data) };
148
+ case 'team/message/queued':
149
+ return { ...event, data: parsePersisted(event.type, teamMessageQueuedEventSchema, event.data) };
150
+ case 'team/message/delivered':
151
+ return { ...event, data: parsePersisted(event.type, teamMessageDeliveredEventSchema, event.data) };
152
+ /* v8 ignore next 2 -- TeamEventType is closed and every member is handled above. */
153
+ default:
154
+ return event;
155
+ }
156
+ }
157
+ function applyProjectionEvent(state, event) {
158
+ if (state.failure !== undefined)
159
+ return state;
160
+ if (!isTeamEvent(event))
161
+ return state;
162
+ try {
163
+ const selector = parsePersisted(event.type, teamEventSelectorSchema, event.data);
164
+ if (selector.teamId !== state.id)
165
+ return state;
166
+ if (selector.version !== 2) {
167
+ throw new Error(`unsupported Agent Teams event version ${String(selector.version)}`);
168
+ }
169
+ return applyCurrentTeamEvent(state, parseCurrentTeamEvent(event));
170
+ }
171
+ catch (error) {
172
+ /* v8 ignore next -- the owned Team transition throws Error instances. */
173
+ return { ...state, failure: error instanceof Error ? error.message : String(error) };
174
+ }
175
+ }
176
+ function replaceAt(items, index, item) {
177
+ const next = [...items];
178
+ if (index < 0)
179
+ next.push(item);
180
+ else
181
+ next[index] = item;
182
+ return next;
183
+ }
184
+ function applyCurrentTeamEvent(state, event) {
185
+ switch (event.type) {
186
+ case 'team/member': {
187
+ const member = event.data.member;
188
+ const index = state.members.findIndex(candidate => candidate.id === member.id);
189
+ const prior = state.members[index];
190
+ const named = state.members.find(candidate => candidate.name === member.name);
191
+ if (named !== undefined && named.id !== member.id) {
192
+ throw new Error(`teammate name "${member.name}" is reused by another member`);
193
+ }
194
+ if (prior === undefined) {
195
+ if (member.phase !== 'provisioning')
196
+ throw new Error(`teammate "${member.name}" must begin provisioning`);
197
+ }
198
+ else {
199
+ if (prior.name !== member.name || prior.provider !== member.provider || prior.context !== member.context) {
200
+ throw new Error(`teammate "${member.id}" changed immutable identity fields`);
201
+ }
202
+ if (prior.phase !== 'provisioning' || member.phase === 'provisioning') {
203
+ throw new Error(`teammate "${member.name}" has an invalid ${prior.phase} -> ${member.phase} transition`);
204
+ }
205
+ }
206
+ return { ...state, members: replaceAt(state.members, index, member) };
207
+ }
208
+ case 'team/task': {
209
+ const task = event.data.task;
210
+ const index = state.tasks.findIndex(candidate => candidate.id === task.id);
211
+ const prior = state.tasks[index];
212
+ if (prior === undefined && task.revision !== 1) {
213
+ throw new Error(`team task "${task.id}" must begin at revision 1`);
214
+ }
215
+ if (prior !== undefined && task.revision !== prior.revision + 1) {
216
+ throw new Error(`team task "${task.id}" revision is not contiguous`);
217
+ }
218
+ assertTaskGraphCandidate(state.tasks, task);
219
+ let nextTaskNumber = state.nextTaskNumber;
220
+ const match = numericTaskIdPattern.exec(task.id);
221
+ if (match !== null) {
222
+ const number = Number(match[1]);
223
+ nextTaskNumber = Math.max(nextTaskNumber, number === Number.MAX_SAFE_INTEGER ? number : number + 1);
224
+ }
225
+ return { ...state, tasks: replaceAt(state.tasks, index, task), nextTaskNumber };
226
+ }
227
+ case 'team/message/queued': {
228
+ const message = event.data.message;
229
+ if (state.messages.some(candidate => candidate.id === message.id)) {
230
+ throw new Error(`team message "${message.id}" was queued twice`);
231
+ }
232
+ return { ...state, messages: [...state.messages, message] };
233
+ }
234
+ case 'team/message/delivered': {
235
+ const queued = state.messages.find(message => message.id === event.data.messageId);
236
+ if (queued === undefined)
237
+ throw new Error(`team message "${event.data.messageId}" was delivered before queueing`);
238
+ if (queued.targetId !== event.data.targetId)
239
+ throw new Error(`team message "${event.data.messageId}" target changed`);
240
+ if (state.delivered.includes(event.data.messageId))
241
+ throw new Error(`team message "${event.data.messageId}" was delivered twice`);
242
+ return { ...state, delivered: [...state.delivered, event.data.messageId] };
243
+ }
244
+ /* v8 ignore next 2 -- TeamEventType is closed and every member is handled above. */
245
+ default:
246
+ return state;
247
+ }
248
+ }
249
+ const teamMemberProjectionSchema = z.object({
250
+ id: sessionIdSchema,
251
+ name: z.string(),
252
+ role: z.enum(['lead', 'teammate']),
253
+ phase: z.enum(['provisioning', 'active', 'failed']),
254
+ error: z.string().optional(),
255
+ }).strict();
256
+ const teamTaskViewSchema = z.object({
257
+ id: teamTaskIdSchema,
258
+ revision: positiveSafeInteger,
259
+ subject: z.string(),
260
+ description: z.string(),
261
+ status: z.enum(['pending', 'in_progress', 'completed', 'deleted']),
262
+ blockedBy: z.array(teamTaskIdSchema),
263
+ writeScopes: z.array(z.string()),
264
+ ownerName: z.string().optional(),
265
+ ready: z.boolean(),
266
+ writeScopeWarnings: z.array(z.string()),
267
+ }).strict();
268
+ const teamProjectionSchema = z.object({
269
+ members: z.array(teamMemberProjectionSchema),
270
+ tasks: z.array(teamTaskViewSchema),
271
+ failure: z.string().optional(),
272
+ }).strict();
273
+ /** Client views keyed by the member and task collections they were derived from. */
274
+ const teamProjectionViews = new WeakMap();
275
+ function buildTeamProjection(state) {
276
+ const rootId = brandString(state.id);
277
+ const members = [{ id: rootId, name: 'lead', role: 'lead', phase: 'active' }];
278
+ for (const member of state.members) {
279
+ members.push({
280
+ id: member.id,
281
+ name: member.name,
282
+ role: 'teammate',
283
+ phase: member.phase,
284
+ ...member.error === undefined ? {} : { error: member.error },
285
+ });
286
+ }
287
+ return {
288
+ members,
289
+ tasks: state.tasks
290
+ .filter(task => task.status !== 'deleted')
291
+ .map(task => projectTaskView(state, task)),
292
+ ...state.failure === undefined ? {} : { failure: state.failure },
293
+ };
294
+ }
295
+ /**
296
+ * Durable client view of one Team state. Mailbox-only state changes reuse the
297
+ * previous view reference, so the live drive publishes nothing for them.
298
+ * A failure is terminal: later events retain the failed state reference and
299
+ * do not republish its view.
300
+ * @param state - current Team state.
301
+ * @returns the roster and non-deleted task board, plus any projection failure.
302
+ */
303
+ export function teamProjectionView(state) {
304
+ if (state.failure !== undefined)
305
+ return buildTeamProjection(state);
306
+ let byTasks = teamProjectionViews.get(state.members);
307
+ if (byTasks === undefined) {
308
+ byTasks = new WeakMap();
309
+ teamProjectionViews.set(state.members, byTasks);
310
+ }
311
+ let view = byTasks.get(state.tasks);
312
+ if (view === undefined) {
313
+ view = buildTeamProjection(state);
314
+ byTasks.set(state.tasks, view);
315
+ }
316
+ return view;
317
+ }
318
+ /** Team projection selected by the projected Session identity; the wire view carries durable roster and task state only. */
319
+ export const teamProjectionDefinition = {
320
+ key: 'agentTeam',
321
+ stateVersion: 4,
322
+ stateSchema: teamProjectionEntrySchema,
323
+ init: header => emptyTeamState(header.id),
324
+ apply: applyProjectionEvent,
325
+ wire: { viewSchema: teamProjectionSchema, view: teamProjectionView },
326
+ };
327
+ //# sourceMappingURL=projection.js.map
@@ -0,0 +1,31 @@
1
+ /** Wire failure mapping for the Team service's browser write face. */
2
+ /** Wire details the Team domain carries on its catch-all refusal code. */
3
+ export interface TeamRejectedFailureDetails {
4
+ /** The stable Team failure class, as the domain's `TeamError` code names it. */
5
+ readonly code: string;
6
+ }
7
+ declare module '@qilin-agent/typert-protocol' {
8
+ interface RemoteErrorDetailsMap {
9
+ /** The wire identity resolves to a Session that is not a Team member. */
10
+ 'agent-team/not-a-member': {};
11
+ /**
12
+ * The compare-and-set revision no longer matches the durable task; the
13
+ * mutation was refused. The board projection carries the current revisions.
14
+ */
15
+ 'agent-team/stale-revision': {};
16
+ /**
17
+ * The Team domain refused the request for a reason without a dedicated
18
+ * wire code; `code` names the stable Team failure class.
19
+ */
20
+ 'agent-team/rejected': TeamRejectedFailureDetails;
21
+ }
22
+ }
23
+ /**
24
+ * Map one Team-domain failure onto the shared Remote failure vocabulary so the
25
+ * browser can branch on a stable code. Unknown values pass through unchanged
26
+ * and surface as `gateway/internal`.
27
+ * @param error - the value thrown by the Team domain operation.
28
+ * @returns the value to rethrow from the wire method.
29
+ */
30
+ export declare function teamWireError(error: unknown): unknown;
31
+ //# sourceMappingURL=remote.d.ts.map
@@ -0,0 +1,22 @@
1
+ /** Wire failure mapping for the Team service's browser write face. */
2
+ import { RemoteError } from '@qilin-agent/typert-protocol';
3
+ import { TeamError } from "./error.js";
4
+ /**
5
+ * Map one Team-domain failure onto the shared Remote failure vocabulary so the
6
+ * browser can branch on a stable code. Unknown values pass through unchanged
7
+ * and surface as `gateway/internal`.
8
+ * @param error - the value thrown by the Team domain operation.
9
+ * @returns the value to rethrow from the wire method.
10
+ */
11
+ export function teamWireError(error) {
12
+ if (!(error instanceof TeamError))
13
+ return error;
14
+ if (error.code === 'TEAM_TASK_STALE_REVISION') {
15
+ return new RemoteError('agent-team/stale-revision', error.message, {});
16
+ }
17
+ if (error.code === 'TEAM_NOT_MEMBER') {
18
+ return new RemoteError('agent-team/not-a-member', error.message, {});
19
+ }
20
+ return new RemoteError('agent-team/rejected', error.message, { code: error.code });
21
+ }
22
+ //# sourceMappingURL=remote.js.map
@@ -0,0 +1,107 @@
1
+ /** Team membership, continuable-child provisioning, and roster-owned teardown. */
2
+ import type { Context } from '@qilin-agent/kylin';
3
+ import type { Agent } from '@qilin-agent/agent';
4
+ import type { SessionId } from '@qilin-agent/session';
5
+ import type { TeamJournal } from './journal.ts';
6
+ import type { TeamRuntimeLifecycle } from './lifecycle.ts';
7
+ import type { TeamState } from './projection.ts';
8
+ import { TeamId } from './types.ts';
9
+ import type { SpawnTeammateRequest, SpawnTeammateResult, TeamMemberView } from './types.ts';
10
+ /** Caller identity inside one implicit Team. */
11
+ export interface TeamMembership {
12
+ readonly root: Agent;
13
+ readonly id: TeamId;
14
+ readonly role: 'lead' | 'teammate';
15
+ readonly name: string;
16
+ }
17
+ /**
18
+ * Resolve one active Team member by model-facing name, including the Lead pseudo-row.
19
+ * @param root - exact live Team Lead.
20
+ * @param state - current Team state.
21
+ * @param rawName - candidate member name.
22
+ * @returns resolved durable id and normalized name.
23
+ */
24
+ export declare function resolveActiveMember(root: Agent, state: TeamState, rawName: string): {
25
+ id: SessionId;
26
+ name: string;
27
+ };
28
+ /** Owns Team identities and the lifecycle of rostered continuable children. */
29
+ export declare class TeamRoster {
30
+ private readonly ctx;
31
+ private readonly journal;
32
+ private readonly lifecycle;
33
+ private readonly maxMembers;
34
+ /**
35
+ * @param ctx - Team service context with Agent, Session, persistence, and subagent services.
36
+ * @param journal - authoritative Lead-log transaction owner.
37
+ * @param lifecycle - shared Team runtime admission cutoff.
38
+ * @param maxMembers - maximum immutable roster entries per Team.
39
+ */
40
+ constructor(ctx: Context, journal: TeamJournal, lifecycle: TeamRuntimeLifecycle, maxMembers: number);
41
+ /**
42
+ * Resolve one exact live Agent's Team role.
43
+ * @param agent - exact live Agent used as the authority credential.
44
+ * @returns its root, Team identity, role, and model-facing name.
45
+ */
46
+ membership(agent: Agent): TeamMembership;
47
+ /**
48
+ * Resolve a caller without throwing for scoped installation and lifecycle observers.
49
+ * @param agent - candidate exact live Agent.
50
+ * @returns Team membership, or undefined for non-Team subagents and stale identities.
51
+ */
52
+ tryMembership(agent: Agent): TeamMembership | undefined;
53
+ /**
54
+ * List the runtime-enriched roster visible to one Team member.
55
+ * @param membership - exact caller membership resolved by this roster.
56
+ * @returns Lead and teammate rows in creation order.
57
+ */
58
+ list(membership: TeamMembership): TeamMemberView[];
59
+ /**
60
+ * Create one named, continuable direct child of the Team Lead.
61
+ * @param caller - exact live Lead Agent.
62
+ * @param request - immutable name, description, prompt, context mode, provider, and cancellation.
63
+ * @returns the active roster row.
64
+ */
65
+ spawn(caller: Agent, request: SpawnTeammateRequest): Promise<SpawnTeammateResult>;
66
+ /**
67
+ * Reconcile provisioning state when one Team member Session starts.
68
+ * @param agent - newly started exact live Agent.
69
+ * @param signal - shared runtime cancellation.
70
+ */
71
+ recoverFor(agent: Agent, signal: AbortSignal): Promise<void>;
72
+ /**
73
+ * Interrupt one live teammate turn without clearing its pending inbox.
74
+ * @param caller - exact live Lead Agent.
75
+ * @param targetName - durable teammate name.
76
+ * @returns the target status sampled before cancellation.
77
+ */
78
+ interrupt(caller: Agent, targetName: string): {
79
+ previousStatus: 'running' | 'inactive';
80
+ };
81
+ /**
82
+ * Group exact live roster children by their current Lead for runtime teardown.
83
+ * @returns each live Lead and the roster child ids currently in the Agent registry.
84
+ */
85
+ liveChildrenByRoot(): Map<Agent, SessionId[]>;
86
+ /**
87
+ * Release exact teammate Activations through the continuation lifecycle owner.
88
+ * @param root - exact live Team Lead authorizing release.
89
+ * @param childIds - selected roster child ids.
90
+ */
91
+ stopTeammates(root: Agent, childIds: readonly SessionId[]): Promise<void>;
92
+ /** Perform one creation admitted before the Team runtime disposal cutoff. */
93
+ private spawnAdmitted;
94
+ /** Flush the accepted initial inbox item before the Lead can commit `active`. */
95
+ private checkpointInitialPrompt;
96
+ /** Settle provisioning-only members from their independently durable child Sessions. */
97
+ private reconcileProvisioning;
98
+ /** Build one runtime member row after successful creation. */
99
+ private memberView;
100
+ /** Validate a never-reused model-facing teammate name. */
101
+ private memberName;
102
+ /** Append one terminal provisioning edge unless recovery already settled it. */
103
+ private settleProvisioning;
104
+ /** Whether a Session's own suffix identifies a provider-owned subagent child. */
105
+ private subagentDescriptor;
106
+ }
107
+ //# sourceMappingURL=roster.d.ts.map