@wowyuarm/dsh-agent-team 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/README.zh.md +5 -5
- package/cordis.patch.yml +26 -12
- package/package.json +50 -47
- package/packages/agent-team/lib/attachments.js +63 -4
- package/packages/agent-team/lib/compaction-engine.js +18 -0
- package/packages/agent-team/lib/context-continuity-host.js +198 -4
- package/packages/agent-team/lib/context-judge.js +150 -0
- package/packages/agent-team/lib/index.js +482 -97
- package/packages/agent-team/lib/invariant.js +36 -12
- package/packages/agent-team/lib/ledger.js +2 -1
- package/packages/agent-team/lib/member-runtime.js +2 -1
- package/packages/agent-team/lib/recovery.js +53 -4
- package/packages/agent-team/lib/typert.host.js +138 -44
- package/packages/agent-team/lib/typert.remote-client.d.ts +3 -1
- package/packages/agent-team/lib/typert.remote-client.d.ts.map +1 -1
- package/packages/agent-team/lib/typert.remote-client.js +75 -35
- package/packages/agent-team/lib/types/attachments.d.ts +32 -2
- package/packages/agent-team/lib/types/attachments.d.ts.map +1 -1
- package/packages/agent-team/lib/types/compaction-engine.d.ts +19 -0
- package/packages/agent-team/lib/types/compaction-engine.d.ts.map +1 -0
- package/packages/agent-team/lib/types/context-continuity-host.d.ts +131 -4
- package/packages/agent-team/lib/types/context-continuity-host.d.ts.map +1 -1
- package/packages/agent-team/lib/types/context-judge.d.ts +82 -0
- package/packages/agent-team/lib/types/context-judge.d.ts.map +1 -0
- package/packages/agent-team/lib/types/index.d.ts +259 -17
- package/packages/agent-team/lib/types/index.d.ts.map +1 -1
- package/packages/agent-team/lib/types/invariant.d.ts +27 -5
- package/packages/agent-team/lib/types/invariant.d.ts.map +1 -1
- package/packages/agent-team/lib/types/ledger.d.ts.map +1 -1
- package/packages/agent-team/lib/types/member-runtime.d.ts +1 -1
- package/packages/agent-team/lib/types/member-runtime.d.ts.map +1 -1
- package/packages/agent-team/lib/types/recovery.d.ts +19 -6
- package/packages/agent-team/lib/types/recovery.d.ts.map +1 -1
- package/packages/agent-team/lib/types/types/requests-results.d.ts +28 -2
- package/packages/agent-team/lib/types/types/requests-results.d.ts.map +1 -1
- package/packages/agent-team/lib/types/types.d.ts +9 -0
- package/packages/agent-team/lib/types/types.d.ts.map +1 -1
- package/packages/client-agent-team/lib/client.js +1006 -374
- package/packages/client-agent-team/lib/client.js.map +1 -1
- package/packages/client-agent-team/lib/types/client/{HumanSettingsSection.d.ts → TeamSettingsSection.d.ts} +12 -4
- package/packages/client-agent-team/lib/types/client/TeamSettingsSection.d.ts.map +1 -0
- package/packages/client-agent-team/lib/types/client/TeamSettingsSection.js +195 -0
- package/packages/client-agent-team/lib/types/client/attachment-preview.d.ts +7 -11
- package/packages/client-agent-team/lib/types/client/attachment-preview.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/attachment-preview.js +13 -3
- package/packages/client-agent-team/lib/types/client/context-judge.d.ts +64 -0
- package/packages/client-agent-team/lib/types/client/context-judge.d.ts.map +1 -0
- package/packages/client-agent-team/lib/types/client/context-judge.js +78 -0
- package/packages/client-agent-team/lib/types/client/index.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/index.js +75 -11
- package/packages/client-agent-team/lib/types/client/judge-form.d.ts +99 -0
- package/packages/client-agent-team/lib/types/client/judge-form.d.ts.map +1 -0
- package/packages/client-agent-team/lib/types/client/judge-form.js +208 -0
- package/packages/client-agent-team/lib/types/client/locales.d.ts +52 -6
- package/packages/client-agent-team/lib/types/client/locales.d.ts.map +1 -1
- package/packages/client-agent-team/lib/types/client/locales.js +55 -6
- package/packages/tool-agent-team/README.md +6 -3
- package/packages/tool-agent-team/README.zh.md +6 -3
- package/packages/tool-agent-team/lib/context-tools.js +84 -112
- package/packages/tool-agent-team/lib/types/context-tools.d.ts +29 -13
- package/packages/tool-agent-team/lib/types/context-tools.d.ts.map +1 -1
- package/packages/agent-team/lib/pressure-policy.js +0 -235
- package/packages/agent-team/lib/types/pressure-policy.d.ts +0 -134
- package/packages/agent-team/lib/types/pressure-policy.d.ts.map +0 -1
- package/packages/client-agent-team/lib/types/client/HumanSettingsSection.d.ts.map +0 -1
- package/packages/client-agent-team/lib/types/client/HumanSettingsSection.js +0 -118
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { type SettingsFieldState, type SettingsFormActions, type SettingsFormScope, type SettingsFormShell } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
2
|
+
import type { TeamContextJudgeCheck } from './context-judge.ts';
|
|
3
|
+
/** Where each control's value lives inside the Team row's settings section. */
|
|
4
|
+
declare const FIELD_PATHS: {
|
|
5
|
+
readonly apiBase: readonly ["jev", "apiBase"];
|
|
6
|
+
readonly model: readonly ["jev", "model"];
|
|
7
|
+
readonly apiKey: readonly ["jev", "apiKey"];
|
|
8
|
+
};
|
|
9
|
+
/** One control this page owns. */
|
|
10
|
+
export type TeamJudgeField = keyof typeof FIELD_PATHS;
|
|
11
|
+
/** The group this form edits, as it sits inside the Team row's section. */
|
|
12
|
+
export interface TeamJudgeSection {
|
|
13
|
+
/** The judge's endpoint configuration. */
|
|
14
|
+
readonly jev?: unknown;
|
|
15
|
+
}
|
|
16
|
+
/** Everything the page renders about the form, in one replaceable value. */
|
|
17
|
+
export interface TeamJudgeFormSnapshot {
|
|
18
|
+
/** Availability, writability, and what a save would do. */
|
|
19
|
+
readonly shell: SettingsFormShell;
|
|
20
|
+
/** One state per control this page owns. */
|
|
21
|
+
readonly fields: Readonly<Record<TeamJudgeField, SettingsFieldState>>;
|
|
22
|
+
}
|
|
23
|
+
export declare class TeamJudgeForm {
|
|
24
|
+
private readonly section;
|
|
25
|
+
private readonly judge;
|
|
26
|
+
private readonly model;
|
|
27
|
+
private readonly scope;
|
|
28
|
+
private readonly store;
|
|
29
|
+
/**
|
|
30
|
+
* @param section - the Team row's configuration form, as the settings provider serves it.
|
|
31
|
+
* @param judge - the status projection a landed write re-reads.
|
|
32
|
+
*/
|
|
33
|
+
constructor(section: SettingsFormScope<TeamJudgeSection>, judge: TeamContextJudgeCheck);
|
|
34
|
+
/** The form state the page renders. */
|
|
35
|
+
readonly getSnapshot: () => TeamJudgeFormSnapshot;
|
|
36
|
+
/** Observe the form state. */
|
|
37
|
+
readonly subscribe: (listener: () => void) => (() => void);
|
|
38
|
+
/** Stage a draft, reset a field, save every staged edit, or discard them. */
|
|
39
|
+
actions(): SettingsFormActions;
|
|
40
|
+
/**
|
|
41
|
+
* Remove the stored key literal: the judge unmounts and the status re-reads.
|
|
42
|
+
*
|
|
43
|
+
* Deliberately its own write rather than a staged edit — the shared form
|
|
44
|
+
* model has no clear for a write-only control, and an empty draft must keep
|
|
45
|
+
* the stored literal instead of clearing it. The page only offers this while
|
|
46
|
+
* no draft is staged, because a write moves the document revision the staged
|
|
47
|
+
* save is fenced to.
|
|
48
|
+
* @returns whether the Host accepted the clear.
|
|
49
|
+
*/
|
|
50
|
+
clearKey(): Promise<boolean>;
|
|
51
|
+
dispose(): void;
|
|
52
|
+
/** Build the page's state from the model's reads and drafts. */
|
|
53
|
+
private project;
|
|
54
|
+
/** Write every staged edit, then re-read the status the Host now serves. */
|
|
55
|
+
save(): Promise<void>;
|
|
56
|
+
}
|
|
57
|
+
/** Read-side face the settings page binds for the endpoint form. */
|
|
58
|
+
export interface TeamJudgeFormSource {
|
|
59
|
+
getSnapshot(): TeamJudgeForm | undefined;
|
|
60
|
+
subscribe(listener: () => void): () => void;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The form's seat on the page, as an observable rather than a value.
|
|
64
|
+
*
|
|
65
|
+
* The form exists only while this deployment serves a settings document, and
|
|
66
|
+
* that service may arrive after the page's first render. A slot entry's
|
|
67
|
+
* injected props are computed once and cached for the entry's lifetime, so a
|
|
68
|
+
* value handed over at that moment would freeze the answer: the group would
|
|
69
|
+
* never appear until a reload. The page therefore observes this seat, which
|
|
70
|
+
* the service's arrival and departure both publish through.
|
|
71
|
+
*/
|
|
72
|
+
export declare class TeamJudgeFormSeat implements TeamJudgeFormSource {
|
|
73
|
+
private form;
|
|
74
|
+
private readonly listeners;
|
|
75
|
+
readonly getSnapshot: () => TeamJudgeForm | undefined;
|
|
76
|
+
/**
|
|
77
|
+
* Observe the form, without reading anything on subscribe: the seat carries
|
|
78
|
+
* no remote state of its own, so a subscriber renders whatever is held now.
|
|
79
|
+
* @param listener - invoked after every hold or release.
|
|
80
|
+
* @returns the disposer removing this listener.
|
|
81
|
+
*/
|
|
82
|
+
readonly subscribe: (listener: () => void) => (() => void);
|
|
83
|
+
/**
|
|
84
|
+
* Publish the form the settings service answers with.
|
|
85
|
+
* @param form - the form built over that service's section scope.
|
|
86
|
+
*/
|
|
87
|
+
hold(form: TeamJudgeForm): void;
|
|
88
|
+
/**
|
|
89
|
+
* Withdraw the form when its service goes away. Only the holder of the form
|
|
90
|
+
* in place can withdraw it, so a replacement is never cleared by the
|
|
91
|
+
* departure of the one it replaced.
|
|
92
|
+
* @param form - the form this caller holds.
|
|
93
|
+
*/
|
|
94
|
+
release(form: TeamJudgeForm): void;
|
|
95
|
+
dispose(): void;
|
|
96
|
+
private publish;
|
|
97
|
+
}
|
|
98
|
+
export {};
|
|
99
|
+
//# sourceMappingURL=judge-form.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"judge-form.d.ts","sourceRoot":"","sources":["../../../src/client/judge-form.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,kBAAkB,EAAE,KAAK,mBAAmB,EAA2B,KAAK,iBAAiB,EAClE,KAAK,iBAAiB,EACvD,MAAM,uCAAuC,CAAA;AAC9C,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAqB/D,+EAA+E;AAC/E,QAAA,MAAM,WAAW;;;;CAIP,CAAA;AAEV,kCAAkC;AAClC,MAAM,MAAM,cAAc,GAAG,MAAM,OAAO,WAAW,CAAA;AAErD,2EAA2E;AAC3E,MAAM,WAAW,gBAAgB;IAC/B,0CAA0C;IAC1C,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CACvB;AA4DD,4EAA4E;AAC5E,MAAM,WAAW,qBAAqB;IACpC,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAA;IACjC,4CAA4C;IAC5C,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC,CAAA;CACtE;AAQD,qBAAa,aAAa;IAUtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,KAAK;IAVxB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA4C;IAClE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;IACtC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;IAEtC;;;OAGG;gBAEgB,OAAO,EAAE,iBAAiB,CAAC,gBAAgB,CAAC,EAC5C,KAAK,EAAE,qBAAqB;IAiB/C,uCAAuC;IACvC,QAAQ,CAAC,WAAW,QAAO,qBAAqB,CAA4B;IAE5E,8BAA8B;IAC9B,QAAQ,CAAC,SAAS,GAAI,UAAU,MAAM,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC,CAAkC;IAE3F,6EAA6E;IAC7E,OAAO,IAAI,mBAAmB;IAI9B;;;;;;;;;OASG;IACG,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IAYlC,OAAO,IAAI,IAAI;IAIf,gEAAgE;IAChE,OAAO,CAAC,OAAO;IAMf,4EAA4E;IACtE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAI5B;AAED,oEAAoE;AACpE,MAAM,WAAW,mBAAmB;IAClC,WAAW,IAAI,aAAa,GAAG,SAAS,CAAA;IACxC,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAA;CAC5C;AAED;;;;;;;;;GASG;AACH,qBAAa,iBAAkB,YAAW,mBAAmB;IAC3D,OAAO,CAAC,IAAI,CAA2B;IACvC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAwB;IAElD,QAAQ,CAAC,WAAW,QAAO,aAAa,GAAG,SAAS,CAAa;IAEjE;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,GAAI,UAAU,MAAM,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC,CAGxD;IAED;;;OAGG;IACH,IAAI,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI;IAK/B;;;;;OAKG;IACH,OAAO,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI;IAMlC,OAAO,IAAI,IAAI;IAIf,OAAO,CAAC,OAAO;CAGhB"}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { SettingsFormModel, settingsTextField, } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
2
|
+
/**
|
|
3
|
+
* The Team settings page's staged form over the judge's endpoint.
|
|
4
|
+
*
|
|
5
|
+
* The page edits one group of the Team row's settings section: the `jev`
|
|
6
|
+
* endpoint the relatedness judge is mounted from. The identity fields that
|
|
7
|
+
* share that section belong to the Human profile rows and are never rendered
|
|
8
|
+
* here, so this form reaches its values through a projection — the shared form
|
|
9
|
+
* model addresses one flat section, and the adapter below maps each control to
|
|
10
|
+
* the path it really lives at.
|
|
11
|
+
*
|
|
12
|
+
* The key literal is the one control that is not read back: the Host redacts
|
|
13
|
+
* it, so its draft starts blank on every load, a blank draft writes nothing,
|
|
14
|
+
* and removing a stored literal is an explicit clear rather than an empty
|
|
15
|
+
* string.
|
|
16
|
+
*/
|
|
17
|
+
/** The group inside the Team row's settings section that this form edits. */
|
|
18
|
+
const JUDGE_GROUP = 'jev';
|
|
19
|
+
/** Where each control's value lives inside the Team row's settings section. */
|
|
20
|
+
const FIELD_PATHS = {
|
|
21
|
+
apiBase: [JUDGE_GROUP, 'apiBase'],
|
|
22
|
+
model: [JUDGE_GROUP, 'model'],
|
|
23
|
+
apiKey: [JUDGE_GROUP, 'apiKey'],
|
|
24
|
+
};
|
|
25
|
+
/** Read the judge group of a section layer as a plain record. */
|
|
26
|
+
function groupOf(layer) {
|
|
27
|
+
if (layer === null || typeof layer !== 'object')
|
|
28
|
+
return undefined;
|
|
29
|
+
const value = layer[JUDGE_GROUP];
|
|
30
|
+
return value !== null && typeof value === 'object' ? value : undefined;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Project one section layer onto the controls this page renders. A control the
|
|
34
|
+
* layer does not carry stays absent rather than becoming an empty string, which
|
|
35
|
+
* is what the model reads to decide whether a field is overridden and what a
|
|
36
|
+
* reset reverts to.
|
|
37
|
+
* @param layer - a section, or one of its composition layers.
|
|
38
|
+
* @returns the flat control values, or undefined when the layer carries none.
|
|
39
|
+
*/
|
|
40
|
+
function flatten(layer) {
|
|
41
|
+
if (layer === null || typeof layer !== 'object')
|
|
42
|
+
return undefined;
|
|
43
|
+
const group = groupOf(layer);
|
|
44
|
+
const flat = {};
|
|
45
|
+
for (const [field, path] of Object.entries(FIELD_PATHS)) {
|
|
46
|
+
if (group !== undefined && Object.hasOwn(group, path[1]))
|
|
47
|
+
flat[field] = group[path[1]];
|
|
48
|
+
}
|
|
49
|
+
return flat;
|
|
50
|
+
}
|
|
51
|
+
/** Address one control's edit at the path it really lives at. */
|
|
52
|
+
function locate(op) {
|
|
53
|
+
const path = FIELD_PATHS[op.path[0]];
|
|
54
|
+
return op.op === 'set'
|
|
55
|
+
? { op: 'set', path: [...path], value: op.value }
|
|
56
|
+
: { op: 'unset', path: [...path] };
|
|
57
|
+
}
|
|
58
|
+
/** The shared form model's view of this page's controls, over the real section. */
|
|
59
|
+
class TeamJudgeScope {
|
|
60
|
+
section;
|
|
61
|
+
constructor(section) {
|
|
62
|
+
this.section = section;
|
|
63
|
+
}
|
|
64
|
+
getSnapshot() {
|
|
65
|
+
const snapshot = this.section.getSnapshot();
|
|
66
|
+
return {
|
|
67
|
+
status: snapshot.status,
|
|
68
|
+
value: flatten(snapshot.value),
|
|
69
|
+
base: flatten(snapshot.base),
|
|
70
|
+
user: flatten(snapshot.user),
|
|
71
|
+
writable: snapshot.writable,
|
|
72
|
+
revision: snapshot.revision,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
subscribe(listener) {
|
|
76
|
+
return this.section.subscribe(listener);
|
|
77
|
+
}
|
|
78
|
+
mutate(ops, expectedRevision) {
|
|
79
|
+
return this.section.mutate(ops.map(op => locate(op)), expectedRevision);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
export class TeamJudgeForm {
|
|
83
|
+
section;
|
|
84
|
+
judge;
|
|
85
|
+
model;
|
|
86
|
+
scope;
|
|
87
|
+
store;
|
|
88
|
+
/**
|
|
89
|
+
* @param section - the Team row's configuration form, as the settings provider serves it.
|
|
90
|
+
* @param judge - the status projection a landed write re-reads.
|
|
91
|
+
*/
|
|
92
|
+
constructor(section, judge) {
|
|
93
|
+
this.section = section;
|
|
94
|
+
this.judge = judge;
|
|
95
|
+
this.scope = new TeamJudgeScope(section);
|
|
96
|
+
this.model = new SettingsFormModel(this.scope, [
|
|
97
|
+
settingsTextField('apiBase'),
|
|
98
|
+
settingsTextField('model'),
|
|
99
|
+
], [{
|
|
100
|
+
field: 'apiKey',
|
|
101
|
+
// The literal never rides a response, so a draft is only ever what the
|
|
102
|
+
// reader typed; the write addresses the real path directly.
|
|
103
|
+
write: text => section.mutate([{ op: 'set', path: [...FIELD_PATHS.apiKey], value: text }]),
|
|
104
|
+
}]);
|
|
105
|
+
// The model publishes a projection on every scope change or staged edit;
|
|
106
|
+
// binding one is how this page observes it.
|
|
107
|
+
this.store = this.model.bind(() => this.project());
|
|
108
|
+
}
|
|
109
|
+
/** The form state the page renders. */
|
|
110
|
+
getSnapshot = () => this.store.getSnapshot();
|
|
111
|
+
/** Observe the form state. */
|
|
112
|
+
subscribe = (listener) => this.store.subscribe(listener);
|
|
113
|
+
/** Stage a draft, reset a field, save every staged edit, or discard them. */
|
|
114
|
+
actions() {
|
|
115
|
+
return { ...this.model.actions(), save: () => { void this.save(); } };
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Remove the stored key literal: the judge unmounts and the status re-reads.
|
|
119
|
+
*
|
|
120
|
+
* Deliberately its own write rather than a staged edit — the shared form
|
|
121
|
+
* model has no clear for a write-only control, and an empty draft must keep
|
|
122
|
+
* the stored literal instead of clearing it. The page only offers this while
|
|
123
|
+
* no draft is staged, because a write moves the document revision the staged
|
|
124
|
+
* save is fenced to.
|
|
125
|
+
* @returns whether the Host accepted the clear.
|
|
126
|
+
*/
|
|
127
|
+
async clearKey() {
|
|
128
|
+
let landed;
|
|
129
|
+
try {
|
|
130
|
+
landed = await this.section.mutate([{ op: 'unset', path: [...FIELD_PATHS.apiKey] }]);
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
if (!landed)
|
|
136
|
+
return false;
|
|
137
|
+
await this.judge.refresh();
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
dispose() {
|
|
141
|
+
this.model.dispose();
|
|
142
|
+
}
|
|
143
|
+
/** Build the page's state from the model's reads and drafts. */
|
|
144
|
+
project() {
|
|
145
|
+
const fields = {};
|
|
146
|
+
for (const field of Object.keys(FIELD_PATHS))
|
|
147
|
+
fields[field] = this.model.field(field);
|
|
148
|
+
return { shell: this.model.shell(), fields };
|
|
149
|
+
}
|
|
150
|
+
/** Write every staged edit, then re-read the status the Host now serves. */
|
|
151
|
+
async save() {
|
|
152
|
+
await this.model.save();
|
|
153
|
+
if (!this.model.shell().failed)
|
|
154
|
+
await this.judge.refresh();
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* The form's seat on the page, as an observable rather than a value.
|
|
159
|
+
*
|
|
160
|
+
* The form exists only while this deployment serves a settings document, and
|
|
161
|
+
* that service may arrive after the page's first render. A slot entry's
|
|
162
|
+
* injected props are computed once and cached for the entry's lifetime, so a
|
|
163
|
+
* value handed over at that moment would freeze the answer: the group would
|
|
164
|
+
* never appear until a reload. The page therefore observes this seat, which
|
|
165
|
+
* the service's arrival and departure both publish through.
|
|
166
|
+
*/
|
|
167
|
+
export class TeamJudgeFormSeat {
|
|
168
|
+
form;
|
|
169
|
+
listeners = new Set();
|
|
170
|
+
getSnapshot = () => this.form;
|
|
171
|
+
/**
|
|
172
|
+
* Observe the form, without reading anything on subscribe: the seat carries
|
|
173
|
+
* no remote state of its own, so a subscriber renders whatever is held now.
|
|
174
|
+
* @param listener - invoked after every hold or release.
|
|
175
|
+
* @returns the disposer removing this listener.
|
|
176
|
+
*/
|
|
177
|
+
subscribe = (listener) => {
|
|
178
|
+
this.listeners.add(listener);
|
|
179
|
+
return () => { this.listeners.delete(listener); };
|
|
180
|
+
};
|
|
181
|
+
/**
|
|
182
|
+
* Publish the form the settings service answers with.
|
|
183
|
+
* @param form - the form built over that service's section scope.
|
|
184
|
+
*/
|
|
185
|
+
hold(form) {
|
|
186
|
+
this.form = form;
|
|
187
|
+
this.publish();
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Withdraw the form when its service goes away. Only the holder of the form
|
|
191
|
+
* in place can withdraw it, so a replacement is never cleared by the
|
|
192
|
+
* departure of the one it replaced.
|
|
193
|
+
* @param form - the form this caller holds.
|
|
194
|
+
*/
|
|
195
|
+
release(form) {
|
|
196
|
+
if (this.form !== form)
|
|
197
|
+
return;
|
|
198
|
+
this.form = undefined;
|
|
199
|
+
this.publish();
|
|
200
|
+
}
|
|
201
|
+
dispose() {
|
|
202
|
+
this.listeners.clear();
|
|
203
|
+
}
|
|
204
|
+
publish() {
|
|
205
|
+
for (const listener of this.listeners)
|
|
206
|
+
listener();
|
|
207
|
+
}
|
|
208
|
+
}
|
|
@@ -109,9 +109,9 @@ export declare const zh: {
|
|
|
109
109
|
readonly timelineLabel: "消息时间线";
|
|
110
110
|
readonly taskClosedNotice: "任务已关闭,重新打开后可继续讨论";
|
|
111
111
|
readonly human: "Human";
|
|
112
|
-
readonly
|
|
113
|
-
readonly
|
|
114
|
-
readonly
|
|
112
|
+
readonly teamSettingsNav: "团队";
|
|
113
|
+
readonly teamSettingsTitle: "团队";
|
|
114
|
+
readonly teamSettingsIntro: "你在 Team 里的身份,以及 jev 要用的端点。";
|
|
115
115
|
readonly humanSettingsName: "名字";
|
|
116
116
|
readonly humanSettingsNameHint: "Agents 用这个名字 @ 到你;改名只对之后的消息生效。";
|
|
117
117
|
readonly humanSettingsNameEmpty: "名字不能为空。";
|
|
@@ -131,6 +131,29 @@ export declare const zh: {
|
|
|
131
131
|
readonly humanSettingsUnavailable: "资料读不出来:{message}";
|
|
132
132
|
readonly humanSettingsVersion: "版本 {version}";
|
|
133
133
|
readonly humanSettingsUpdateAvailable: "有新版本 {version},去查看发布说明";
|
|
134
|
+
readonly teamJudgeGroupTitle: "jev";
|
|
135
|
+
readonly teamJudgeGroupHint: "判断隔了很久之后这一步是否仍是同一件事。调用发往 apiBase 下的 /systemone,换端点通常要同时换 model;留空沿用部署默认值。";
|
|
136
|
+
readonly teamJudgeReady: "jev 已就绪";
|
|
137
|
+
readonly teamJudgeNoKey: "未配置 key,填入即启用";
|
|
138
|
+
readonly teamJudgeUnavailable: "jev 不可用:检查 apiBase 与 model";
|
|
139
|
+
readonly teamJudgeApiBase: "apiBase";
|
|
140
|
+
readonly teamJudgeModel: "model";
|
|
141
|
+
readonly teamJudgeKey: "key";
|
|
142
|
+
readonly teamJudgeKeyHint: "只写不回显:留空保存不会改动已存的 key。";
|
|
143
|
+
readonly teamJudgeKeySet: "已配置";
|
|
144
|
+
readonly teamJudgeKeyUnset: "未配置";
|
|
145
|
+
readonly teamJudgeClearKey: "清除 key";
|
|
146
|
+
readonly teamJudgeClearHint: "清除后 jev 立即卸载,不再判断。";
|
|
147
|
+
readonly teamJudgeClearBlocked: "先保存,再清除。";
|
|
148
|
+
readonly teamJudgeClearFailed: "没能清除,请重试。";
|
|
149
|
+
readonly teamSettingsOverridden: "已覆盖";
|
|
150
|
+
readonly teamSettingsReset: "重置";
|
|
151
|
+
readonly teamSettingsInvalid: "这个值不被接受。";
|
|
152
|
+
readonly teamSettingsUnavailable: "这台部署没有提供 Team 的设置文档。";
|
|
153
|
+
readonly teamSettingsReadOnly: "当前设置是只读的。";
|
|
154
|
+
readonly teamSettingsSaveFailed: "保存没有被接受,请检查后重试。";
|
|
155
|
+
readonly teamSettingsSave: "保存";
|
|
156
|
+
readonly teamSettingsSaving: "保存中…";
|
|
134
157
|
readonly environmentOkTitle: "在支持范围内";
|
|
135
158
|
readonly environmentOkDetail: "正在运行的 DSH {version} 在我们声明的支持范围内。";
|
|
136
159
|
readonly environmentOutOfRangeTitle: "不在支持范围内";
|
|
@@ -326,9 +349,9 @@ export declare const en: {
|
|
|
326
349
|
readonly timelineLabel: "Message timeline";
|
|
327
350
|
readonly taskClosedNotice: "This task is closed; reopen it to continue the discussion";
|
|
328
351
|
readonly human: "Human";
|
|
329
|
-
readonly
|
|
330
|
-
readonly
|
|
331
|
-
readonly
|
|
352
|
+
readonly teamSettingsNav: "Team";
|
|
353
|
+
readonly teamSettingsTitle: "Team";
|
|
354
|
+
readonly teamSettingsIntro: "Your identity in the Team, and the endpoint jev calls.";
|
|
332
355
|
readonly humanSettingsName: "Name";
|
|
333
356
|
readonly humanSettingsNameHint: "Agents @ you by this name; a rename applies to later messages only.";
|
|
334
357
|
readonly humanSettingsNameEmpty: "A name is required.";
|
|
@@ -348,6 +371,29 @@ export declare const en: {
|
|
|
348
371
|
readonly humanSettingsUnavailable: "The profile could not be read: {message}";
|
|
349
372
|
readonly humanSettingsVersion: "Version {version}";
|
|
350
373
|
readonly humanSettingsUpdateAvailable: "New version {version} available — see the release notes";
|
|
374
|
+
readonly teamJudgeGroupTitle: "jev";
|
|
375
|
+
readonly teamJudgeGroupHint: "Decides whether a step after a long absence still belongs to the same piece of work. Calls go to /systemone under the apiBase, and changing the endpoint usually means changing the model too; empty inherits the deployment default.";
|
|
376
|
+
readonly teamJudgeReady: "jev is ready";
|
|
377
|
+
readonly teamJudgeNoKey: "No key yet — enter one to enable it";
|
|
378
|
+
readonly teamJudgeUnavailable: "jev is unavailable: check the apiBase and model";
|
|
379
|
+
readonly teamJudgeApiBase: "apiBase";
|
|
380
|
+
readonly teamJudgeModel: "model";
|
|
381
|
+
readonly teamJudgeKey: "key";
|
|
382
|
+
readonly teamJudgeKeyHint: "Write-only: an empty field saves nothing and leaves a stored key in place.";
|
|
383
|
+
readonly teamJudgeKeySet: "Configured";
|
|
384
|
+
readonly teamJudgeKeyUnset: "Not configured";
|
|
385
|
+
readonly teamJudgeClearKey: "Clear key";
|
|
386
|
+
readonly teamJudgeClearHint: "Clearing unmounts jev immediately; nothing is judged after that.";
|
|
387
|
+
readonly teamJudgeClearBlocked: "Save first, then clear.";
|
|
388
|
+
readonly teamJudgeClearFailed: "The key could not be cleared; try again.";
|
|
389
|
+
readonly teamSettingsOverridden: "Overridden";
|
|
390
|
+
readonly teamSettingsReset: "Reset";
|
|
391
|
+
readonly teamSettingsInvalid: "This value is not accepted.";
|
|
392
|
+
readonly teamSettingsUnavailable: "This deployment does not serve the Team settings document.";
|
|
393
|
+
readonly teamSettingsReadOnly: "Settings are read-only right now.";
|
|
394
|
+
readonly teamSettingsSaveFailed: "The save was not accepted; check the values and try again.";
|
|
395
|
+
readonly teamSettingsSave: "Save";
|
|
396
|
+
readonly teamSettingsSaving: "Saving…";
|
|
351
397
|
readonly environmentOkTitle: "Within the supported range";
|
|
352
398
|
readonly environmentOkDetail: "The running DSH {version} is within the range we declare support for.";
|
|
353
399
|
readonly environmentOutOfRangeTitle: "Outside the supported range";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../../../src/client/locales.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,EAAE
|
|
1
|
+
{"version":3,"file":"locales.d.ts","sourceRoot":"","sources":["../../../src/client/locales.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyPL,CAAA;AAEV,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiPL,CAAA;AAEV,MAAM,MAAM,OAAO,GAAG,MAAM,OAAO,EAAE,CAAA"}
|
|
@@ -109,9 +109,9 @@ export const zh = {
|
|
|
109
109
|
timelineLabel: '消息时间线',
|
|
110
110
|
taskClosedNotice: '任务已关闭,重新打开后可继续讨论',
|
|
111
111
|
human: 'Human',
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
112
|
+
teamSettingsNav: '团队',
|
|
113
|
+
teamSettingsTitle: '团队',
|
|
114
|
+
teamSettingsIntro: '你在 Team 里的身份,以及 jev 要用的端点。',
|
|
115
115
|
humanSettingsName: '名字',
|
|
116
116
|
humanSettingsNameHint: 'Agents 用这个名字 @ 到你;改名只对之后的消息生效。',
|
|
117
117
|
humanSettingsNameEmpty: '名字不能为空。',
|
|
@@ -131,6 +131,32 @@ export const zh = {
|
|
|
131
131
|
humanSettingsUnavailable: '资料读不出来:{message}',
|
|
132
132
|
humanSettingsVersion: '版本 {version}',
|
|
133
133
|
humanSettingsUpdateAvailable: '有新版本 {version},去查看发布说明',
|
|
134
|
+
// The Team page's judge group: the endpoint jev is mounted from, and the one
|
|
135
|
+
// line that says whether it is reachable right now. The group is named for
|
|
136
|
+
// the component a reader configures rather than for a role it plays.
|
|
137
|
+
teamJudgeGroupTitle: 'jev',
|
|
138
|
+
teamJudgeGroupHint: '判断隔了很久之后这一步是否仍是同一件事。调用发往 apiBase 下的 /systemone,换端点通常要同时换 model;留空沿用部署默认值。',
|
|
139
|
+
teamJudgeReady: 'jev 已就绪',
|
|
140
|
+
teamJudgeNoKey: '未配置 key,填入即启用',
|
|
141
|
+
teamJudgeUnavailable: 'jev 不可用:检查 apiBase 与 model',
|
|
142
|
+
teamJudgeApiBase: 'apiBase',
|
|
143
|
+
teamJudgeModel: 'model',
|
|
144
|
+
teamJudgeKey: 'key',
|
|
145
|
+
teamJudgeKeyHint: '只写不回显:留空保存不会改动已存的 key。',
|
|
146
|
+
teamJudgeKeySet: '已配置',
|
|
147
|
+
teamJudgeKeyUnset: '未配置',
|
|
148
|
+
teamJudgeClearKey: '清除 key',
|
|
149
|
+
teamJudgeClearHint: '清除后 jev 立即卸载,不再判断。',
|
|
150
|
+
teamJudgeClearBlocked: '先保存,再清除。',
|
|
151
|
+
teamJudgeClearFailed: '没能清除,请重试。',
|
|
152
|
+
teamSettingsOverridden: '已覆盖',
|
|
153
|
+
teamSettingsReset: '重置',
|
|
154
|
+
teamSettingsInvalid: '这个值不被接受。',
|
|
155
|
+
teamSettingsUnavailable: '这台部署没有提供 Team 的设置文档。',
|
|
156
|
+
teamSettingsReadOnly: '当前设置是只读的。',
|
|
157
|
+
teamSettingsSaveFailed: '保存没有被接受,请检查后重试。',
|
|
158
|
+
teamSettingsSave: '保存',
|
|
159
|
+
teamSettingsSaving: '保存中…',
|
|
134
160
|
// The environment check. The support line is stated in words, never as a bare
|
|
135
161
|
// semver range, and the tested-combination line prints only versions the Host
|
|
136
162
|
// could derive — the page adds no version of its own.
|
|
@@ -333,9 +359,9 @@ export const en = {
|
|
|
333
359
|
timelineLabel: 'Message timeline',
|
|
334
360
|
taskClosedNotice: 'This task is closed; reopen it to continue the discussion',
|
|
335
361
|
human: 'Human',
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
362
|
+
teamSettingsNav: 'Team',
|
|
363
|
+
teamSettingsTitle: 'Team',
|
|
364
|
+
teamSettingsIntro: 'Your identity in the Team, and the endpoint jev calls.',
|
|
339
365
|
humanSettingsName: 'Name',
|
|
340
366
|
humanSettingsNameHint: 'Agents @ you by this name; a rename applies to later messages only.',
|
|
341
367
|
humanSettingsNameEmpty: 'A name is required.',
|
|
@@ -355,6 +381,29 @@ export const en = {
|
|
|
355
381
|
humanSettingsUnavailable: 'The profile could not be read: {message}',
|
|
356
382
|
humanSettingsVersion: 'Version {version}',
|
|
357
383
|
humanSettingsUpdateAvailable: 'New version {version} available — see the release notes',
|
|
384
|
+
teamJudgeGroupTitle: 'jev',
|
|
385
|
+
teamJudgeGroupHint: 'Decides whether a step after a long absence still belongs to the same piece of work. Calls go to /systemone under the apiBase, and changing the endpoint usually means changing the model too; empty inherits the deployment default.',
|
|
386
|
+
teamJudgeReady: 'jev is ready',
|
|
387
|
+
teamJudgeNoKey: 'No key yet — enter one to enable it',
|
|
388
|
+
teamJudgeUnavailable: 'jev is unavailable: check the apiBase and model',
|
|
389
|
+
teamJudgeApiBase: 'apiBase',
|
|
390
|
+
teamJudgeModel: 'model',
|
|
391
|
+
teamJudgeKey: 'key',
|
|
392
|
+
teamJudgeKeyHint: 'Write-only: an empty field saves nothing and leaves a stored key in place.',
|
|
393
|
+
teamJudgeKeySet: 'Configured',
|
|
394
|
+
teamJudgeKeyUnset: 'Not configured',
|
|
395
|
+
teamJudgeClearKey: 'Clear key',
|
|
396
|
+
teamJudgeClearHint: 'Clearing unmounts jev immediately; nothing is judged after that.',
|
|
397
|
+
teamJudgeClearBlocked: 'Save first, then clear.',
|
|
398
|
+
teamJudgeClearFailed: 'The key could not be cleared; try again.',
|
|
399
|
+
teamSettingsOverridden: 'Overridden',
|
|
400
|
+
teamSettingsReset: 'Reset',
|
|
401
|
+
teamSettingsInvalid: 'This value is not accepted.',
|
|
402
|
+
teamSettingsUnavailable: 'This deployment does not serve the Team settings document.',
|
|
403
|
+
teamSettingsReadOnly: 'Settings are read-only right now.',
|
|
404
|
+
teamSettingsSaveFailed: 'The save was not accepted; check the values and try again.',
|
|
405
|
+
teamSettingsSave: 'Save',
|
|
406
|
+
teamSettingsSaving: 'Saving…',
|
|
358
407
|
environmentOkTitle: 'Within the supported range',
|
|
359
408
|
environmentOkDetail: 'The running DSH {version} is within the range we declare support for.',
|
|
360
409
|
environmentOutOfRangeTitle: 'Outside the supported range',
|
|
@@ -7,13 +7,16 @@ Model-facing tools for Agent Team Members. The package registers tools in the ca
|
|
|
7
7
|
## Tools
|
|
8
8
|
|
|
9
9
|
- `team_inbox` lists bounded unread Thread summaries for the calling Member, ordered by direct work and then recency; Task standing appears only where the Thread has a real Task overlay. The header states total unread/direct counts and the number of Threads shown (with a truncation conclusion when unread work lies beyond the bounded list); each item shows its exact unread/direct counts, Channel ref, and Task standing. The footer routes reading to `team_thread read`; the render carries no revision and no write token.
|
|
10
|
-
- `team_thread` reads a Thread, pages history, follows, or unfollows. `threadRef` is primary; a `taskRef` is a Host alias only for released task-only Clients. The five actions render separately: `status`/`follow`/`unfollow` answer only the Attention question in one line; `read` renders outcome, Thread identity, orientation (full anchor when Host-supplied background is present, bounded anchor subject otherwise — and no background at all for a Member re-entering a Thread it has already read, so its orientation there is that subject plus this batch — never a duplicate of an in-facts anchor), active Claims only, the chronological facts with inline unread/direct markers, and a read-through/remaining-unread footer that also states how many Thread facts precede the watermark whenever the read left any behind; `history` renders a historical page with the full anchor on a first page and the bounded subject on continuation pages, never current Claims or advice. `read` advances the durable watermark and is the only read-side source of a next-write token — rendered only when no unread remains; your own committed public mutations hand off a fresh token as well. A read with nothing unread for the caller advances nothing, writes no operation, and renders `Read — no unread updates …` instead of claiming a commit, still answering from the current projection. Activity facts render structured — actor, Task ref, and the Claim refs each activity claimed, completed, accepted, or released. A read that acknowledges an unread acceptance of a still-done Task carries one `contextAdvice` block (usage, route budgets, the `min(128_000, handoffAt)` Task-boundary threshold, and one keep/rollover/
|
|
10
|
+
- `team_thread` reads a Thread, pages history, follows, or unfollows. `threadRef` is primary; a `taskRef` is a Host alias only for released task-only Clients. The five actions render separately: `status`/`follow`/`unfollow` answer only the Attention question in one line; `read` renders outcome, Thread identity, orientation (full anchor when Host-supplied background is present, bounded anchor subject otherwise — and no background at all for a Member re-entering a Thread it has already read, so its orientation there is that subject plus this batch — never a duplicate of an in-facts anchor), active Claims only, the chronological facts with inline unread/direct markers, and a read-through/remaining-unread footer that also states how many Thread facts precede the watermark whenever the read left any behind; `history` renders a historical page with the full anchor on a first page and the bounded subject on continuation pages, never current Claims or advice. `read` advances the durable watermark and is the only read-side source of a next-write token — rendered only when no unread remains; your own committed public mutations hand off a fresh token as well. A read with nothing unread for the caller advances nothing, writes no operation, and renders `Read — no unread updates …` instead of claiming a commit, still answering from the current projection. Activity facts render structured — actor, Task ref, and the Claim refs each activity claimed, completed, accepted, or released. A read that acknowledges an unread acceptance of a still-done Task carries one `contextAdvice` block (usage, route budgets, the `min(128_000, handoffAt)` Task-boundary threshold, and one keep/rollover/compact-now action); it is advisory only and degrades to an explicit `unavailable` line when measurement fails.
|
|
11
11
|
- `team_message` starts a top-level Thread, replies to an existing Thread, or sends a DM. It defaults to a taskless Thread; pass `asTask: true` for atomic Task creation. A committed start/reply renders one committed-verb outcome (Thread created / reply added) with the Message, Thread, and optional Task refs, and exactly one next-write token hand-off. Replies reject unread work before checking token freshness. Typed rejections begin `Not committed`, keep the structured refs and counts needed to reread and retry, and render no numeric revision or write token — recovery is read-and-reconsider. DMs distinguish `Delivered` from `Recorded, not delivered` (with the delivery note and a no-blind-duplicate warning).
|
|
12
12
|
- `team_claim` lists or mutates the calling Member's Direction Claims through `list`, `claim`, `done`, and `release`; it applies only to real Tasks. `list` renders the Task/Thread identity with active Claims only (the collision surface) and no write token. A committed mutation names its action (Claim created/completed/released), renders the authoritative affected Claim first, and hands off one next-write token. Rejections share the message rejection form. Direction exclusion uses Unicode NFKC normalization, trim, whitespace compression, and deterministic case folding.
|
|
13
13
|
- `team_view` is the address book: bounded, membership-authorized Channel, top-level Thread, and Member summaries — current addresses, not a work queue. Threads are the sole paginated catalog: newest-first rows carrying threadRef, Channel ref, a bounded anchor subject, and Task standing inline (never a second Task index, never revision or message count). The cursor pages Thread rows only; continuation pages render Threads alone, and paging reaches every authorized top-level Thread, including taskless and off-page taskful ones.
|
|
14
|
-
- `context_rollover` schedules one rollover of the calling Member into a fresh context. The tool validates the bounded private `handoff` (plus optional `relatedFiles`, or a `checkpointRef` to return to a recorded checkpoint instead) against the Host, concludes the turn, and returns `status: 'scheduled'`; the Host performs the actual swap only after the successful tool result is durably appended. The `checkpointRef` copy is hardened on both the tool and parameter descriptions: omit it for ordinary generation changes and pressure-driven handoffs, and supply it only when citing the exact ref a `
|
|
14
|
+
- `context_rollover` schedules one rollover of the calling Member into a fresh context. The tool validates the bounded private `handoff` (plus optional `relatedFiles`, or a `checkpointRef` to return to a recorded checkpoint instead) against the Host, concludes the turn, and returns `status: 'scheduled'`; the Host performs the actual swap only after the successful tool result is durably appended. The `checkpointRef` copy is hardened on both the tool and parameter descriptions: omit it for ordinary generation changes and pressure-driven handoffs, and supply it only when citing the exact ref a `context_status` result listed as restorable — never a synthesized or guessed one. A `checkpointRef` that cannot succeed now — fabricated, unresolved, unattributable, nonshrinking, unmeasurable, over-budget, or blocked by multiple active Claims — rejects as a model-visible error result instead of a fake `scheduled`; the mutable guards (jobs, route limits) are revalidated at the swap seam, and a seam failure leaves the Member recoverable through a later-turn fresh rollover. `context_rollover` and `context_checkpoint` both conclude the Agent turn.
|
|
15
15
|
- `context_checkpoint` records one named checkpoint of the calling Member's current context. The durable checkpoint is the successful `tool/call`+`tool/result` pair the Session projection folds; the returned ref is deterministic from the Member Session identity plus the tool call id. It performs no lifecycle side effect in the tool body and concludes the turn: a checkpoint resolves at its containing turn's end, so the model records it as its final action of a completed unit of work.
|
|
16
|
-
- `
|
|
16
|
+
- `context_status` returns one bounded structural view of the Member's context generations across the current Session and its archived ancestor lineage: recorded checkpoints and handoff/Team/compaction boundaries, with restorability reasons where a return cannot be proven safe, plus the Member's usage against the handoff budget and, where the scope can price one, what a compaction started now would replace. A Team boundary is offered exactly when the retained prefix through it stays inside one Thread and the return would shrink the working set below the handoff budget. On a row that is not restorable the Team answers with a short stable `anchor` digest of that row's own ref, so rows sharing a name and a price stay distinguishable and no non-selectable row carries a citable string; only the `ref` printed on a restorable row can be cited. Structural only — no transcript content. A fresh `context_rollover` never requires reading the status first.
|
|
17
|
+
- `context_compact` shortens the calling Member's current generation in place: one stretch of older history is replaced by a summary while the newest work stays verbatim. It never switches generation and never returns to an anchor. A Member whose preset mounts no compaction engine is told the capability is unavailable in this scope, and a context with nothing safe to replace reports itself unchanged.
|
|
18
|
+
|
|
19
|
+
All four context tools are the engine's own definitions, built by `createContinuityTools`: the engine owns their argument contract, the anti-forgery gate on a cited ref, the turn-conclusion timing, and the render shapes, while the Team supplies its vocabulary and the adapter behind them.
|
|
17
20
|
|
|
18
21
|
Mentions are authored in the Message body, as `@Handle` (the `@` is required, matching ignores case, and `@all` reaches the Channel); there is no recipient parameter. An Agent cannot silently enroll an uninvited Member: naming one this Thread has never carried commits the Message, delivers nothing to that Member, and reports them as undelivered. Human confirmation is a separate Host/Client flow. Closed Tasks reject replies, Claims, and new Attention until a Human reopens them; taskless Threads have no Claim or Task-resolution mutation path.
|
|
19
22
|
|
|
@@ -7,13 +7,16 @@
|
|
|
7
7
|
## 工具
|
|
8
8
|
|
|
9
9
|
- `team_inbox` 列出调用方 Member 的有界未读 Thread 摘要,先按 direct work、再按最近活动排序;只有 Thread 存在真实 Task overlay 时才出现 Task standing。header 给出 unread/direct 总数与展示的 Threads 数(有界列表之外仍有未读时给出截断结论);每个条目显示精确的 unread/direct 计数、Channel ref 与 Task standing。页脚把阅读指向 `team_thread read`;渲染不携带 revision 与写令牌。
|
|
10
|
-
- `team_thread` 读取 Thread、分页历史、follow 或 unfollow。`threadRef` 是主身份;`taskRef` 只对 released task-only Client 是 Host alias。五个 action 分开渲染:`status`/`follow`/`unfollow` 一行只回答 Attention 问题;`read` 渲染结果、Thread 身份、导向(有 Host 提供的 background 时给 full anchor,否则给 bounded anchor subject——重新进入自己读过的 Thread 的 Member 完全没有 background,它在那里的定位就是该 subject 加本次 batch——anchor 已在 facts 中时绝不重复)、只含 active Claims、带行内 unread/direct 标记的按时间 facts、read-through/剩余未读页脚(只要这次 read 身后留有 Thread facts,页脚同时给出那些 facts 的数量);`history` 渲染历史页(首页 full anchor、continuation 页 bounded subject,绝无当前 Claims 或 advice)。`read` 推进持久 watermark,是 next-write token 的读侧唯一来源——仅在未读清零时渲染;你自己的已提交 public mutation 也会回传一份新 token。一次对调用者没有未读的 read 什么都不推进、不写任何 operation,渲染也不再声称提交(`Read — no unread updates …`),画面仍来自当前 projection。Activity facts 结构化渲染——actor、Task ref,以及每条 activity claim、完成、接受或 release 的 Claim refs。确认仍为 done 状态 Task 的未读验收的那次 read 附带一段 `contextAdvice`(用量、路由预算、`min(128_000, handoffAt)` 任务边界阈值、keep/rollover/
|
|
10
|
+
- `team_thread` 读取 Thread、分页历史、follow 或 unfollow。`threadRef` 是主身份;`taskRef` 只对 released task-only Client 是 Host alias。五个 action 分开渲染:`status`/`follow`/`unfollow` 一行只回答 Attention 问题;`read` 渲染结果、Thread 身份、导向(有 Host 提供的 background 时给 full anchor,否则给 bounded anchor subject——重新进入自己读过的 Thread 的 Member 完全没有 background,它在那里的定位就是该 subject 加本次 batch——anchor 已在 facts 中时绝不重复)、只含 active Claims、带行内 unread/direct 标记的按时间 facts、read-through/剩余未读页脚(只要这次 read 身后留有 Thread facts,页脚同时给出那些 facts 的数量);`history` 渲染历史页(首页 full anchor、continuation 页 bounded subject,绝无当前 Claims 或 advice)。`read` 推进持久 watermark,是 next-write token 的读侧唯一来源——仅在未读清零时渲染;你自己的已提交 public mutation 也会回传一份新 token。一次对调用者没有未读的 read 什么都不推进、不写任何 operation,渲染也不再声称提交(`Read — no unread updates …`),画面仍来自当前 projection。Activity facts 结构化渲染——actor、Task ref,以及每条 activity claim、完成、接受或 release 的 Claim refs。确认仍为 done 状态 Task 的未读验收的那次 read 附带一段 `contextAdvice`(用量、路由预算、`min(128_000, handoffAt)` 任务边界阈值、keep/rollover/compact-now 唯一动作);它只是建议,测量失败时降级为显式 `unavailable` 文案。
|
|
11
11
|
- `team_message` 创建顶层 Thread、回复既有 Thread 或发送 DM。默认创建 taskless Thread;传入 `asTask: true` 才原子创建 Task。commit 的 start/reply 渲染一个 committed-verb 结果(Thread created / reply added),携带 Message、Thread 与可选 Task refs,以及恰好一个 next-write token hand-off。Reply 在检查令牌新鲜度前先拒绝未读工作。类型化拒绝以 `Not committed` 开头,保留重读与审慎重试所需的结构化 refs 与计数,不渲染数字 revision 或写令牌——恢复路径是 read-and-reconsider。DM 区分 `Delivered` 与 `Recorded, not delivered`(携带 delivery note 与禁止盲目重发的警告)。
|
|
12
12
|
- `team_claim` 通过 `list`、`claim`、`done`、`release` 读取或修改调用方 Member 的 Direction Claim;它只适用于真实 Task。`list` 渲染 Task/Thread 身份与只有 active Claims 的 collision surface,且无写令牌。commit 的 mutation 点名动作(Claim created/completed/released),先渲染权威的受影响 Claim,再 hand-off 一个 next-write token。拒绝与 message 拒绝共享同一形式。Direction 互斥键执行 Unicode NFKC normalization、trim、空白压缩和确定性大小写折叠。
|
|
13
13
|
- `team_view` 是 address book:有界、按 membership 授权的 Channel、顶层 Thread 与 Member 摘要——是当前的地址簿,不是工作队列。Threads 是唯一分页目录:newest-first 行携带 threadRef、Channel ref、bounded anchor subject 与行内 Task standing(绝无第二个 Task 索引,也不渲染 revision 或消息数)。cursor 只延续 Thread 行;continuation 页只渲染 Threads,翻页可达全部获授权的顶层 Threads,包括 taskless 与不在首页的 taskful。
|
|
14
|
-
- `context_rollover` 为调用方 Member 安排一次进入全新上下文的 rollover。工具向 Host 校验有界的私有 `handoff`(及可选 `relatedFiles`;传入 `checkpointRef` 则改为回返到已记录的 checkpoint),结束当前 turn 并返回 `status: 'scheduled'`;Host 只在成功的 tool result 持久落盘后才执行真正的换窗。`checkpointRef` 在工具与参数两级 description 上做了 copy hardening:普通续代与压力换窗必须省略,只有引用 `
|
|
14
|
+
- `context_rollover` 为调用方 Member 安排一次进入全新上下文的 rollover。工具向 Host 校验有界的私有 `handoff`(及可选 `relatedFiles`;传入 `checkpointRef` 则改为回返到已记录的 checkpoint),结束当前 turn 并返回 `status: 'scheduled'`;Host 只在成功的 tool result 持久落盘后才执行真正的换窗。`checkpointRef` 在工具与参数两级 description 上做了 copy hardening:普通续代与压力换窗必须省略,只有引用 `context_status` 结果中列为 restorable 的精确 ref 时才提供——绝不合成或猜测。当下不可能成功的 `checkpointRef`——伪造、未 resolve、无法归属、不缩减、不可测量、超预算或被多个 active Claim 阻塞——以 model-visible 的 error result 拒绝,而不是返回假 `scheduled`;可变 guards(jobs、route limits)在换窗 seam 复查,seam 失败后 Member 仍可通过后续 turn 的显式 fresh rollover 恢复。`context_rollover` 与 `context_checkpoint` 都会结束 Agent turn(换窗后不得再接旧代工作;checkpoint 在其所属 turn 结束时 resolve)。
|
|
15
15
|
- `context_checkpoint` 为调用的 Member 记录一个命名的当前上下文 checkpoint。durable checkpoint 就是 Session projection 折叠的成功 `tool/call`+`tool/result` 对;返回的 ref 由 Member Session 身份加 tool call id 确定性派生。工具体不做 lifecycle 副作用,但会结束 turn:checkpoint 在其所属 turn 结束时 resolve,因此模型把它作为一个完整工作单元的最后动作来记录。
|
|
16
|
-
- `
|
|
16
|
+
- `context_status` 返回该 Member 跨当前 Session 与已归档祖先 lineage 的上下文代际有界结构视图:已记录的 checkpoints 与 handoff/Team/compaction 边界,无法证明可安全回返的条目携带拒绝原因;同时给出该 Member 相对 handoff 预算的用量,以及作用域能定价时此刻发起 compaction 会替换的内容。Team 边界只有在「经它保留的前缀仍停留在单一 Thread 内」且回返能把工作集缩到 handoff 预算之下时才会被提供。对不可返回的行,Team 以该行自身 ref 的短稳定 `anchor` 摘要作答,使名称与价格相同的行仍可区分,且任何不可选择的行都不携带可引用的字符串;只有 restorable 行上打印的 `ref` 可被引用。仅结构信息——不含任何 transcript 正文。fresh 的 `context_rollover` 从不需要先读 status。
|
|
17
|
+
- `context_compact` 就地缩短调用方 Member 的当前代:较早历史中的一段被替换为摘要,最新工作保持原文。它绝不切换代际,也绝不回返到锚点。preset 未挂载 compaction 引擎的 Member 会被告知该能力在此作用域不可用;没有可安全替换内容的上下文会报告自身未改变。
|
|
18
|
+
|
|
19
|
+
四个 context 工具全部用引擎自己的定义(`createContinuityTools`):参数契约、对引用 ref 的 anti-forgery 门、结束 turn 的时机与渲染形状都由引擎负责,Team 只提供自己的词汇与它们背后的 adapter。
|
|
17
20
|
|
|
18
21
|
mention 在 Message 正文里撰写,形如 `@Handle`(`@` 必需、大小写不敏感,`@all` 触达整个 Channel);不存在收件人参数。Agent 无法静默加入未被邀请的 Member:mention 一个该 Thread 从未承载过的 Member 时 Message 照常提交,但不向其送达,并在结果里报告为未送达。Human confirmation 属于单独的 Host/Client 流程。Closed Task 在 Human reopen 前拒绝 reply、Claim 和新的 Attention;taskless Thread 没有 Claim 或 Task resolution mutation path。
|
|
19
22
|
|