@deepseek-ai/dsh-experimental-agent-team 0.1.5-alpha.2

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 (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.i18n.yaml +6 -0
  3. package/README.md +220 -0
  4. package/README.zh.md +220 -0
  5. package/lib/index.js +1894 -0
  6. package/lib/invariant.js +361 -0
  7. package/lib/typert.host.d.ts +3 -0
  8. package/lib/typert.host.js +867 -0
  9. package/lib/typert.remote-client.d.ts +32 -0
  10. package/lib/typert.remote-client.js +210 -0
  11. package/lib/types/activity.d.ts +23 -0
  12. package/lib/types/activity.js +85 -0
  13. package/lib/types/client.d.ts +3 -0
  14. package/lib/types/client.js +3 -0
  15. package/lib/types/error.d.ts +13 -0
  16. package/lib/types/error.js +23 -0
  17. package/lib/types/index.d.ts +137 -0
  18. package/lib/types/index.js +313 -0
  19. package/lib/types/invariant.d.ts +9 -0
  20. package/lib/types/invariant.js +26 -0
  21. package/lib/types/journal.d.ts +39 -0
  22. package/lib/types/journal.js +63 -0
  23. package/lib/types/lifecycle.d.ts +33 -0
  24. package/lib/types/lifecycle.js +85 -0
  25. package/lib/types/mailbox.d.ts +78 -0
  26. package/lib/types/mailbox.js +292 -0
  27. package/lib/types/persisted.d.ts +20 -0
  28. package/lib/types/persisted.js +20 -0
  29. package/lib/types/projection.d.ts +48 -0
  30. package/lib/types/projection.js +260 -0
  31. package/lib/types/roster.d.ts +113 -0
  32. package/lib/types/roster.js +446 -0
  33. package/lib/types/session-message.d.ts +11 -0
  34. package/lib/types/session-message.js +23 -0
  35. package/lib/types/task-board.d.ts +62 -0
  36. package/lib/types/task-board.js +275 -0
  37. package/lib/types/task-graph.d.ts +21 -0
  38. package/lib/types/task-graph.js +62 -0
  39. package/lib/types/types.d.ts +206 -0
  40. package/lib/types/types.js +26 -0
  41. package/lib/types/validation.d.ts +16 -0
  42. package/lib/types/validation.js +33 -0
  43. package/package.json +88 -0
@@ -0,0 +1,361 @@
1
+ import { z } from "zod";
2
+ import { brandString } from "@deepseek-ai/dsh-brand";
3
+ //#region lib/types/types.js
4
+ /** Public Agent Teams identities, durable records, and service request values. */
5
+ /**
6
+ * Brand one root Session identity as its implicit Team identity.
7
+ * @param id - Root Session identity.
8
+ * @returns the same string branded as a Team identity.
9
+ */
10
+ function TeamId(id) {
11
+ return id;
12
+ }
13
+ /**
14
+ * Brand a validated task id.
15
+ * @param id - Team-local task identity.
16
+ * @returns the same string branded as a Team task identity.
17
+ */
18
+ function TeamTaskId(id) {
19
+ return id;
20
+ }
21
+ /**
22
+ * Brand a generated peer-message id.
23
+ * @param id - Durable mailbox message identity.
24
+ * @returns the same string branded as a Team message identity.
25
+ */
26
+ function TeamMessageId(id) {
27
+ return id;
28
+ }
29
+ //#endregion
30
+ //#region lib/types/task-graph.js
31
+ /** Complete dependency validation for current Team task snapshots. */
32
+ /** Package-private task dependency failure retained for command error mapping. */
33
+ var TeamTaskGraphError = class extends Error {
34
+ violation;
35
+ /**
36
+ * @param message - concrete invalid dependency relation.
37
+ * @param violation - stable relation category used by Team commands.
38
+ */
39
+ constructor(message, violation) {
40
+ super(message);
41
+ this.violation = violation;
42
+ this.name = "TeamTaskGraphError";
43
+ }
44
+ };
45
+ /**
46
+ * Validate the complete active task graph after replacing one candidate snapshot.
47
+ * @param current - current task snapshots before the candidate event.
48
+ * @param candidate - new or next-revision task snapshot.
49
+ * @throws {TeamTaskGraphError} when an active dependency is missing, duplicated, self-referential, or cyclic.
50
+ */
51
+ function assertTaskGraphCandidate(current, candidate) {
52
+ const tasks = new Map(current.map((task) => [task.id, task]));
53
+ tasks.set(candidate.id, candidate);
54
+ for (const task of tasks.values()) {
55
+ if (task.status === "deleted") continue;
56
+ const seen = /* @__PURE__ */ new Set();
57
+ for (const blockerId of task.blockedBy) {
58
+ if (blockerId === task.id) throw new TeamTaskGraphError(`team task "${task.id}" cannot block itself`, "cycle");
59
+ if (seen.has(blockerId)) throw new TeamTaskGraphError(`team task "${task.id}" repeats blocker "${blockerId}"`, "duplicate");
60
+ const blocker = tasks.get(blockerId);
61
+ if (blocker === void 0 || blocker.status === "deleted") throw new TeamTaskGraphError(`blocker task "${blockerId}" for "${task.id}" is missing or deleted`, "missing");
62
+ seen.add(blockerId);
63
+ }
64
+ }
65
+ const visiting = /* @__PURE__ */ new Set();
66
+ const visited = /* @__PURE__ */ new Set();
67
+ const visit = (id) => {
68
+ if (visiting.has(id)) throw new TeamTaskGraphError(`task dependency cycle includes "${id}"`, "cycle");
69
+ if (visited.has(id)) return;
70
+ const task = tasks.get(id);
71
+ if (task === void 0 || task.status === "deleted") return;
72
+ visiting.add(id);
73
+ for (const blockerId of task.blockedBy) visit(blockerId);
74
+ visiting.delete(id);
75
+ visited.add(id);
76
+ };
77
+ for (const task of tasks.values()) visit(task.id);
78
+ }
79
+ //#endregion
80
+ //#region lib/types/projection.js
81
+ /** Host-only Team state projected incrementally from committed Session events. */
82
+ const nonNegativeSafeInteger = z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
83
+ const positiveSafeInteger = nonNegativeSafeInteger.min(1);
84
+ const sessionIdSchema = z.string().min(1).transform((value) => brandString(value));
85
+ const teamIdSchema = z.string().min(1).transform((value) => TeamId(value));
86
+ const numericTaskIdPattern = /^task-(\d+)$/u;
87
+ const teamTaskIdSchema = z.string().min(1).refine((value) => {
88
+ const match = numericTaskIdPattern.exec(value);
89
+ return match === null || Number.isSafeInteger(Number(match[1]));
90
+ }, { message: "numeric task id suffix must be a safe integer" }).transform((value) => TeamTaskId(value));
91
+ const teamMessageIdSchema = z.string().min(1).transform((value) => TeamMessageId(value));
92
+ const coreContentBlockTypes = new Set([
93
+ "text",
94
+ "reasoning",
95
+ "image",
96
+ "tool-call",
97
+ "tool-result"
98
+ ]);
99
+ const imageAttachmentSchema = z.object({
100
+ attachmentId: z.string().min(1),
101
+ mediaType: z.enum([
102
+ "image/png",
103
+ "image/jpeg",
104
+ "image/webp",
105
+ "image/gif"
106
+ ]),
107
+ bytes: nonNegativeSafeInteger,
108
+ width: positiveSafeInteger,
109
+ height: positiveSafeInteger,
110
+ name: z.string().optional()
111
+ }).strict();
112
+ const contentBlockSchema = z.lazy(() => z.union([
113
+ z.object({
114
+ type: z.literal("text"),
115
+ text: z.string()
116
+ }).strict(),
117
+ z.object({
118
+ type: z.literal("reasoning"),
119
+ text: z.string()
120
+ }).strict(),
121
+ z.object({
122
+ type: z.literal("image"),
123
+ attachment: imageAttachmentSchema
124
+ }).strict(),
125
+ z.object({
126
+ type: z.literal("tool-call"),
127
+ id: z.string().min(1),
128
+ name: z.string(),
129
+ arguments: z.string()
130
+ }).strict(),
131
+ z.object({
132
+ type: z.literal("tool-result"),
133
+ toolCallId: z.string().min(1),
134
+ content: z.array(contentBlockSchema),
135
+ isError: z.boolean().optional()
136
+ }).strict(),
137
+ z.object({ type: z.string().min(1) }).loose().refine((block) => !coreContentBlockTypes.has(block.type), { message: "known content block types must match their declared fields" })
138
+ ]));
139
+ const teamMemberSnapshotSchema = z.object({
140
+ id: sessionIdSchema,
141
+ name: z.string(),
142
+ description: z.string(),
143
+ provider: z.string(),
144
+ context: z.enum(["fresh", "fork"]),
145
+ phase: z.enum([
146
+ "provisioning",
147
+ "active",
148
+ "failed"
149
+ ]),
150
+ error: z.string().optional()
151
+ }).strict();
152
+ const teamTaskSnapshotSchema = z.object({
153
+ id: teamTaskIdSchema,
154
+ revision: positiveSafeInteger,
155
+ subject: z.string(),
156
+ description: z.string(),
157
+ status: z.enum([
158
+ "pending",
159
+ "in_progress",
160
+ "completed",
161
+ "deleted"
162
+ ]),
163
+ ownerId: sessionIdSchema.optional(),
164
+ blockedBy: z.array(teamTaskIdSchema),
165
+ writeScopes: z.array(z.string())
166
+ }).strict();
167
+ const teamMessageSnapshotSchema = z.object({
168
+ id: teamMessageIdSchema,
169
+ senderId: sessionIdSchema,
170
+ senderName: z.string(),
171
+ targetId: sessionIdSchema,
172
+ content: z.array(contentBlockSchema)
173
+ }).strict();
174
+ const teamEventSelectorSchema = z.object({
175
+ version: nonNegativeSafeInteger,
176
+ teamId: teamIdSchema
177
+ }).loose();
178
+ const teamMemberEventSchema = z.object({
179
+ version: z.literal(2),
180
+ teamId: teamIdSchema,
181
+ member: teamMemberSnapshotSchema
182
+ }).strict();
183
+ const teamTaskEventSchema = z.object({
184
+ version: z.literal(2),
185
+ teamId: teamIdSchema,
186
+ task: teamTaskSnapshotSchema
187
+ }).strict();
188
+ const teamMessageQueuedEventSchema = z.object({
189
+ version: z.literal(2),
190
+ teamId: teamIdSchema,
191
+ message: teamMessageSnapshotSchema
192
+ }).strict();
193
+ const teamMessageDeliveredEventSchema = z.object({
194
+ version: z.literal(2),
195
+ teamId: teamIdSchema,
196
+ messageId: teamMessageIdSchema,
197
+ targetId: sessionIdSchema
198
+ }).strict();
199
+ /**
200
+ * Construct empty state for one Team identity.
201
+ * @param rootId - root Session identity.
202
+ * @returns mutable empty Team state.
203
+ */
204
+ function emptyTeamState(rootId) {
205
+ return {
206
+ id: TeamId(rootId),
207
+ members: [],
208
+ tasks: [],
209
+ messages: [],
210
+ delivered: [],
211
+ nextTaskNumber: 1
212
+ };
213
+ }
214
+ const teamProjectionEntrySchema = z.object({
215
+ id: teamIdSchema,
216
+ members: z.array(teamMemberSnapshotSchema),
217
+ tasks: z.array(teamTaskSnapshotSchema),
218
+ messages: z.array(teamMessageSnapshotSchema),
219
+ delivered: z.array(teamMessageIdSchema),
220
+ nextTaskNumber: positiveSafeInteger,
221
+ failure: z.string().optional()
222
+ }).strict();
223
+ /**
224
+ * Test whether a Session event belongs to the Team domain.
225
+ * @param event - candidate Session event.
226
+ * @returns whether the event has a Team-owned type.
227
+ */
228
+ function isTeamEvent(event) {
229
+ return event.type === "team/member" || event.type === "team/task" || event.type === "team/message/queued" || event.type === "team/message/delivered";
230
+ }
231
+ /** Decode one persisted Team value and retain the schema failure as its cause. */
232
+ function parsePersisted(type, schema, value) {
233
+ try {
234
+ return schema.parse(value);
235
+ } catch (error) {
236
+ throw new Error(`persisted Agent Teams ${type} payload is invalid`, { cause: error });
237
+ }
238
+ }
239
+ /** Decode the complete current-version payload selected by one Team event type. */
240
+ function parseCurrentTeamEvent(event) {
241
+ switch (event.type) {
242
+ case "team/member": return {
243
+ ...event,
244
+ data: parsePersisted(event.type, teamMemberEventSchema, event.data)
245
+ };
246
+ case "team/task": return {
247
+ ...event,
248
+ data: parsePersisted(event.type, teamTaskEventSchema, event.data)
249
+ };
250
+ case "team/message/queued": return {
251
+ ...event,
252
+ data: parsePersisted(event.type, teamMessageQueuedEventSchema, event.data)
253
+ };
254
+ case "team/message/delivered": return {
255
+ ...event,
256
+ data: parsePersisted(event.type, teamMessageDeliveredEventSchema, event.data)
257
+ };
258
+ /* v8 ignore next 2 -- TeamEventType is closed and every member is handled above. */
259
+ default: return event;
260
+ }
261
+ }
262
+ function applyProjectionEvent(state, event) {
263
+ if (state.failure !== void 0) return;
264
+ if (!isTeamEvent(event)) return;
265
+ try {
266
+ const selector = parsePersisted(event.type, teamEventSelectorSchema, event.data);
267
+ if (selector.teamId !== state.id) return;
268
+ if (selector.version !== 2) throw new Error(`unsupported Agent Teams event version ${String(selector.version)}`);
269
+ applyCurrentTeamEvent(state, parseCurrentTeamEvent(event));
270
+ } catch (error) {
271
+ /* v8 ignore next -- the owned Team transition throws Error instances. */
272
+ state.failure = error instanceof Error ? error.message : String(error);
273
+ }
274
+ }
275
+ function applyCurrentTeamEvent(state, event) {
276
+ switch (event.type) {
277
+ case "team/member": {
278
+ const member = event.data.member;
279
+ const index = state.members.findIndex((candidate) => candidate.id === member.id);
280
+ const prior = state.members[index];
281
+ const named = state.members.find((candidate) => candidate.name === member.name);
282
+ if (named !== void 0 && named.id !== member.id) throw new Error(`teammate name "${member.name}" is reused by another member`);
283
+ if (prior === void 0) {
284
+ if (member.phase !== "provisioning") throw new Error(`teammate "${member.name}" must begin provisioning`);
285
+ } else {
286
+ if (prior.name !== member.name || prior.provider !== member.provider || prior.context !== member.context) throw new Error(`teammate "${member.id}" changed immutable identity fields`);
287
+ if (prior.phase !== "provisioning" || member.phase === "provisioning") throw new Error(`teammate "${member.name}" has an invalid ${prior.phase} -> ${member.phase} transition`);
288
+ }
289
+ if (index < 0) state.members.push(member);
290
+ else state.members[index] = member;
291
+ break;
292
+ }
293
+ case "team/task": {
294
+ const task = event.data.task;
295
+ const index = state.tasks.findIndex((candidate) => candidate.id === task.id);
296
+ const prior = state.tasks[index];
297
+ if (prior === void 0 && task.revision !== 1) throw new Error(`team task "${task.id}" must begin at revision 1`);
298
+ if (prior !== void 0 && task.revision !== prior.revision + 1) throw new Error(`team task "${task.id}" revision is not contiguous`);
299
+ assertTaskGraphCandidate(state.tasks, task);
300
+ const match = numericTaskIdPattern.exec(task.id);
301
+ if (match !== null) {
302
+ const number = Number(match[1]);
303
+ state.nextTaskNumber = Math.max(state.nextTaskNumber, number === Number.MAX_SAFE_INTEGER ? number : number + 1);
304
+ }
305
+ if (index < 0) state.tasks.push(task);
306
+ else state.tasks[index] = task;
307
+ break;
308
+ }
309
+ case "team/message/queued": {
310
+ const message = event.data.message;
311
+ if (state.messages.some((candidate) => candidate.id === message.id)) throw new Error(`team message "${message.id}" was queued twice`);
312
+ state.messages.push(message);
313
+ break;
314
+ }
315
+ case "team/message/delivered": {
316
+ const queued = state.messages.find((message) => message.id === event.data.messageId);
317
+ if (queued === void 0) throw new Error(`team message "${event.data.messageId}" was delivered before queueing`);
318
+ if (queued.targetId !== event.data.targetId) throw new Error(`team message "${event.data.messageId}" target changed`);
319
+ if (state.delivered.includes(event.data.messageId)) throw new Error(`team message "${event.data.messageId}" was delivered twice`);
320
+ state.delivered.push(event.data.messageId);
321
+ break;
322
+ }
323
+ /* v8 ignore next 2 -- TeamEventType is closed and every member is handled above. */
324
+ default: return;
325
+ }
326
+ }
327
+ /** Host-only Team projection selected by the projected Session identity. */
328
+ const teamProjectionDefinition = {
329
+ key: "agentTeam",
330
+ stateVersion: 3,
331
+ stateSchema: teamProjectionEntrySchema,
332
+ init: (header) => emptyTeamState(header.id),
333
+ apply: (state, event) => {
334
+ applyProjectionEvent(state, event);
335
+ return state;
336
+ }
337
+ };
338
+ //#endregion
339
+ //#region lib/types/invariant.js
340
+ /** Agent Teams runtime invariant companion. */
341
+ const PACKAGE_NAME = "@deepseek-ai/dsh-experimental-agent-team";
342
+ /** Cordis companion plugin name. */
343
+ const name = "team-invariant";
344
+ /** Invariant registry required by the companion. */
345
+ const inject = ["invariants"];
346
+ /** Validate candidate Team events against the projected committed prefix. */
347
+ const install = Object.assign((ctx, fail) => {
348
+ ctx.on("internal/dispatch", (_mode, eventName, args) => {
349
+ if (eventName !== "session/event") return;
350
+ const [session, event] = args;
351
+ /* v8 ignore next -- non-Team Session events have no Agent Teams invariant. */
352
+ if (!isTeamEvent(event)) return;
353
+ const state = ctx.sessionProjections.stateOf(session, "agentTeam");
354
+ const candidate = teamProjectionDefinition.apply(structuredClone(state), event);
355
+ if (candidate.failure !== void 0) fail(`session event ${event.seq} violates the Agent Teams stream: ${candidate.failure}`);
356
+ }, { global: true });
357
+ }, { inject: ["sessionProjections"] });
358
+ /** Register the package invariant companion. */
359
+ const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
360
+ //#endregion
361
+ export { apply, inject, name };
@@ -0,0 +1,3 @@
1
+ /* Generated by @deepseek-ai/dsh-typert-generator from FaceModel — do not edit. */
2
+
3
+ export declare const TYPERT: unknown