@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.
Files changed (67) hide show
  1. package/README.md +5 -5
  2. package/README.zh.md +5 -5
  3. package/cordis.patch.yml +26 -12
  4. package/package.json +50 -47
  5. package/packages/agent-team/lib/attachments.js +63 -4
  6. package/packages/agent-team/lib/compaction-engine.js +18 -0
  7. package/packages/agent-team/lib/context-continuity-host.js +198 -4
  8. package/packages/agent-team/lib/context-judge.js +150 -0
  9. package/packages/agent-team/lib/index.js +482 -97
  10. package/packages/agent-team/lib/invariant.js +36 -12
  11. package/packages/agent-team/lib/ledger.js +2 -1
  12. package/packages/agent-team/lib/member-runtime.js +2 -1
  13. package/packages/agent-team/lib/recovery.js +53 -4
  14. package/packages/agent-team/lib/typert.host.js +138 -44
  15. package/packages/agent-team/lib/typert.remote-client.d.ts +3 -1
  16. package/packages/agent-team/lib/typert.remote-client.d.ts.map +1 -1
  17. package/packages/agent-team/lib/typert.remote-client.js +75 -35
  18. package/packages/agent-team/lib/types/attachments.d.ts +32 -2
  19. package/packages/agent-team/lib/types/attachments.d.ts.map +1 -1
  20. package/packages/agent-team/lib/types/compaction-engine.d.ts +19 -0
  21. package/packages/agent-team/lib/types/compaction-engine.d.ts.map +1 -0
  22. package/packages/agent-team/lib/types/context-continuity-host.d.ts +131 -4
  23. package/packages/agent-team/lib/types/context-continuity-host.d.ts.map +1 -1
  24. package/packages/agent-team/lib/types/context-judge.d.ts +82 -0
  25. package/packages/agent-team/lib/types/context-judge.d.ts.map +1 -0
  26. package/packages/agent-team/lib/types/index.d.ts +259 -17
  27. package/packages/agent-team/lib/types/index.d.ts.map +1 -1
  28. package/packages/agent-team/lib/types/invariant.d.ts +27 -5
  29. package/packages/agent-team/lib/types/invariant.d.ts.map +1 -1
  30. package/packages/agent-team/lib/types/ledger.d.ts.map +1 -1
  31. package/packages/agent-team/lib/types/member-runtime.d.ts +1 -1
  32. package/packages/agent-team/lib/types/member-runtime.d.ts.map +1 -1
  33. package/packages/agent-team/lib/types/recovery.d.ts +19 -6
  34. package/packages/agent-team/lib/types/recovery.d.ts.map +1 -1
  35. package/packages/agent-team/lib/types/types/requests-results.d.ts +28 -2
  36. package/packages/agent-team/lib/types/types/requests-results.d.ts.map +1 -1
  37. package/packages/agent-team/lib/types/types.d.ts +9 -0
  38. package/packages/agent-team/lib/types/types.d.ts.map +1 -1
  39. package/packages/client-agent-team/lib/client.js +1006 -374
  40. package/packages/client-agent-team/lib/client.js.map +1 -1
  41. package/packages/client-agent-team/lib/types/client/{HumanSettingsSection.d.ts → TeamSettingsSection.d.ts} +12 -4
  42. package/packages/client-agent-team/lib/types/client/TeamSettingsSection.d.ts.map +1 -0
  43. package/packages/client-agent-team/lib/types/client/TeamSettingsSection.js +195 -0
  44. package/packages/client-agent-team/lib/types/client/attachment-preview.d.ts +7 -11
  45. package/packages/client-agent-team/lib/types/client/attachment-preview.d.ts.map +1 -1
  46. package/packages/client-agent-team/lib/types/client/attachment-preview.js +13 -3
  47. package/packages/client-agent-team/lib/types/client/context-judge.d.ts +64 -0
  48. package/packages/client-agent-team/lib/types/client/context-judge.d.ts.map +1 -0
  49. package/packages/client-agent-team/lib/types/client/context-judge.js +78 -0
  50. package/packages/client-agent-team/lib/types/client/index.d.ts.map +1 -1
  51. package/packages/client-agent-team/lib/types/client/index.js +75 -11
  52. package/packages/client-agent-team/lib/types/client/judge-form.d.ts +99 -0
  53. package/packages/client-agent-team/lib/types/client/judge-form.d.ts.map +1 -0
  54. package/packages/client-agent-team/lib/types/client/judge-form.js +208 -0
  55. package/packages/client-agent-team/lib/types/client/locales.d.ts +52 -6
  56. package/packages/client-agent-team/lib/types/client/locales.d.ts.map +1 -1
  57. package/packages/client-agent-team/lib/types/client/locales.js +55 -6
  58. package/packages/tool-agent-team/README.md +6 -3
  59. package/packages/tool-agent-team/README.zh.md +6 -3
  60. package/packages/tool-agent-team/lib/context-tools.js +84 -112
  61. package/packages/tool-agent-team/lib/types/context-tools.d.ts +29 -13
  62. package/packages/tool-agent-team/lib/types/context-tools.d.ts.map +1 -1
  63. package/packages/agent-team/lib/pressure-policy.js +0 -235
  64. package/packages/agent-team/lib/types/pressure-policy.d.ts +0 -134
  65. package/packages/agent-team/lib/types/pressure-policy.d.ts.map +0 -1
  66. package/packages/client-agent-team/lib/types/client/HumanSettingsSection.d.ts.map +0 -1
  67. package/packages/client-agent-team/lib/types/client/HumanSettingsSection.js +0 -118
