@qilin-agent/experimental-agent-team 3.1.5 → 3.1.6
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.i18n.yaml +44 -44
- package/README.md +32 -28
- package/README.zh.md +33 -29
- package/lib/index.js +3 -7
- package/lib/typert.host.js +145 -26
- package/lib/typert.remote-client.d.ts +6 -2
- package/lib/typert.remote-client.js +77 -23
- package/lib/types/index.d.ts +1 -3
- package/lib/types/index.js +2 -6
- package/lib/types/journal.d.ts +1 -1
- package/lib/types/session-message.d.ts +1 -1
- package/lib/types/session-message.js +1 -1
- package/lib/types/types.d.ts +5 -5
- package/package.json +26 -26
package/README.i18n.yaml
CHANGED
|
@@ -3,77 +3,77 @@
|
|
|
3
3
|
# After editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write packages/experimental/agent-team/README.md
|
|
5
5
|
/:
|
|
6
|
-
en:
|
|
7
|
-
zh:
|
|
6
|
+
en: 8b11ad84b831ec01
|
|
7
|
+
zh: 01acc9f40e64b8d4
|
|
8
8
|
/qilin-agent-experimental-agent-team:
|
|
9
9
|
en: 4402b42eb6f211c1
|
|
10
10
|
zh: 8ac92563ac79d88a
|
|
11
11
|
/qilin-agent-experimental-agent-team/summary:
|
|
12
|
-
en:
|
|
13
|
-
zh:
|
|
12
|
+
en: 93089ec3250c740b
|
|
13
|
+
zh: ac1f8c50602fd5ef
|
|
14
14
|
/qilin-agent-experimental-agent-team/table-of-contents:
|
|
15
15
|
en: d152484eb41ac6b4
|
|
16
16
|
zh: 09388d293f9be9cb
|
|
17
17
|
/qilin-agent-experimental-agent-team/use-this-package:
|
|
18
|
-
en:
|
|
19
|
-
zh:
|
|
18
|
+
en: bf566e925ea847da
|
|
19
|
+
zh: 7a88fd5fbc13bf14
|
|
20
20
|
/qilin-agent-experimental-agent-team/use-this-package/when-to-choose-it:
|
|
21
|
-
en:
|
|
22
|
-
zh:
|
|
21
|
+
en: fc789f82c1b86394
|
|
22
|
+
zh: c6dff674d537dc26
|
|
23
23
|
/qilin-agent-experimental-agent-team/use-this-package/smallest-working-setup:
|
|
24
24
|
en: 067776ea2c4f9776
|
|
25
25
|
zh: 4a73fe617591dd61
|
|
26
26
|
/qilin-agent-experimental-agent-team/use-this-package/teammates:
|
|
27
|
-
en:
|
|
28
|
-
zh:
|
|
27
|
+
en: 5a314d1f80ecd31b
|
|
28
|
+
zh: c34e6a93dd1e2045
|
|
29
29
|
/qilin-agent-experimental-agent-team/use-this-package/messages-between-teammates:
|
|
30
|
-
en:
|
|
31
|
-
zh:
|
|
30
|
+
en: 3f98b1feabc09b11
|
|
31
|
+
zh: c83ad4de36021fb5
|
|
32
32
|
/qilin-agent-experimental-agent-team/use-this-package/shared-task-board:
|
|
33
33
|
en: 73682f0d2001b517
|
|
34
34
|
zh: 3744d82eb3b7fcb9
|
|
35
35
|
/qilin-agent-experimental-agent-team/use-this-package/waiting-and-interruption:
|
|
36
|
-
en:
|
|
37
|
-
zh:
|
|
36
|
+
en: f8e38ccf6295b375
|
|
37
|
+
zh: 44f008e23613c0af
|
|
38
38
|
/qilin-agent-experimental-agent-team/use-this-package/what-success-and-failure-look-like:
|
|
39
|
-
en:
|
|
40
|
-
zh:
|
|
39
|
+
en: cfcb985f5628e427
|
|
40
|
+
zh: a455c63b9813a06f
|
|
41
41
|
/qilin-agent-experimental-agent-team/understand-the-implementation:
|
|
42
42
|
en: 6a18034f1ccc247a
|
|
43
43
|
zh: e08b0eb0ccb41ea8
|
|
44
44
|
/qilin-agent-experimental-agent-team/understand-the-implementation/design-philosophy:
|
|
45
|
-
en:
|
|
46
|
-
zh:
|
|
45
|
+
en: 0b6c6a1f5e069abb
|
|
46
|
+
zh: 0cdca2d88bd25993
|
|
47
47
|
/qilin-agent-experimental-agent-team/understand-the-implementation/source-map:
|
|
48
48
|
en: b4617379acb1800c
|
|
49
|
-
zh:
|
|
49
|
+
zh: bdb67fae4e5b4c53
|
|
50
50
|
/qilin-agent-experimental-agent-team/understand-the-implementation/team-identity-and-roster:
|
|
51
|
-
en:
|
|
52
|
-
zh:
|
|
53
|
-
/qilin-agent-experimental-agent-team/understand-the-implementation/direct-
|
|
54
|
-
en:
|
|
55
|
-
zh:
|
|
51
|
+
en: 2389048c1a494ed3
|
|
52
|
+
zh: 7e72acd6b83ea248
|
|
53
|
+
/qilin-agent-experimental-agent-team/understand-the-implementation/direct-messages-and-historical-compatibility:
|
|
54
|
+
en: 60d5c54d032ec106
|
|
55
|
+
zh: efdf8a7dcd4e8e1e
|
|
56
56
|
/qilin-agent-experimental-agent-team/understand-the-implementation/shared-task-board:
|
|
57
57
|
en: 2dc37ba97a8a7178
|
|
58
58
|
zh: 96bd24033030e19d
|
|
59
59
|
/qilin-agent-experimental-agent-team/understand-the-implementation/waiting-and-interruption:
|
|
60
|
-
en:
|
|
61
|
-
zh:
|
|
60
|
+
en: 29eebf85f25d8d8b
|
|
61
|
+
zh: 6976a482f65b4989
|
|
62
62
|
/qilin-agent-experimental-agent-team/understand-the-implementation/durability-model:
|
|
63
|
-
en:
|
|
64
|
-
zh:
|
|
63
|
+
en: 16e982658c04aa80
|
|
64
|
+
zh: 3c75e95bb6d7b8bd
|
|
65
65
|
/qilin-agent-experimental-agent-team/understand-the-implementation/disposal:
|
|
66
|
-
en:
|
|
67
|
-
zh:
|
|
66
|
+
en: a12fb358183cc6d8
|
|
67
|
+
zh: 7fdb0434d3c407fe
|
|
68
68
|
/qilin-agent-experimental-agent-team/further-exploration:
|
|
69
|
-
en:
|
|
70
|
-
zh:
|
|
69
|
+
en: a74b13081f4198df
|
|
70
|
+
zh: 364d6ac92f0380c0
|
|
71
71
|
/qilin-agent-experimental-agent-team/further-exploration/browser-projection:
|
|
72
|
-
en:
|
|
73
|
-
zh:
|
|
72
|
+
en: 33ad8d459cf2ba34
|
|
73
|
+
zh: f5c9b92a5ccbb52a
|
|
74
74
|
/qilin-agent-experimental-agent-team/further-exploration/browser-write-bridge:
|
|
75
|
-
en:
|
|
76
|
-
zh:
|
|
75
|
+
en: 0b80f4c679480592
|
|
76
|
+
zh: 85725998a7d68604
|
|
77
77
|
/qilin-agent-experimental-agent-team/model-experience:
|
|
78
78
|
en: 215e7ba838619b7b
|
|
79
79
|
zh: a311da3843709f90
|
|
@@ -81,17 +81,17 @@
|
|
|
81
81
|
en: 7a72088145dd45ec
|
|
82
82
|
zh: 6763071c604c2edd
|
|
83
83
|
/qilin-agent-experimental-agent-team/model-experience/peer-messages/what-the-model-sees:
|
|
84
|
-
en:
|
|
85
|
-
zh:
|
|
84
|
+
en: 03d122c94d97375c
|
|
85
|
+
zh: e05915f33dedbdc1
|
|
86
86
|
/qilin-agent-experimental-agent-team/model-experience/peer-messages/token-effect:
|
|
87
|
-
en:
|
|
88
|
-
zh:
|
|
87
|
+
en: 9e0eca38b2fc9327
|
|
88
|
+
zh: 99462fd765390ed6
|
|
89
89
|
/qilin-agent-experimental-agent-team/model-experience/peer-messages/kv-cache-effect:
|
|
90
|
-
en:
|
|
91
|
-
zh:
|
|
90
|
+
en: af2993419835b838
|
|
91
|
+
zh: b2a4fea055d5cdf4
|
|
92
92
|
/qilin-agent-experimental-agent-team/known-limitations-and-deferred-work:
|
|
93
|
-
en:
|
|
94
|
-
zh:
|
|
93
|
+
en: 2b6bbe3e4242d932
|
|
94
|
+
zh: c1b33474c62f9674
|
|
95
95
|
/qilin-agent-experimental-agent-team/known-limitations-and-deferred-work/dev-note:
|
|
96
96
|
en: 498e4cf9fe5741a7
|
|
97
97
|
zh: 9d2bab630e655c99
|
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "Run
|
|
2
|
+
description: "Run named teammates with direct inbox messages and a durable shared task board in experimental Team compositions."
|
|
3
3
|
kind: "package-reference"
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -9,7 +9,7 @@ English | [中文](README.zh.md)
|
|
|
9
9
|
|
|
10
10
|
## Summary
|
|
11
11
|
|
|
12
|
-
`qilin-experimental-agent-team`
|
|
12
|
+
`qilin-experimental-agent-team` gives one session a Lead, named teammates, direct messages, and a durable shared task board. Sends use each target Agent’s inbox and can cold-resume stored teammates. Team retains roster and task state; message persistence follows the target Agent’s normal policy. Mount `qilin-experimental-tool-agent-team` for model tools. The package is experimental and requires durable session storage.
|
|
13
13
|
|
|
14
14
|
## Table of Contents
|
|
15
15
|
|
|
@@ -25,11 +25,11 @@ English | [中文](README.zh.md)
|
|
|
25
25
|
<a id="use-this-package"></a>
|
|
26
26
|
## Use this package
|
|
27
27
|
|
|
28
|
-
Add this package
|
|
28
|
+
Add this package when one agent needs named helpers in a shared working directory, direct peer messages, and durable roster and task state. Mount it with `@qilin-agent/experimental-tool-agent-team` to expose the model tools.
|
|
29
29
|
|
|
30
30
|
### When to choose it
|
|
31
31
|
|
|
32
|
-
Choose it
|
|
32
|
+
Choose it for cooperation in one shared workspace with durable roster and task state. Separate working directories, coordination across processes, and automatic task-owner release are unsupported. Durable session storage is required.
|
|
33
33
|
|
|
34
34
|
### Smallest working setup
|
|
35
35
|
|
|
@@ -59,15 +59,15 @@ The generated [configuration catalog](../../../docs/config-catalog.md#qilin-agen
|
|
|
59
59
|
|
|
60
60
|
Ask the Lead to create a teammate: give it a unique lowercase name such as `reviewer` and describe its job. A teammate starts fresh with no memory of the Lead's conversation, or as a fork that inherits the Lead's completed turns; the creation request chooses which. Teammate names are permanent — even a teammate whose creation failed keeps its name, and no name is ever reused.
|
|
61
61
|
|
|
62
|
-
The roster shows every member with its role (`lead` or `teammate`) and current status: `running`, `
|
|
62
|
+
The roster shows every member with its role (`lead` or `teammate`) and current status: `running`, `inactive` (no turn is executing, whether loaded or stored), `provisioning`, or `failed`. A member that is not loaded receives its messages when it wakes.
|
|
63
63
|
|
|
64
64
|
Only the Lead can create teammates or interrupt them.
|
|
65
65
|
|
|
66
66
|
### Messages between teammates
|
|
67
67
|
|
|
68
|
-
Any member can send
|
|
68
|
+
Any member can send to another member or the Lead. Each attempt either returns the Team message identity carried by the accepted delivery source or throws. Team does not retain unaccepted send intent, retry new messages after restart, or deduplicate explicit resends.
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
Steer gives a running target the message at its nearest step boundary and starts or cold-resumes an inactive target. Success means inbox acceptance, not model processing or a separate synchronous storage flush. Accepted messages follow ordinary Agent persistence and inbox recovery.
|
|
71
71
|
|
|
72
72
|
### Shared task board
|
|
73
73
|
|
|
@@ -81,11 +81,11 @@ File hints produce warnings when two in-progress tasks plan to touch overlapping
|
|
|
81
81
|
|
|
82
82
|
A member can wait for the next team change — a teammate's status, an incoming message, or a task update — instead of polling repeatedly; the wait reports only whether it timed out, and the caller re-reads the current state afterward.
|
|
83
83
|
|
|
84
|
-
The Lead can stop a teammate's current turn without deleting
|
|
84
|
+
The Lead can stop a teammate's current turn without deleting its queued messages; task ownership is unchanged.
|
|
85
85
|
|
|
86
86
|
### What success and failure look like
|
|
87
87
|
|
|
88
|
-
Success
|
|
88
|
+
Success returns a teammate roster row, an accepted Team message id, or an updated task revision. Invalid member names, unready tasks, stale revisions, exhausted limits, and failed message admission report errors.
|
|
89
89
|
|
|
90
90
|
-----
|
|
91
91
|
|
|
@@ -101,12 +101,12 @@ This section explains the design decisions behind the service and points at the
|
|
|
101
101
|
|
|
102
102
|
The service is built on one separation and three commitments:
|
|
103
103
|
|
|
104
|
-
- **Durable log, derived state.** The Lead
|
|
105
|
-
- **Process-local ownership.**
|
|
104
|
+
- **Durable log, derived state.** The Lead log owns roster and tasks; each target Agent owns its accepted messages.
|
|
105
|
+
- **Process-local ownership.** Continuation delivery owns target locking, cold recovery, and lifecycle authorization.
|
|
106
106
|
- **Explicit authority.** Every service method takes the exact live calling `Agent`; only the Lead spawns, reassigns, or interrupts.
|
|
107
107
|
- **Bounds that fail loud.** Every limit is a validated deployment value, and exhaustion reports a typed error instead of reusing an id or name.
|
|
108
108
|
|
|
109
|
-
The [Agent Teams Agent Note](../../../.agents/notes/implemented/feature/2026-08-05-agent-teams.md) owns the
|
|
109
|
+
The [Agent Teams Agent Note](../../../.agents/notes/implemented/feature/2026-08-05-agent-teams.md) owns the roster, mailbox, task, and shared-checkout decisions. Model-facing identity is a required runtime-context contribution from the [tool package](../tool-agent-team/README.md).
|
|
110
110
|
|
|
111
111
|
### Source map
|
|
112
112
|
|
|
@@ -124,13 +124,13 @@ The [Agent Teams Agent Note](../../../.agents/notes/implemented/feature/2026-08-
|
|
|
124
124
|
|
|
125
125
|
### Team identity and roster
|
|
126
126
|
|
|
127
|
-
Every ordinary runtime root is the implicit Lead of a Team whose `TeamId` equals its `SessionId`; there is no creation event, and durable state begins with the first member
|
|
127
|
+
Every ordinary runtime root is the implicit Lead of a Team whose `TeamId` equals its `SessionId`; there is no creation event, and durable Team state begins with the first member or task record. `spawnTeammate()` first appends and flushes a `provisioning` member record, then asks the configured provider to create the reserved child; a provider failure appends a durable `failed` member. A fresh child starts with no Lead history; a fork child captures the Lead's completed-turn prefix once. Recovery reconciles an unterminated provisioning record against the child's independently persisted Session: a matching direct-parent and continuable descriptor plus a recorded initial user message produces `active`, and anything else produces `failed`. If recovery wins a same-process race, the creator accepts the terminal state or reports `TEAM_PROVISIONING_CONFLICT` and drains the child. Names are reserved by the first provisioning record and never reused.
|
|
128
128
|
|
|
129
|
-
### Direct
|
|
129
|
+
### Direct messages and historical compatibility
|
|
130
130
|
|
|
131
|
-
`sendMessage()`
|
|
131
|
+
`sendMessage()` checks exact caller membership, rejects self-messaging, and bounds the complete sender-framed UTF-8 content. It mints one `TeamMessageId`, returns it after acceptance, and emits Team activity only after acceptance. The target stores `team-message` source carrying that id, the Team id, and the sender's identity; the first content block is `Team message <id> from <name>:`. No new `team/message/queued` or `team/message/delivered` records are written for these sends. Team adds no per-target send ordering; delivery order belongs to the target inbox. The Web client presents these messages with the Team title and icon.
|
|
132
132
|
|
|
133
|
-
Sibling messages never impersonate the Lead through the public adjacent-Agent messaging operation.
|
|
133
|
+
Lead delivery calls `Agent.steer()` directly. Teammate delivery uses the continuation owner's host-only Steer path, which preserves the Team sender source while authorizing the Lead-to-child edge and cold-resuming inactive targets. Sibling messages never impersonate the Lead through the public adjacent-Agent messaging operation.
|
|
134
134
|
|
|
135
135
|
### Shared task board
|
|
136
136
|
|
|
@@ -138,15 +138,19 @@ Tasks are complete versioned snapshots; every mutation carries `expectedRevision
|
|
|
138
138
|
|
|
139
139
|
### Waiting and interruption
|
|
140
140
|
|
|
141
|
-
`waitForChange()` waits for one roster, task, message, or live-status edge that occurs after registration, from ten seconds through one hour, and reports only whether it timed out; runtime disposal releases current waits. Cancellation preserves an Error reason or reports a non-Error reason through `TEAM_WAIT_ABORTED`. `interrupt()` is Lead-only and delegates to the continuable-subagent interrupt path, which cancels only a live teammate's current turn with `keepInbox`; it neither releases task ownership nor deletes durable mail.
|
|
141
|
+
`waitForChange()` waits for one roster, task, message-acceptance, or live-status edge that occurs after registration, from ten seconds through one hour, and reports only whether it timed out; runtime disposal releases current waits. Cancellation preserves an Error reason or reports a non-Error reason through `TEAM_WAIT_ABORTED`. `interrupt()` is Lead-only and delegates to the continuable-subagent interrupt path, which cancels only a live teammate's current turn with `keepInbox`; it neither releases task ownership nor deletes durable mail.
|
|
142
142
|
|
|
143
143
|
### Durability model
|
|
144
144
|
|
|
145
|
-
|
|
145
|
+
Roster and task mutations append `team/member` and `team/task` to the exact live Lead Session and flush before reporting success or waking waiters. Historical `team/message/queued` and `team/message/delivered` records remain readable; Team writes neither. All four event types are log-only: they never enter the conversation surface, so derived model history is untouched by coordination records. Session event `seq` and `time` own ordering and timing; snapshots do not duplicate them.
|
|
146
|
+
|
|
147
|
+
Historical mailbox events remain readable, and `team-message` sources attribute both new peer deliveries and historical ones. The projection still reports queued-minus-delivered records, but Team never delivers or acknowledges them: a historical message that its target had not recorded stays undelivered.
|
|
148
|
+
|
|
149
|
+
Mailbox projection and checkpoint admission preserve every decoded JSON field of accepted content outside the locally declared validators, including an own `__proto__` key. Local field checks cover `text`, `reasoning`, `image`, and `tool-call`; accepted unknown tags remain opaque. Team projection cache version 4 rebuilds checkpoints from earlier cache versions from the Session log; the Session format version is unchanged.
|
|
146
150
|
|
|
147
151
|
### Disposal
|
|
148
152
|
|
|
149
|
-
Disposal closes admission, aborts and awaits
|
|
153
|
+
The runtime lifecycle tracks sends and complete creation transactions in one operation set. Disposal closes admission, aborts and awaits those operations, then releases the roster’s live children and descendants. Non-Team children remain untouched. Admitted operations share one `disposalTimeoutMs` settlement deadline; each subsequent Team child drain has its own deadline. This value is not a whole-service shutdown bound. Cleanup failures are reported.
|
|
150
154
|
|
|
151
155
|
</details>
|
|
152
156
|
|
|
@@ -159,8 +163,8 @@ Read these pages when the package-level contract is not enough. They move from t
|
|
|
159
163
|
|
|
160
164
|
- [Agent Teams subsystem](../../../docs/subsystems/agent-team.md) — durable Team types and the `ctx.agentTeams` service API.
|
|
161
165
|
- [tool-agent-team package](../tool-agent-team/README.md) — the tools that let the model create, message, and coordinate teammates.
|
|
162
|
-
- [Agent Teams Agent Note](../../../.agents/notes/implemented/feature/2026-08-05-agent-teams.md) —
|
|
163
|
-
- [Experimental package
|
|
166
|
+
- [Agent Teams Agent Note](../../../.agents/notes/implemented/feature/2026-08-05-agent-teams.md) — roster, mailbox, task, and shared-checkout decisions.
|
|
167
|
+
- [Experimental package reference](../AGENTS.md) — placement, publication, and dependency isolation.
|
|
164
168
|
|
|
165
169
|
-----
|
|
166
170
|
|
|
@@ -170,11 +174,11 @@ Read these pages when the package-level contract is not enough. They move from t
|
|
|
170
174
|
|
|
171
175
|
The `agentTeam` Session projection publishes the Lead Session's durable roster identities and phases, member errors, non-deleted task views, and any `failure` beside the last valid state. Its `apply` replaces only the touched collection; mailbox-only changes retain the client view reference and produce no frame. The [subsystem reference](../../../docs/subsystems/agent-team.md#web-projection) defines the wire types.
|
|
172
176
|
|
|
173
|
-
The [Web UI](../client-ui-agent-team/README.md) reads the shared Session projections and overlays activity from Session status. The `./client` export supplies browser-safe roster, task, and projection types.
|
|
177
|
+
The [Web UI](../client-ui-agent-team/README.md) reads the shared Session projections and overlays activity from Session status. Task creation and updates travel through both the service and model tools and the browser write bridge below. The `./client` export supplies browser-safe roster, task, and projection types.
|
|
174
178
|
|
|
175
179
|
### Browser write bridge
|
|
176
180
|
|
|
177
|
-
The service exposes two wire methods on the `agentTeams` Typert namespace — `createTask` and `updateTask` — the direct wire face of the same-named service operations. `updateTask` carries every board mutation the browser offers as a typed action: `edit`, `complete`, `reopen`, `delete`, `reassign`, and `set_dependencies`. The wire caller is the exact live conversation agent; because the Web conversation prompt path runs as the Lead, the browser always writes with Lead authority, and a teammate conversation resolves its writes to the Lead before calling. Domain refusals map onto the shared Remote vocabulary through `src/remote.ts`: `TEAM_TASK_STALE_REVISION` becomes `agent-team/stale-revision`, a non-member caller becomes `agent-team/not-a-member`, and every other Team error becomes `agent-team/rejected` carrying the originating Team code in its details. The same file augments `RemoteErrorDetailsMap` with the Team codes so browser consumers branch on them type-safely. Read paths stay on the `agentTeam` projection; the bridge adds no model-visible input.
|
|
181
|
+
The service exposes two wire methods on the `agentTeams` Typert namespace — `createTask` and `updateTask` — the direct wire face of the same-named service operations. `updateTask` carries every board mutation the browser offers as a typed action: `edit`, `complete`, `reopen`, `delete`, `reassign`, and `set_dependencies`. The wire caller is the exact live conversation agent; because the Web conversation prompt path runs as the Lead, the browser always writes with Lead authority, and a teammate conversation resolves its writes to the Lead before calling. Domain refusals map onto the shared Remote failure vocabulary through `src/remote.ts`: `TEAM_TASK_STALE_REVISION` becomes `agent-team/stale-revision`, a non-member caller becomes `agent-team/not-a-member`, and every other Team error becomes `agent-team/rejected` carrying the originating Team code in its details. The same file augments `RemoteErrorDetailsMap` with the Team codes so browser consumers branch on them type-safely. Read paths stay on the `agentTeam` projection; the bridge adds no model-visible input.
|
|
178
182
|
|
|
179
183
|
## Model Experience
|
|
180
184
|
|
|
@@ -182,15 +186,15 @@ The service exposes two wire methods on the `agentTeams` Typert namespace — `c
|
|
|
182
186
|
|
|
183
187
|
#### What the model sees
|
|
184
188
|
|
|
185
|
-
Each
|
|
189
|
+
Each peer message is a user-role message whose first text block names the stable Team message id and sender, followed by the original content blocks. Roster, task, and historical mailbox records remain log-only.
|
|
186
190
|
|
|
187
191
|
#### Token effect
|
|
188
192
|
|
|
189
|
-
Each peer delivery adds the sender prefix plus message content to the target history. Task and roster mutations add no model tokens; their model-facing representation belongs to `@qilin-agent/experimental-tool-agent-team` results.
|
|
193
|
+
Each peer delivery adds the sender prefix plus message content to the target history; the stable id appears in the prefix and in the delivery source. Task and roster mutations add no model tokens; their model-facing representation belongs to `@qilin-agent/experimental-tool-agent-team` results.
|
|
190
194
|
|
|
191
195
|
#### KV Cache effect
|
|
192
196
|
|
|
193
|
-
Peer messages append after the target's reusable history prefix. Cold resume reuses the persisted conversation before appending
|
|
197
|
+
Peer messages append after the target's reusable history prefix. Cold resume reuses the persisted conversation before appending the new message.
|
|
194
198
|
|
|
195
199
|
## Known Limitations and Deferred Work
|
|
196
200
|
|
|
@@ -204,8 +208,8 @@ These limits describe what a team cannot do yet or what needs special operationa
|
|
|
204
208
|
- **One process and one shared checkout** — members share cwd and observe edits immediately; this package provides no worktree, remote member, merge, or filesystem lock.
|
|
205
209
|
- **Advisory write scopes** — Bash, formatters, code generators, and direct external writers can bypass filesystem version checks; Leads must coordinate ownership and review the final diff.
|
|
206
210
|
- **Flat immutable roster** — only the Lead creates direct teammates; there is no nested Team, rename, deletion, or name reuse.
|
|
207
|
-
- **No automatic ownership release** —
|
|
208
|
-
- **
|
|
211
|
+
- **No automatic ownership release** — inactivity, interruption, process exit, and failed work do not release a task owner.
|
|
212
|
+
- **No send retry guarantee** — Team does not retain or deduplicate new attempts; concurrent processes over one Team are unsupported. Historical queued messages that never reached their target are not delivered.
|
|
209
213
|
|
|
210
214
|
<a id="dev-note"></a>
|
|
211
215
|
### Dev Note
|
package/README.zh.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "
|
|
2
|
+
description: "在实验性 Team 组合中运行具名 teammate,使用直接 inbox 消息和持久共享任务板。"
|
|
3
3
|
kind: "package-reference"
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -9,7 +9,7 @@ kind: "package-reference"
|
|
|
9
9
|
|
|
10
10
|
## 概述
|
|
11
11
|
|
|
12
|
-
`qilin-experimental-agent-team`
|
|
12
|
+
`qilin-experimental-agent-team` 为一个会话提供 Lead、具名 teammate、直接消息和持久共享任务板。发送使用目标 agent(智能体)的 inbox,并可冷恢复已存储的 teammate。Team 保留 roster 与任务状态,消息持久化遵循目标 Agent 的常规策略。挂载 `qilin-experimental-tool-agent-team` 可提供模型工具。本包为实验性功能,需要持久会话存储。
|
|
13
13
|
|
|
14
14
|
## 目录
|
|
15
15
|
|
|
@@ -25,11 +25,11 @@ kind: "package-reference"
|
|
|
25
25
|
<a id="use-this-package"></a>
|
|
26
26
|
## 使用本包
|
|
27
27
|
|
|
28
|
-
当一个 agent
|
|
28
|
+
当一个 agent 需要共享工作目录中的具名助手、直接 peer 消息以及持久 roster 与任务状态时,加入本包。与 `@qilin-agent/experimental-tool-agent-team` 一起挂载可提供模型工具。
|
|
29
29
|
|
|
30
30
|
### 何时选择
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
适用于在同一共享工作区协作并保留持久 roster 和任务状态。不支持独立工作目录、跨进程协调和自动释放任务 owner。需要持久会话存储。
|
|
33
33
|
|
|
34
34
|
### 最小工作配置
|
|
35
35
|
|
|
@@ -59,15 +59,15 @@ kind: "package-reference"
|
|
|
59
59
|
|
|
60
60
|
请 Lead 创建 teammate:给它一个唯一的小写名字(例如 `reviewer`)并描述其职责。teammate 可以 fresh 启动(不携带 Lead 对话的任何记忆),也可以作为 fork 启动(继承 Lead 已完成的轮次);创建请求决定用哪种。teammate 名字是永久的——即使创建失败的 teammate 也保留其名字,任何名字都不会被复用。
|
|
61
61
|
|
|
62
|
-
roster 显示每个成员的职责(`lead` 或 `teammate`)与当前状态:`running`、`
|
|
62
|
+
roster 显示每个成员的职责(`lead` 或 `teammate`)与当前状态:`running`、`inactive`(当前没有执行轮次,包括已加载和仅存储的成员)、`provisioning` 或 `failed`。未加载的成员会在唤醒后收到其消息。
|
|
63
63
|
|
|
64
64
|
只有 Lead 可以创建 teammate 或中断它们。
|
|
65
65
|
|
|
66
66
|
### teammate 之间的消息
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
任何成员都可向其他成员或 Lead 发送消息。每次尝试要么返回获准投递 source 所携带的 Team 消息身份,要么抛出错误。Team 不保留尚未接收的发送意图,不在重启后重试新消息,也不对显式重发去重。
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
Steer 让 running target 在最近的步骤边界接收消息,并启动或冷恢复 inactive target。成功表示 inbox 接收,不表示模型已处理或已完成单独的同步存储 flush。获准消息遵循普通 Agent 的持久化和 inbox 恢复策略。
|
|
71
71
|
|
|
72
72
|
### 共享任务板
|
|
73
73
|
|
|
@@ -81,11 +81,11 @@ roster 显示每个成员的职责(`lead` 或 `teammate`)与当前状态:`
|
|
|
81
81
|
|
|
82
82
|
成员可以等待下一次团队变化——teammate 的状态、新消息或任务更新——而不必反复轮询;等待只报告是否超时,调用方随后重新读取当前状态。
|
|
83
83
|
|
|
84
|
-
Lead 可以停止 teammate
|
|
84
|
+
Lead 可以停止 teammate 的当前轮次,而不会删除其排队的消息;任务归属不变。
|
|
85
85
|
|
|
86
86
|
### 成功与失败的表现
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
成功会返回 teammate roster 行、获准的 Team 消息 id 或更新后的任务 revision。无效成员名称、未就绪任务、过期 revision、上限耗尽和消息准入失败均报告错误。
|
|
89
89
|
|
|
90
90
|
-----
|
|
91
91
|
|
|
@@ -101,12 +101,12 @@ Lead 可以停止 teammate 的当前轮次,而不会删除其 inbox 中已有
|
|
|
101
101
|
|
|
102
102
|
本服务建立在一个分离与三项承诺之上:
|
|
103
103
|
|
|
104
|
-
- **持久日志,派生状态。** Lead
|
|
105
|
-
- **进程内归属。**
|
|
104
|
+
- **持久日志,派生状态。** Lead 日志拥有 roster 与任务,各目标 Agent 拥有其接收的消息。
|
|
105
|
+
- **进程内归属。** Continuation 投递拥有目标锁、冷恢复和生命周期授权。
|
|
106
106
|
- **显式权限。** 每个服务方法都接收确切的实时调用方 `Agent`;只有 Lead 可以 spawn、reassign 或 interrupt。
|
|
107
107
|
- **超出上限时明确失败。** 每个限制都是经过校验的部署值,耗尽时报告类型化错误,而不是复用 id 或名字。
|
|
108
108
|
|
|
109
|
-
[Agent Teams Agent Note](../../../.agents/notes/implemented/feature/2026-08-05-agent-teams.zh.md)
|
|
109
|
+
[Agent Teams Agent Note](../../../.agents/notes/implemented/feature/2026-08-05-agent-teams.zh.md)负责 roster、mailbox、任务与共享 checkout 决策。面向模型的身份由 [tool 包](../tool-agent-team/README.zh.md) 以 required runtime context 贡献。
|
|
110
110
|
|
|
111
111
|
### 源码地图
|
|
112
112
|
|
|
@@ -117,18 +117,18 @@ Lead 可以停止 teammate 的当前轮次,而不会删除其 inbox 中已有
|
|
|
117
117
|
| [`src/task-board.ts`](src/task-board.ts) | 任务 CAS 命令、DAG 校验与派生视图 |
|
|
118
118
|
| [`src/journal.ts`](src/journal.ts) | 串行化的 Lead 日志事务与提交通知 |
|
|
119
119
|
| [`src/projection.ts`](src/projection.ts) | 解码并校验 Team 事件、发布 `agentTeam` 客户端视图的严格回放投影 |
|
|
120
|
-
| [`src/remote.ts`](src/remote.ts) |
|
|
120
|
+
| [`src/remote.ts`](src/remote.ts) | 浏览器写面:wire 错误映射与 `RemoteErrorDetailsMap` 的 Team 扩展 |
|
|
121
121
|
| [`src/task-view.ts`](src/task-view.ts) | 任务板与客户端视图共用的纯任务派生:就绪状态、owner 名称与写入范围重叠 |
|
|
122
122
|
| [`src/activity.ts`](src/activity.ts) | 一次性变更等待者与 dispose(资源释放)时的等待解除 |
|
|
123
123
|
| [`src/lifecycle.ts`](src/lifecycle.ts) | 共享准入截止与有界结算 |
|
|
124
124
|
|
|
125
125
|
### Team 身份与 roster
|
|
126
126
|
|
|
127
|
-
每个普通运行时 root 都是一个隐式 Team 的 Lead,其 `TeamId` 等于 `SessionId
|
|
127
|
+
每个普通运行时 root 都是一个隐式 Team 的 Lead,其 `TeamId` 等于 `SessionId`;不存在创建事件,持久 Team 状态从第一条成员或任务记录开始。`spawnTeammate()` 先追加并 flush 一条 `provisioning` 成员记录,再要求配置的提供方创建预留 child;提供方失败会追加一条持久的 `failed` 成员。fresh child 不携带 Lead 历史;fork child 只捕获一次 Lead 的已完成 turn 前缀。恢复把未终结的 provisioning 记录对照 child 独立持久化的会话进行对账:直接 parent 与 continuable descriptor 匹配、且初始用户消息已记录则产生 `active`,其他任何情况都产生 `failed`。如果恢复在同进程竞争中先完成,creator 会接受终态,或报告 `TEAM_PROVISIONING_CONFLICT` 并 drain 该 child。名字由第一条 provisioning 记录保留,且永不复用。
|
|
128
128
|
|
|
129
|
-
###
|
|
129
|
+
### 直接消息与历史兼容
|
|
130
130
|
|
|
131
|
-
`sendMessage()`
|
|
131
|
+
`sendMessage()` 检查确切调用方的成员身份,拒绝自发消息,并限制包含发送者前缀的完整 UTF-8 内容大小。它铸出一个 `TeamMessageId`,在接收后返回该 id,并仅在接收后发出 Team activity。目标保存 `team-message` source,携带该 id、Team id 与发送者身份;首个内容块为 `Team message <id> from <name>:`。这些发送不写入新的 `team/message/queued` 或 `team/message/delivered` 记录。Team 不额外保证同目标发送顺序;投递顺序由目标 inbox 管理。Web 客户端使用 Team 标题和图标展示这些消息。
|
|
132
132
|
|
|
133
133
|
投递给 Lead 时直接调用 `Agent.steer()`。投递给 teammate 时使用 continuation owner 的 host-only Steer 路径;该路径会保留 Team 发送者 source,同时授权 Lead-to-child edge 并冷恢复 inactive target。sibling 消息绝不会通过公开的相邻 Agent 消息操作伪装成 Lead。
|
|
134
134
|
|
|
@@ -138,15 +138,19 @@ Lead 可以停止 teammate 的当前轮次,而不会删除其 inbox 中已有
|
|
|
138
138
|
|
|
139
139
|
### 等待与中断
|
|
140
140
|
|
|
141
|
-
`waitForChange()` 等待注册之后发生的下一条 roster、task
|
|
141
|
+
`waitForChange()` 等待注册之后发生的下一条 roster、task、消息接收或实时状态边,时长从 10 秒到 1 小时,并且只报告是否超时;运行时 dispose 会释放当前等待。取消会保留 Error reason;非 Error reason 则通过 `TEAM_WAIT_ABORTED` 报告。`interrupt()` 仅限 Lead,委托 continuable-subagent 的 interrupt 路径,以 `keepInbox` 只取消 live teammate 的当前 turn;它既不释放任务 owner,也不删除持久 mail。
|
|
142
142
|
|
|
143
143
|
### 持久性模型
|
|
144
144
|
|
|
145
|
-
|
|
145
|
+
roster 与任务变更将 `team/member` 和 `team/task` 追加到精确的 live Lead 会话,并在报告成功或唤醒等待者之前 flush。历史 `team/message/queued` 与 `team/message/delivered` 记录仍可读取;Team 不再写入这两种记录。这四种事件仅存在于日志:它们从不进入会话表面,因此派生模型历史不受协作记录影响。顺序与时间由会话事件的 `seq` 与 `time` 负责,快照不重复保存。
|
|
146
|
+
|
|
147
|
+
历史 mailbox 事件仍可读取;`team-message` source 同时归属新的 peer 投递与历史投递。投影仍报告 queued-minus-delivered 记录,但 Team 不会投递或确认这些记录:目标尚未记录的历史消息保持未投递。
|
|
148
|
+
|
|
149
|
+
Mailbox 投影与 checkpoint 准入保留本地声明的校验器之外获准内容中全部已解码 JSON 字段,包括自有 `__proto__` 键。本地字段检查覆盖 `text`、`reasoning`、`image` 和 `tool-call`;获准的未知标签保持不透明。Team 投影缓存版本 4 从 Session 日志重建较早缓存版本的 checkpoint;Session 格式版本保持不变。
|
|
146
150
|
|
|
147
151
|
### Dispose
|
|
148
152
|
|
|
149
|
-
dispose
|
|
153
|
+
运行时生命周期用同一个操作集合跟踪发送和完整创建事务。dispose 关闭准入,中止并等待这些操作,然后释放 roster 中的 live child 及其后代。非 Team child 不受影响。已获准操作共享一个 `disposalTimeoutMs` 等待期限;随后每个 Team 的 child drain 各有独立期限。此值不是整个服务关闭的总时限。清理失败会明确报告。
|
|
150
154
|
|
|
151
155
|
</details>
|
|
152
156
|
|
|
@@ -159,8 +163,8 @@ dispose 会关闭准入、中止并等待已获准的发送与创建事务,再
|
|
|
159
163
|
|
|
160
164
|
- [Agent Teams 子系统](../../../docs/subsystems/agent-team.zh.md)——持久 Team 类型与 `ctx.agentTeams` 服务 API。
|
|
161
165
|
- [tool-agent-team 包](../tool-agent-team/README.zh.md)——让模型创建 teammate、向其发送消息并进行协调的工具。
|
|
162
|
-
- [Agent Teams Agent Note](../../../.agents/notes/implemented/feature/2026-08-05-agent-teams.zh.md)
|
|
163
|
-
- [
|
|
166
|
+
- [Agent Teams Agent Note](../../../.agents/notes/implemented/feature/2026-08-05-agent-teams.zh.md)——roster、mailbox、任务与共享 checkout 决策。
|
|
167
|
+
- [实验包参考](../AGENTS.md)——位置、公开发布与依赖隔离。
|
|
164
168
|
|
|
165
169
|
-----
|
|
166
170
|
|
|
@@ -170,11 +174,11 @@ dispose 会关闭准入、中止并等待已获准的发送与创建事务,再
|
|
|
170
174
|
|
|
171
175
|
`agentTeam` Session 投影发布 Lead Session 的持久成员身份与阶段、成员错误、未删除任务视图,以及最后有效状态旁的 `failure`。其 `apply` 只替换被触及的集合;仅邮箱的变化保留客户端视图引用,不产生 frame。[子系统参考](../../../docs/subsystems/agent-team.zh.md#web-projection) 定义传输类型。
|
|
172
176
|
|
|
173
|
-
[Web UI](../client-ui-agent-team/README.zh.md) 读取共享 Session 投影,并从 Session
|
|
177
|
+
[Web UI](../client-ui-agent-team/README.zh.md) 读取共享 Session 投影,并从 Session 状态叠加活动信息。任务创建与更新既可以通过服务和模型工具完成,也可以通过下文的浏览器写面完成。`./client` 导出可供浏览器使用的 roster、任务与投影类型。
|
|
174
178
|
|
|
175
|
-
###
|
|
179
|
+
### 浏览器写面
|
|
176
180
|
|
|
177
|
-
服务在 `agentTeams` Typert
|
|
181
|
+
服务在 `agentTeams` Typert 命名空间上暴露两个 wire 方法——`createTask` 与 `updateTask`——它们与同名服务操作直接对应。`updateTask` 以类型化 action 承载浏览器提供的所有看板变更:`edit`、`complete`、`reopen`、`delete`、`reassign` 与 `set_dependencies`。wire 调用方是确切的实时会话 agent;由于 Web 会话的提示词路径以 Lead 身份运行,浏览器始终以 Lead 权限写入,而 teammate 会话会在调用前把写入解析到 Lead。领域拒绝通过 `src/remote.ts` 映射到共享 Remote 失败词汇:`TEAM_TASK_STALE_REVISION` 变为 `agent-team/stale-revision`,非成员调用方变为 `agent-team/not-a-member`,其他 Team 错误变为 `agent-team/rejected` 并在 details 中携带原始 Team 错误码。同一文件为 `RemoteErrorDetailsMap` 扩展 Team 错误码,使浏览器消费方可以类型安全地分支。读取路径仍走 `agentTeam` 投影;写面不增加模型可见输入。
|
|
178
182
|
|
|
179
183
|
## 模型体验
|
|
180
184
|
|
|
@@ -182,15 +186,15 @@ dispose 会关闭准入、中止并等待已获准的发送与创建事务,再
|
|
|
182
186
|
|
|
183
187
|
#### 模型看到什么
|
|
184
188
|
|
|
185
|
-
|
|
189
|
+
每条 peer 消息都是用户角色消息:首个文本块给出稳定的 Team 消息 id 与发送者,随后是原始内容块。roster、task 和历史 mailbox 记录仍仅存在于日志。
|
|
186
190
|
|
|
187
191
|
#### Token 影响
|
|
188
192
|
|
|
189
|
-
每次 peer 投递都会把发送者前缀与消息内容加入 target
|
|
193
|
+
每次 peer 投递都会把发送者前缀与消息内容加入 target 历史;稳定 id 同时出现在前缀与投递 source 中。任务与 roster 变更不增加模型 token;其面向模型的呈现属于 `@qilin-agent/experimental-tool-agent-team` 结果。
|
|
190
194
|
|
|
191
195
|
#### KV Cache 影响
|
|
192
196
|
|
|
193
|
-
Peer 消息追加在 target
|
|
197
|
+
Peer 消息追加在 target 可复用历史前缀之后。冷恢复会先复用持久对话,再追加新消息。
|
|
194
198
|
|
|
195
199
|
## 已知限制与延期工作
|
|
196
200
|
|
|
@@ -204,8 +208,8 @@ Peer 消息追加在 target 可复用历史前缀之后。冷恢复会先复用
|
|
|
204
208
|
- **单进程、共享 checkout**——成员共享 cwd,修改立即可见;本包不提供 worktree、远端成员、merge 或文件锁。
|
|
205
209
|
- **write scope 仅作提示**——Bash、formatter、代码生成器与直接外部写入可以绕过文件版本检查;Lead 必须协调 owner 并检查最终 diff。
|
|
206
210
|
- **扁平且不可变的 roster**——只有 Lead 可以创建直接 teammate;不支持嵌套 Team、重命名、删除或名字复用。
|
|
207
|
-
- **不会自动释放 owner
|
|
208
|
-
-
|
|
211
|
+
- **不会自动释放 owner**——成员不活动、interrupt、进程退出与工作失败都不会释放任务 owner。
|
|
212
|
+
- **无发送重试保证**——Team 不保留新尝试,也不对其去重;不支持多个进程同时操作一个 Team。从未到达目标的历史排队消息不会被投递。
|
|
209
213
|
|
|
210
214
|
<a id="dev-note"></a>
|
|
211
215
|
### 开发备注
|
package/lib/index.js
CHANGED
|
@@ -777,7 +777,7 @@ async function readPersistedSession(persistence, id, signal) {
|
|
|
777
777
|
}
|
|
778
778
|
//#endregion
|
|
779
779
|
//#region lib/types/session-message.js
|
|
780
|
-
/** Durable Session-message acceptance checks
|
|
780
|
+
/** Durable Session-message acceptance checks for teammate provisioning. */
|
|
781
781
|
/** Fold the durable inbox suffix into the messages still awaiting a claim. */
|
|
782
782
|
function pendingInboxMessages(events) {
|
|
783
783
|
const inbox = {
|
|
@@ -1749,20 +1749,16 @@ let TeamService = (() => {
|
|
|
1749
1749
|
tryMembership(agent) {
|
|
1750
1750
|
return this.roster.tryMembership(agent);
|
|
1751
1751
|
}
|
|
1752
|
-
/** Queue one contained
|
|
1752
|
+
/** Queue one contained provisioning reconciliation after publication has unwound. */
|
|
1753
1753
|
scheduleRecovery(agent) {
|
|
1754
1754
|
queueMicrotask(() => {
|
|
1755
1755
|
if (this.lifecycle.disposed) return;
|
|
1756
|
-
this.recoverFor(agent).catch((error) => {
|
|
1756
|
+
this.roster.recoverFor(agent, this.lifecycle.signal).catch((error) => {
|
|
1757
1757
|
if (this.lifecycle.disposed) return;
|
|
1758
1758
|
this.ctx.logger.warn(`Agent Teams recovery for "${agent.id}" failed: ${errorMessage(error)}`);
|
|
1759
1759
|
});
|
|
1760
1760
|
});
|
|
1761
1761
|
}
|
|
1762
|
-
/** Reconcile roster provisioning when one Team member Session starts. */
|
|
1763
|
-
async recoverFor(agent) {
|
|
1764
|
-
await this.roster.recoverFor(agent, this.lifecycle.signal);
|
|
1765
|
-
}
|
|
1766
1762
|
/** Stop Team-owned live branches and release every waiter before service disposal completes. */
|
|
1767
1763
|
async disposeRuntime() {
|
|
1768
1764
|
this.lifecycle.close();
|