@@ -1,134 +0,0 @@
1
- /**
2
- * Team-owned context pressure policy.
3
- *
4
- * The Team preset mounts `compaction-basic` with `auto: false`; this
5
- * coordinator owns both policy entry points instead — the proactive handoff
6
- * notice near the effective handoff budget and the forced CompactionEngine
7
- * reduction before any request at or above the effective hard limit — while
8
- * reusing the public CompactionEngine implementation. The hard-limit
9
- * translation lives in exactly one method; no caller re-derives it.
10
- *
11
- * Fail-closed rule: at the hard limit, a compaction that no-ops, throws, is
12
- * cancelled, or does not advance the durable surface must block the model
13
- * request (reject the step) rather than knowingly submit over the Team limit.
14
- * A blocked Member keeps its log and reports a recoverable error.
15
- * @module @wowyuarm/dsh-agent-team/pressure-policy
16
- */
17
- import type { Agent } from '@deepseek-ai/dsh-agent';
18
- import type { CompactionEngine } from '@deepseek-ai/dsh-compaction';
19
- import type { AgentTeamMemberId } from './types.ts';
20
- import type { SessionEvent } from '@deepseek-ai/dsh-session';
21
- import { type SessionEventFold } from './session-event-cursor.ts';
22
- /**
23
- * Stable summary of the one-shot rollover pressure notice. It is a durable
24
- * marker: the notice's own presence in a Session's log is what latches the
25
- * policy, so the wording is read back and must not drift.
26
- */
27
- export declare const CONTEXT_PRESSURE_NOTICE_SUMMARY = "Context pressure: prepare a handoff";
28
- /**
29
- * Whether this Session's own span already carries the pressure notice: either
30
- * surfaced as a `user/message` or still queued in a durable
31
- * `agent/inbox/spliced` insert. Expressed as a fold rather than a scan because
32
- * the answer is monotone — once delivered it stays delivered for the
33
- * generation — so the cursor only ever has to read events it has not seen.
34
- */
35
- export declare const PRESSURE_NOTICE_FOLD: SessionEventFold<boolean, SessionEvent>;
36
- /**
37
- * One pressure-notice text. The wording is the engine's — the same sentence a
38
- * fresh-context handoff is asked for through — so the notice and the rollover
39
- * tool cannot drift apart; Team supplies only its own labels and input shape.
40
- */
41
- export declare function contextPressureNoticeText(input: {
42
- readonly usageTokens: number;
43
- readonly handoffAt: number;
44
- readonly hardLimit: number;
45
- readonly activeClaims: readonly string[];
46
- readonly runningJobs: readonly string[];
47
- }): string;
48
- export interface PressurePolicyOptions {
49
- /** Resolve the live Agent of one Member. */
50
- readonly agentForMember: (memberId: AgentTeamMemberId) => Agent | undefined;
51
- /** Resolve the durable Member of one live Agent. */
52
- readonly memberForAgent: (agent: Agent) => {
53
- readonly memberId: AgentTeamMemberId;
54
- readonly sessionId: Agent['id'];
55
- } | undefined;
56
- /** Resolve the Member-scoped compaction engine. */
57
- readonly compactionForAgent: (agent: Agent) => CompactionEngine | undefined;
58
- /** Effective budgets for one Member's current route; undefined means the route window is unknown. */
59
- readonly limitsForAgent: (agent: Agent) => Promise<{
60
- readonly usageTokens: number;
61
- readonly hardLimit: number;
62
- readonly handoffAt: number;
63
- } | undefined> | {
64
- readonly usageTokens: number;
65
- readonly hardLimit: number;
66
- readonly handoffAt: number;
67
- } | undefined;
68
- /** The model-visible active-Claim labels for one Member's notice. */
69
- readonly activeClaimLabels: (memberId: AgentTeamMemberId) => readonly string[];
70
- /** The model-visible running-job labels for one Member's notice. */
71
- readonly runningJobLabels: (memberId: AgentTeamMemberId) => readonly string[];
72
- /** Report a Member failure with a recoverable diagnostic. */
73
- readonly failed: (memberId: AgentTeamMemberId, sessionId: Agent['id'], diagnostic: string) => void;
74
- /** Log one coordinator diagnostic. */
75
- readonly log: (message: string) => void;
76
- }
77
- export declare class PressurePolicyCoordinator {
78
- private readonly options;
79
- /**
80
- * Retry budget per agent for the current provider-overflow sequence.
81
- * Process-only by design: a restart re-earns one sequence per chain.
82
- */
83
- private readonly overflowRetries;
84
- /**
85
- * Whether the one-shot notice was already delivered, folded incrementally per
86
- * Member. The scan below is a monotone "has this ever happened" fold over the
87
- * Session's own events, so a cursor can replace re-scanning the whole log on
88
- * every step; identity guarding falls back to a cold fold when the Member's
89
- * Session changed under the entry.
90
- */
91
- private readonly noticeSeen;
92
- private disposed;
93
- constructor(options: PressurePolicyOptions);
94
- /**
95
- * The one-shot pressure notice is durable Session evidence, not process
96
- * state: a `CONTEXT_PRESSURE_NOTICE_SUMMARY` notice already surfaced as a
97
- * `user/message`, or still queued in a durable `agent/inbox/spliced`
98
- * insert (a steered notice surfaces only at the next step boundary, and a
99
- * Host restart replays the splice before surfacing), marks the current
100
- * generation as already notified. A resume or restart stays quiet; a
101
- * rollover starts a fresh Session whose own event span has no notice yet,
102
- * which is exactly the documented re-arm.
103
- */
104
- private noticeDelivered;
105
- dispose(): void;
106
- /** A successful assistant response ends any open overflow-recovery sequence. */
107
- onAssistantMessage(agent: Agent): void;
108
- /**
109
- * Pre-step policy for one Member agent: below the handoff budget nothing
110
- * happens; at the handoff budget one structured notice per generation is
111
- * steered into the running turn; at the hard limit the request is forced
112
- * through compaction first and fails closed when that cannot be proven.
113
- * Returns the decision for the step: `continue` forwards, `reject` blocks.
114
- */
115
- onPreStep(agent: Agent, signal: AbortSignal): Promise<{
116
- readonly kind: 'continue' | 'reject' | 'notice';
117
- }>;
118
- /**
119
- * Provider-overflow recovery: one bounded compact-and-retry sequence per
120
- * open failure chain. Returns whether the request may retry once.
121
- */
122
- onRequestError(agent: Agent, failure: {
123
- readonly code?: string;
124
- }, signal: AbortSignal): Promise<boolean>;
125
- /**
126
- * The one Team hard-limit translation: force a CompactionEngine reduction
127
- * in the current Agent/Session and prove it advanced the durable surface
128
- * (or measurably reduced pressure) before continuing. Background jobs are
129
- * untouched — compaction never cancels or discards them.
130
- * @returns whether the request may proceed.
131
- */
132
- private enforceHardLimit;
133
- }
134
- //# sourceMappingURL=pressure-policy.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pressure-policy.d.ts","sourceRoot":"","sources":["../../src/pressure-policy.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"HumanSettingsSection.d.ts","sourceRoot":"","sources":["../../../src/client/HumanSettingsSection.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAA;AAEjF,OAAO,EAAoB,KAAK,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAElF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAA;AAmBnE,MAAM,WAAW,4BAA4B;IAC3C,mFAAmF;IACnF,QAAQ,EAAE,qBAAqB,CAAA;IAC/B,sFAAsF;IACtF,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;IACvD,gGAAgG;IAChG,YAAY,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;IACzD,gEAAgE;IAChE,YAAY,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;IAC/C,+EAA+E;IAC/E,WAAW,EAAE,qBAAqB,CAAA;CACnC;AAED,MAAM,MAAM,yBAAyB,GACjC,YAAY,CAAC,kBAAkB,CAAC,GAChC,WAAW,CAAC,MAAM,CAAC,GACnB,4BAA4B,CAAA;AAsBhC,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,yBAAyB,+BAkKpE"}
@@ -1,118 +0,0 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useRef, useState } from 'react';
3
- import { Button, Input } from '@deepseek-ai/dsh-client-ui-primitives';
4
- import { useHumanIdentity } from "./human-identity.js";
5
- import { EnvironmentCheck } from "./EnvironmentCheck.js";
6
- import { useAvatarImage } from "./avatar-image.js";
7
- import css from './human-settings.module.css';
8
- /**
9
- * The Human's own settings page: display name, avatar, the local environment
10
- * check, and the version footnote.
11
- *
12
- * The page owns no durable fact and no copy of one. Name, avatar, and version
13
- * all arrive from the shared identity projection, so a save here moves the
14
- * message rows and member refs at the same moment; a failed write keeps the
15
- * typed name in the field and reports the Host's own reason. The environment
16
- * check is a separate projection, read only, and belongs to the installation
17
- * rather than to the Human.
18
- */
19
- /** Host-side avatar ceiling (`ATTACHMENT_MAX_BYTES`): the settings page refuses larger files before the round trip. */
20
- const AVATAR_MAX_BYTES = 10 * 1024 * 1024;
21
- /**
22
- * Run one durable write and reduce every failure to the message the page
23
- * reports. A rejected Remote call (a dropped carrier, a refused write) is a
24
- * failure like any other: without this the field would sit on "saving" forever
25
- * and report nothing.
26
- */
27
- async function failureOf(action) {
28
- try {
29
- return await action();
30
- }
31
- catch (error) {
32
- return error instanceof Error ? error.message : String(error);
33
- }
34
- }
35
- /** First visible character of a display name, or the neutral `H` before one is known. */
36
- function avatarInitial(name) {
37
- const trimmed = (name ?? '').replace(/^@/, '').trim();
38
- return trimmed === '' ? 'H' : trimmed.slice(0, 1).toUpperCase();
39
- }
40
- export function HumanSettingsSection(props) {
41
- const { t, identity } = props;
42
- const profile = useHumanIdentity(identity);
43
- // Undefined means "follow the Host value": the field re-syncs whenever the
44
- // profile changes underneath, without a background read clobbering a name
45
- // the reader is still editing.
46
- const [draft, setDraft] = useState(undefined);
47
- const [saving, setSaving] = useState(false);
48
- const [uploading, setUploading] = useState(false);
49
- const [notice, setNotice] = useState(null);
50
- const filePicker = useRef(null);
51
- const name = draft ?? profile.name ?? '';
52
- const dirty = draft !== undefined && draft.trim() !== (profile.name ?? '');
53
- const emptyName = draft !== undefined && draft.trim() === '';
54
- const hasAvatar = profile.avatarRef !== undefined;
55
- // The circle answers to decoded bytes, not to a stored reference: the Host
56
- // accepts any `image/…` payload, so a file this browser cannot read has to
57
- // fall back to the initial exactly as a removed one does.
58
- const avatar = useAvatarImage(profile.avatarUrl);
59
- const submitName = async () => {
60
- if (!dirty || emptyName || saving)
61
- return;
62
- setSaving(true);
63
- setNotice(null);
64
- const failure = await failureOf(() => props.saveName(name.trim()));
65
- setSaving(false);
66
- if (failure !== undefined) {
67
- setNotice(t('humanSettingsNameFailed', { message: failure }));
68
- return;
69
- }
70
- setDraft(undefined);
71
- };
72
- const pickAvatar = async (file) => {
73
- if (file === undefined)
74
- return;
75
- setNotice(null);
76
- if (!file.type.startsWith('image/')) {
77
- setNotice(t('humanSettingsAvatarNotImage'));
78
- return;
79
- }
80
- if (file.size > AVATAR_MAX_BYTES) {
81
- setNotice(t('humanSettingsAvatarTooLarge'));
82
- return;
83
- }
84
- setUploading(true);
85
- const failure = await failureOf(() => props.uploadAvatar(file));
86
- setUploading(false);
87
- if (failure !== undefined)
88
- setNotice(t('humanSettingsAvatarFailed', { message: failure }));
89
- };
90
- const removeAvatar = async () => {
91
- setNotice(null);
92
- const failure = await failureOf(() => props.removeAvatar());
93
- if (failure !== undefined)
94
- setNotice(t('humanSettingsAvatarFailed', { message: failure }));
95
- };
96
- // The page says what it is before it says what happened: the settings nav
97
- // lists it beside the Harness's own pages, so the title alone leaves "whose
98
- // profile is this, and where does it apply?" unanswered — and every state,
99
- // including a failed read, has to answer it.
100
- const pageHeader = _jsxs(_Fragment, { children: [_jsx("h2", { className: css.heading, children: t('humanSettingsTitle') }), _jsx("p", { className: css.intro, children: t('humanSettingsIntro') })] });
101
- if (profile.status === 'loading' && profile.name === undefined) {
102
- return _jsxs("div", { className: css.section, children: [pageHeader, _jsx("p", { className: css.state, role: "status", children: t('humanSettingsLoading') })] });
103
- }
104
- if (profile.name === undefined) {
105
- return _jsxs("div", { className: css.section, children: [pageHeader, _jsx("p", { className: css.state, role: "alert", children: t('humanSettingsUnavailable', { message: profile.error ?? '' }) }), _jsx("div", { className: css.stateAction, children: _jsx(Button, { variant: "outline", onClick: () => { void identity.refresh(); }, children: t('retry') }) })] });
106
- }
107
- return (_jsxs("div", { className: css.section, children: [pageHeader, _jsxs("div", { className: css.rows, children: [_jsxs("div", { className: css.row, children: [_jsxs("div", { className: css.rowText, children: [_jsx("div", { className: css.title, children: t('humanSettingsName') }), _jsx("div", { className: css.desc, children: t('humanSettingsNameHint') })] }), _jsxs("form", { className: css.controls, onSubmit: (event) => {
108
- event.preventDefault();
109
- void submitName();
110
- }, children: [_jsx(Input, { className: css.nameInput, "aria-label": t('humanSettingsName'), "aria-invalid": emptyName || undefined, value: name, disabled: saving, onChange: (event) => { setDraft(event.target.value); } }), _jsx(Button, { type: "submit", variant: "primary", disabled: saving || !dirty || emptyName, children: saving ? t('humanSettingsSaving') : t('humanSettingsSave') })] })] }), _jsxs("div", { className: css.row, children: [_jsxs("div", { className: css.rowText, children: [_jsx("div", { className: css.title, children: t('humanSettingsAvatar') }), _jsx("div", { className: css.desc, children: t('humanSettingsAvatarHint') })] }), _jsxs("div", { className: css.controls, children: [avatar.src === undefined
111
- ? _jsx("span", { className: `${css.identity} ${css.identityFallback}`, "data-avatar": "initial", "aria-hidden": "true", children: avatarInitial(profile.name) })
112
- : _jsx("img", { className: `${css.identity} ${css.identityImage}`, "data-avatar": "image", src: avatar.src, alt: "", onError: avatar.failed }), _jsx("input", { ref: filePicker, type: "file", accept: "image/*", tabIndex: -1, "aria-hidden": "true", hidden: true, onChange: (event) => {
113
- void pickAvatar(event.target.files?.[0]);
114
- event.target.value = '';
115
- } }), _jsx(Button, { variant: "outline", disabled: uploading, onClick: () => { filePicker.current?.click(); }, children: uploading ? t('humanSettingsUploading') : hasAvatar ? t('humanSettingsReplace') : t('humanSettingsUpload') }), hasAvatar && _jsx(Button, { disabled: uploading, onClick: () => { void removeAvatar(); }, children: t('humanSettingsRemoveAvatar') })] })] })] }), _jsx(EnvironmentCheck, { t: t, environment: props.environment }), _jsxs("div", { className: css.footnote, children: [_jsx("span", { children: t('humanSettingsVersion', { version: profile.version ?? '' }) }), _jsx("span", { "aria-hidden": "true", children: "\u00B7" }), _jsx("a", { className: css.link, href: profile.repoUrl ?? '', target: "_blank", rel: "noreferrer", children: "GitHub" }), profile.updateAvailable && profile.latestVersion !== undefined
116
- ? _jsx("a", { className: css.link, href: `${profile.repoUrl ?? ''}/releases`, target: "_blank", rel: "noreferrer", children: t('humanSettingsUpdateAvailable', { version: profile.latestVersion }) })
117
- : null] }), emptyName && _jsx("p", { className: css.notice, children: t('humanSettingsNameEmpty') }), notice === null ? null : _jsx("p", { className: css.notice, role: "alert", children: notice })] }));
118
- }