dsh-pause-session 0.1.0 → 0.2.0
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/CHANGELOG.md +38 -0
- package/DEVELOPMENT.md +25 -2
- package/README.md +41 -31
- package/README.zh.md +31 -21
- package/REHEARSAL.md +6 -6
- package/lib/client.js +1067 -1342
- package/lib/client.js.map +1 -1
- package/lib/index.js +1041 -1020
- package/lib/index.js.map +1 -1
- package/lib/typert.host.d.ts +3 -0
- package/lib/typert.host.js +339 -0
- package/lib/typert.remote-client.d.ts +38 -0
- package/lib/typert.remote-client.d.ts.map +1 -0
- package/lib/typert.remote-client.js +244 -0
- package/lib/types/client/control.d.ts +25 -158
- package/lib/types/client/global.d.ts +39 -239
- package/lib/types/client/index.d.ts +6 -5
- package/lib/types/client/locales.d.ts +2 -4
- package/lib/types/client/pill.d.ts +5 -5
- package/lib/types/client/remote.d.ts +71 -0
- package/lib/types/client/view.d.ts +19 -5
- package/lib/types/coldlog.d.ts +1 -1
- package/lib/types/control.d.ts +41 -60
- package/lib/types/global.d.ts +6 -4
- package/lib/types/index.d.ts +1 -1
- package/lib/types/park-state.d.ts +51 -0
- package/lib/types/registry.d.ts +1 -1
- package/lib/types/release-order.d.ts +21 -0
- package/lib/types/remote-adapter.d.ts +22 -0
- package/lib/types/remote.d.ts +158 -0
- package/lib/types/resume-activation.d.ts +27 -0
- package/lib/types/resume-text.d.ts +67 -0
- package/lib/types/resume.d.ts +5 -100
- package/lib/types/shared.d.ts +20 -123
- package/lib/types/snapshot.d.ts +29 -0
- package/lib/types/triage.d.ts +8 -9
- package/package.json +37 -18
- package/lib/types/client/burst.d.ts +0 -253
|
@@ -1,52 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Browser-side reading and driving of the host's park state for one session.
|
|
3
3
|
*
|
|
4
|
-
* The
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* definition's presence in that list IS the host's "this session is paused"
|
|
10
|
-
* fact, and the companion status definition answers with the park state as of
|
|
11
|
-
* the read; this module never derives either from its own press. That one
|
|
12
|
-
* answer carries the record's goal opt-out as well, so the switch beside the
|
|
13
|
-
* pause button can show it without a second host round-trip — and without it,
|
|
14
|
-
* the control renders no switch at all.
|
|
4
|
+
* The browser reads the native `pauseSession` stream; actions travel through
|
|
5
|
+
* the same Remote namespace. No slash command is involved. The stream is
|
|
6
|
+
* host-authoritative, so this module never derives a state from its own press.
|
|
7
|
+
* The snapshot also carries the record's goal opt-out, so the switch beside the
|
|
8
|
+
* pause button can show it without a second host round-trip.
|
|
15
9
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* produced it rather than a reason to keep asking (`./burst.ts`). One transition
|
|
20
|
-
* arrives as several registry changes — parking a session also registers its
|
|
21
|
-
* three commands — so the burst's own collection window is what turns a tick of
|
|
22
|
-
* changes into one read per shown session. A press or a goal switch reads as it
|
|
23
|
-
* runs, and the marker changes it causes are that action's own echo: those are
|
|
24
|
-
* absorbed for a short window (`./burst.ts`) rather than read back — except for
|
|
25
|
-
* the one look an action owes when that window closes, if the reading it left
|
|
26
|
-
* behind is still moving, because a transition announced inside the window would
|
|
27
|
-
* otherwise never be read at all.
|
|
28
|
-
*
|
|
29
|
-
* The whole-app control reads the same park and publishes what it found
|
|
30
|
-
* (`./global.ts`), and a header consults that answer before spending a read of
|
|
31
|
-
* its own: with nothing registered, no session can be paused, so a header that
|
|
32
|
-
* already says "running" is left saying it rather than paying a round-trip to
|
|
33
|
-
* hear it again. A header the host last showed on its way to a park is never
|
|
34
|
-
* answered that way — that reading is the newer fact — and the derivation is
|
|
35
|
-
* voided by the next whole-app answer that names a registered session, which
|
|
36
|
-
* the forwarded change a park causes is what brings in.
|
|
10
|
+
* The stream is the change feed. A pushed snapshot triggers one cached read per
|
|
11
|
+
* shown header; a press or goal switch reads the host's answer once after the
|
|
12
|
+
* action.
|
|
37
13
|
* @module dsh-pause-session/client/control
|
|
38
14
|
*/
|
|
39
|
-
import type { ClientRemote } from '@deepseek-ai/dsh-api-remotes/client';
|
|
40
15
|
import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
|
|
41
16
|
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
42
|
-
import type {
|
|
43
|
-
import type { GlobalReading } from './global.js';
|
|
44
|
-
/**
|
|
45
|
-
* The whole-app answer as the session headers read it, or `undefined` before
|
|
46
|
-
* that control has heard from the host. Reading it costs nothing: it is the
|
|
47
|
-
* published snapshot, not a host round-trip.
|
|
48
|
-
*/
|
|
49
|
-
export type AggregateSource = () => GlobalReading | undefined;
|
|
17
|
+
import type { PauseTransport } from './remote.js';
|
|
50
18
|
/**
|
|
51
19
|
* What the Session-header control knows about one session: what the host
|
|
52
20
|
* reported, or that no answer has arrived (`undefined`) or the last read
|
|
@@ -77,68 +45,36 @@ export interface PauseState {
|
|
|
77
45
|
}
|
|
78
46
|
/** Owns the published reading per session; nothing else writes that state. */
|
|
79
47
|
export declare class PauseControl {
|
|
80
|
-
private readonly
|
|
48
|
+
private readonly transport;
|
|
81
49
|
private readonly lifetime;
|
|
82
|
-
private readonly aggregate;
|
|
83
50
|
/** State source the Session-header contribution binds its selector hook to. */
|
|
84
51
|
readonly store: SnapshotStore<PauseState>;
|
|
85
|
-
/** Sessions this control has shown; a
|
|
52
|
+
/** Sessions this control has shown; a pushed snapshot applies to every one. */
|
|
86
53
|
private readonly shown;
|
|
87
54
|
/** Highest read sequence requested per session: an answer older than it is dropped. */
|
|
88
55
|
private readonly latest;
|
|
89
|
-
/**
|
|
90
|
-
* Sessions a change has put back on the list of ones to read once — a
|
|
91
|
-
* transition this browser has been told about and has not answered yet.
|
|
92
|
-
*/
|
|
93
|
-
private readonly owed;
|
|
94
|
-
/**
|
|
95
|
-
* Whether the look owed at the close of an echo window is still to be taken.
|
|
96
|
-
* It reads every shown session, exactly as a change does: the look exists
|
|
97
|
-
* because a change may have been swallowed, and a swallowed change carries no
|
|
98
|
-
* payload either.
|
|
99
|
-
*/
|
|
100
|
-
private trailing;
|
|
101
|
-
/**
|
|
102
|
-
* Sessions whose header was answered from the whole-app "nothing is
|
|
103
|
-
* registered" instead of a read of their own, and which therefore have to be
|
|
104
|
-
* read for real if that answer stops holding.
|
|
105
|
-
*/
|
|
106
|
-
private readonly derived;
|
|
107
|
-
/** The bounded burst of reads one transition buys; see `./burst.ts`. */
|
|
108
|
-
private readonly burst;
|
|
109
56
|
private reads;
|
|
110
57
|
/**
|
|
111
|
-
* @param
|
|
112
|
-
* @param lifetime - aborts in-flight
|
|
113
|
-
* @param windowMs - how long the burst collects the registrations of one
|
|
114
|
-
* transition before its first read; also the wait after a press.
|
|
115
|
-
* @param policy - the burst waits and visibility source; defaults to the real page.
|
|
116
|
-
* @param aggregate - the whole-app control's published answer; absent means it is never consulted.
|
|
58
|
+
* @param transport - the native namespace source and actions.
|
|
59
|
+
* @param lifetime - aborts in-flight reads when the plugin unloads.
|
|
117
60
|
*/
|
|
118
|
-
constructor(
|
|
61
|
+
constructor(transport: PauseTransport, lifetime: AbortSignal);
|
|
119
62
|
/**
|
|
120
63
|
* Read the host's state for one session.
|
|
121
64
|
* @param sessionId - session whose control was rendered.
|
|
122
65
|
* @returns after this read's answer is published or superseded by a newer one.
|
|
123
66
|
*/
|
|
124
67
|
refresh(sessionId: SessionId): Promise<void>;
|
|
125
|
-
/**
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
68
|
+
/** Apply one pushed snapshot without spending a read per shown header. */
|
|
69
|
+
apply(snapshot: {
|
|
70
|
+
readonly sessions: Readonly<Record<string, {
|
|
71
|
+
readonly phase: PausePhase;
|
|
72
|
+
readonly runningTools: readonly string[];
|
|
73
|
+
readonly rearmGoal?: boolean;
|
|
74
|
+
}>>;
|
|
75
|
+
} | undefined): void;
|
|
76
|
+
/** A new pushed snapshot may have moved every header; read them once. */
|
|
134
77
|
refreshAll(): void;
|
|
135
|
-
/**
|
|
136
|
-
* One pass of the burst: every shown session a change still owes a read. The
|
|
137
|
-
* forwarded event carries no payload, so a change may have touched any of
|
|
138
|
-
* them and each is read once. A session the whole-app answer has already
|
|
139
|
-
* spoken for is answered from it instead of being asked about; see
|
|
140
|
-
* {@link answerIsKnown}.
|
|
141
|
-
*/
|
|
142
78
|
private readAll;
|
|
143
79
|
/** One session's read, published unless a newer read of that session supersedes it. */
|
|
144
80
|
private readOne;
|
|
@@ -152,81 +88,12 @@ export declare class PauseControl {
|
|
|
152
88
|
toggle(sessionId: SessionId): Promise<void>;
|
|
153
89
|
/**
|
|
154
90
|
* Flip this session's goal opt-out. The verb belongs to the session it
|
|
155
|
-
* changes
|
|
156
|
-
* this press needs no listed row. What the switch shows afterwards is the
|
|
157
|
-
* host's next answer, never a local flip: a refused switch leaves the record
|
|
158
|
-
* exactly as it was, and the re-read is what says so.
|
|
91
|
+
* changes; the switch shows the host's next answer, never a local flip.
|
|
159
92
|
* @param sessionId - session whose switch was pressed.
|
|
160
93
|
* @returns after the control re-reads the host.
|
|
161
94
|
*/
|
|
162
95
|
toggleGoal(sessionId: SessionId): Promise<void>;
|
|
163
|
-
/** Ask the
|
|
96
|
+
/** Ask the native stream what this session's park state is. */
|
|
164
97
|
private read;
|
|
165
98
|
private publish;
|
|
166
|
-
/**
|
|
167
|
-
* Whether the park has already answered for this header: with nothing
|
|
168
|
-
* registered, no session can be paused, so a header that says this session is
|
|
169
|
-
* running carries the whole fact and the read that would confirm it is a host
|
|
170
|
-
* round-trip plus two records in that session's log for nothing.
|
|
171
|
-
*
|
|
172
|
-
* A header the host last showed on its way to a park is never answered this
|
|
173
|
-
* way: that reading is newer than the aggregate the derivation rests on, and
|
|
174
|
-
* only a fresh host answer may replace it.
|
|
175
|
-
*/
|
|
176
|
-
private answerIsKnown;
|
|
177
|
-
/**
|
|
178
|
-
* Whether the whole-app answer says the park holds nothing at all: the one
|
|
179
|
-
* predicate the derivation below and its revocation share.
|
|
180
|
-
*/
|
|
181
|
-
private nothingParked;
|
|
182
|
-
/**
|
|
183
|
-
* Answer one header from the whole-app verdict, and remember that it was that
|
|
184
|
-
* kind of answer: the sessions to read for real are exactly the ones the
|
|
185
|
-
* aggregate may have been wrong about.
|
|
186
|
-
*/
|
|
187
|
-
private deriveActive;
|
|
188
|
-
/**
|
|
189
|
-
* The whole-app answer moved. Whatever was answered from "nothing is
|
|
190
|
-
* registered" is read for real the moment that stops holding — the session a
|
|
191
|
-
* header stood in for may be the one the park just took, possibly parked from
|
|
192
|
-
* another window whose change this browser only sees as the forwarded event.
|
|
193
|
-
* Called on every published aggregate, so it must do nothing while the
|
|
194
|
-
* derivation still holds.
|
|
195
|
-
*/
|
|
196
|
-
reconsider(): void;
|
|
197
|
-
/**
|
|
198
|
-
* Decide what the burst owes after a read: another look while a change this
|
|
199
|
-
* browser has not answered is still outstanding, and nothing once none is.
|
|
200
|
-
*
|
|
201
|
-
* A phase that is still moving is left alone. The host announces every
|
|
202
|
-
* transition on its command channel — the flush that settles a park included,
|
|
203
|
-
* which changes no registration of its own — so a read that finds `draining`
|
|
204
|
-
* or `parking` is the answer to the transition that produced it, and watching
|
|
205
|
-
* that phase from here would spend reads on a move that is going to speak for
|
|
206
|
-
* itself. What the burst still owes is the delivery of an announcement: a read
|
|
207
|
-
* still armed when the change arrived, and a read for a change that landed
|
|
208
|
-
* while the last pass was in flight.
|
|
209
|
-
*
|
|
210
|
-
* The one transition that cannot speak for itself is the one this browser's
|
|
211
|
-
* own echo window swallowed: a press reads the host, the park moves while the
|
|
212
|
-
* window is still open, and the changes that would have announced it look
|
|
213
|
-
* exactly like the press's own registrations. So an action that left a phase
|
|
214
|
-
* still moving asks for one look when that window closes, and only then — the
|
|
215
|
-
* read is owed at a moment, not watched. Once nothing is owed, the last
|
|
216
|
-
* reading stays on screen; the next change, the next user action, or the shell
|
|
217
|
-
* handing this control a session again is what asks next.
|
|
218
|
-
*/
|
|
219
|
-
private follow;
|
|
220
|
-
/**
|
|
221
|
-
* Whether any shown session's last reading is a phase the host has not
|
|
222
|
-
* finished walking — the only states an action's own echo could be hiding a
|
|
223
|
-
* transition behind.
|
|
224
|
-
*/
|
|
225
|
-
private moving;
|
|
226
|
-
/**
|
|
227
|
-
* Follow the page in and out of view. A hidden page is not being read — and
|
|
228
|
-
* the read the burst was about to take is not lost, it waits for the page to
|
|
229
|
-
* come back.
|
|
230
|
-
*/
|
|
231
|
-
watchVisibility(): void;
|
|
232
99
|
}
|
|
@@ -1,57 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Browser-side reading and driving of the host's whole-app park state.
|
|
3
3
|
*
|
|
4
|
-
* The
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* asks: `pause-state-all` is registered globally and its RESULT carries the
|
|
9
|
-
* whole-app status as of the read.
|
|
10
|
-
*
|
|
11
|
-
* The command channel is session-addressed, so the control needs one session
|
|
12
|
-
* to talk through. It picks a user session the host can serve (never a
|
|
13
|
-
* subagent's own session), preferring the one on screen; with no session at
|
|
14
|
-
* all there is nothing to ask, and the control claims nothing rather than
|
|
15
|
-
* inventing an answer. Once the host's own answer names the session the park
|
|
16
|
-
* belongs to, reads are addressed there instead: a read writes two records into
|
|
17
|
-
* the address session's transcript, and they belong in the session being parked
|
|
18
|
-
* rather than in whatever the user happens to be looking at. That name outlives
|
|
19
|
-
* the phases — a session that drained and parked cleanly names nothing else — so
|
|
20
|
-
* a clean park is addressed like a moving one. Failing that, the session the
|
|
21
|
-
* last answer reported as registered is remembered, then the one a read was last
|
|
22
|
-
* served through — an address change is the user looking somewhere else, not
|
|
23
|
-
* news about the park, and a park that has emptied out is no reason to start
|
|
24
|
-
* writing rows into every session the user opens next. An address that stops
|
|
25
|
-
* answering (its agent is gone) is forgotten and the read falls back to the next
|
|
26
|
-
* one, the session the shell asks with last, so a stale address costs an honest
|
|
27
|
-
* answer rather than a control that can never speak again.
|
|
28
|
-
*
|
|
29
|
-
* Every phase a session reaches announces itself through the registry — a
|
|
30
|
-
* transition re-registers that session's status verb — so a change is what buys
|
|
31
|
-
* the next read, and the flush that settles a park is announced like every other
|
|
32
|
-
* step (`./burst.ts`). A read that finds work still in flight is therefore the
|
|
33
|
-
* answer to the transition that produced it rather than a reason to keep asking;
|
|
34
|
-
* what the burst still owes is the delivery of a change, and the rows of a panel
|
|
35
|
-
* whose own read did not answer. A settled answer is left on screen unread: the
|
|
36
|
-
* panel stays readable and the pill keeps saying what it says, but the browser
|
|
37
|
-
* stops spending host round-trips and log records on a state that has stopped
|
|
38
|
-
* moving. What owes a read is the host's forwarded registry change, the user's
|
|
39
|
-
* own press or decision, and the first read at mount; once an answer is on
|
|
40
|
-
* screen, the shell handing this control another session to ask through is none
|
|
41
|
-
* of those. A press, a decision and an opened panel each read the host as they
|
|
42
|
-
* run, and the changes they set off are that action's own echo: those are
|
|
43
|
-
* absorbed for a short window (`./burst.ts`), so a forwarded change owes a read
|
|
44
|
-
* exactly when something moved that this browser did not do — with one look owed
|
|
45
|
-
* at the close of that window when the reading the action left is still moving,
|
|
46
|
-
* which is how a park that reaches its final phase inside the echo window is
|
|
47
|
-
* still read.
|
|
4
|
+
* The aggregate arrives from the native `pauseSession` stream. The stream is
|
|
5
|
+
* process-wide and writes nothing into any Session; actions travel through the
|
|
6
|
+
* same Remote namespace. A pushed snapshot is applied directly; a settled park
|
|
7
|
+
* costs nothing while its last answer stays on screen.
|
|
48
8
|
* @module dsh-pause-session/client/global
|
|
49
9
|
*/
|
|
50
|
-
import type { ClientRemote } from '@deepseek-ai/dsh-api-remotes/client';
|
|
51
10
|
import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
|
|
52
11
|
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
53
12
|
import type { GlobalStatus, TriageAction, TriageRow } from '../shared.js';
|
|
54
|
-
import type {
|
|
13
|
+
import type { PauseTransport } from './remote.js';
|
|
55
14
|
/** What the whole-app control knows: the host's answer, or that it could not ask. */
|
|
56
15
|
export type GlobalReading = {
|
|
57
16
|
readonly kind: 'reported';
|
|
@@ -74,11 +33,15 @@ export interface GlobalPauseState {
|
|
|
74
33
|
panelOpen: boolean;
|
|
75
34
|
/** The host's decision list; absent until the panel asks for it. */
|
|
76
35
|
triage: TriageReading | undefined;
|
|
36
|
+
/** The last action or read refusal, shown verbatim in the panel. */
|
|
37
|
+
error?: string;
|
|
38
|
+
/** The last snapshot's per-session details, for the draining progress copy. */
|
|
39
|
+
sessions?: Readonly<Record<string, {
|
|
40
|
+
readonly runningTools: readonly string[];
|
|
41
|
+
}>>;
|
|
77
42
|
}
|
|
78
|
-
/** The command one listed verb runs, named from the one vocabulary the host registers. */
|
|
79
|
-
export declare const TRIAGE_DECISION_COMMAND: Readonly<Record<TriageAction, string>>;
|
|
80
43
|
/**
|
|
81
|
-
* The session a whole-app
|
|
44
|
+
* The session a whole-app action is addressed to.
|
|
82
45
|
*
|
|
83
46
|
* A subagent's own session is never addressed: its agent belongs to a parent
|
|
84
47
|
* and is not the host's business to drive from the shell. Among the rest, the
|
|
@@ -98,169 +61,48 @@ export declare function addressingSession(state: {
|
|
|
98
61
|
};
|
|
99
62
|
} | undefined>>;
|
|
100
63
|
}): SessionId | undefined;
|
|
101
|
-
/**
|
|
102
|
-
* The session a registered park owns, when the host's answer names one that is
|
|
103
|
-
* still moving. This is how a read stops landing in whatever session the user
|
|
104
|
-
* happens to be looking at.
|
|
105
|
-
* @param status - the host's last whole-app answer.
|
|
106
|
-
* @returns a draining session, or `undefined` when the answer names none.
|
|
107
|
-
*/
|
|
108
|
-
export declare function registeredAddress(status: GlobalStatus): SessionId | undefined;
|
|
109
|
-
/**
|
|
110
|
-
* The session the host names as the park's own, whatever phase the park
|
|
111
|
-
* reached — the address a whole-app read belongs at.
|
|
112
|
-
*
|
|
113
|
-
* This is the fact {@link registeredAddress} cannot carry once a park is clean:
|
|
114
|
-
* a session that reached `safe` has nothing left to do, so no bucket names it,
|
|
115
|
-
* and a reader in another window would fall back to whatever session it is
|
|
116
|
-
* showing. An answer written before this field existed names no session here:
|
|
117
|
-
* an absent address, never one to guess at.
|
|
118
|
-
* @param status - the host's last whole-app answer.
|
|
119
|
-
* @returns the session the park belongs to, or `undefined` when the answer names none.
|
|
120
|
-
*/
|
|
121
|
-
export declare function parkedAddress(status: GlobalStatus): SessionId | undefined;
|
|
122
64
|
/** Owns the published whole-app reading; nothing else writes that state. */
|
|
123
65
|
export declare class PauseGlobalControl {
|
|
124
|
-
private readonly
|
|
66
|
+
private readonly transport;
|
|
125
67
|
private readonly lifetime;
|
|
126
68
|
/** State source the whole-app contribution binds its selector hook to. */
|
|
127
69
|
readonly store: SnapshotStore<GlobalPauseState>;
|
|
128
|
-
/** The session the shell asked this control through; reads
|
|
70
|
+
/** The session the shell asked this control through; list reads use it. */
|
|
129
71
|
private address;
|
|
130
|
-
/**
|
|
131
|
-
* The last session an answer reported as registered — the address a read
|
|
132
|
-
* falls back to when the host's own answer names no parked session, which is
|
|
133
|
-
* every reading written before that field existed.
|
|
134
|
-
*
|
|
135
|
-
* The buckets that feed it name only what is still moving, so they say
|
|
136
|
-
* nothing about a park that finished cleanly; the park's own name is the live
|
|
137
|
-
* fact, and this memory is what keeps the rows in the park's transcript for an
|
|
138
|
-
* answer that predates it. An empty registry does not clear it: a park whose
|
|
139
|
-
* sessions stopped moving has not moved out of its sessions.
|
|
140
|
-
*/
|
|
141
|
-
private lastRegistered;
|
|
142
|
-
/**
|
|
143
|
-
* The session an aggregate read was last served through. Later reads keep
|
|
144
|
-
* going there: every read is two records in the address session's log, and
|
|
145
|
-
* the shell's address follows whatever the user is looking at, which is not
|
|
146
|
-
* where a row about the park belongs.
|
|
147
|
-
*/
|
|
148
|
-
private served;
|
|
149
72
|
/** Highest decision-list read requested: an answer older than it is dropped. */
|
|
150
73
|
private latestTriage;
|
|
151
|
-
/** Highest read sequence requested: an answer older than it is dropped. */
|
|
152
|
-
private latest;
|
|
153
74
|
/**
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
* browser's own action is already answered by that action's read.
|
|
75
|
+
* @param transport - the native namespace source and actions.
|
|
76
|
+
* @param lifetime - aborts in-flight reads when the plugin unloads.
|
|
157
77
|
*/
|
|
158
|
-
|
|
159
|
-
/** The bounded burst of reads one transition buys; see `./burst.ts`. */
|
|
160
|
-
private readonly burst;
|
|
78
|
+
constructor(transport: PauseTransport, lifetime: AbortSignal);
|
|
161
79
|
/**
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
* @param windowMs - how long the burst collects the registrations of one
|
|
165
|
-
* transition before its first read; also the wait after a press.
|
|
166
|
-
* @param policy - the burst waits and visibility source; defaults to the real page.
|
|
167
|
-
*/
|
|
168
|
-
constructor(commands: ClientRemote['commands'], lifetime: AbortSignal, windowMs?: number, policy?: Omit<BurstPolicy, 'windowMs' | 'waitsMs'>);
|
|
169
|
-
/**
|
|
170
|
-
* The shell handed this control a session: the one the pill mounted on, or
|
|
171
|
-
* the one the user has just moved to. Only a control with no answer yet reads
|
|
172
|
-
* here — the view moving is not the park moving, and after the first answer
|
|
173
|
-
* the forwarded registry change and the user's own press are what ask again.
|
|
174
|
-
* A read that came back with nothing is not an answer, so moving to another
|
|
175
|
-
* session is one more chance to reach the host rather than a control that
|
|
176
|
-
* stays mute until something else happens to change. The address is kept
|
|
177
|
-
* either way: it is where this control's presses and its decision list go, and
|
|
178
|
-
* the fallback a remembered address falls back to.
|
|
80
|
+
* The shell handed this control a session. The first call reads the aggregate;
|
|
81
|
+
* later calls only move where list reads and actions are addressed.
|
|
179
82
|
* @param sessionId - the session the shell asks through.
|
|
180
|
-
* @returns after this read's answer is published or superseded by a newer one.
|
|
181
83
|
*/
|
|
182
84
|
refresh(sessionId: SessionId): Promise<void>;
|
|
183
|
-
/**
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
* the action read the host as it ran.
|
|
192
|
-
*/
|
|
85
|
+
/** Apply one pushed snapshot directly. */
|
|
86
|
+
apply(snapshot: {
|
|
87
|
+
readonly global: GlobalStatus;
|
|
88
|
+
readonly sessions: Readonly<Record<string, {
|
|
89
|
+
readonly runningTools: readonly string[];
|
|
90
|
+
}>>;
|
|
91
|
+
} | undefined): void;
|
|
92
|
+
/** A pushed snapshot may have moved the aggregate and the open list. */
|
|
193
93
|
refreshAll(): void;
|
|
194
94
|
/**
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
* is reading.
|
|
198
|
-
*/
|
|
199
|
-
private readAll;
|
|
200
|
-
/**
|
|
201
|
-
* The session a read goes through: the one the park is still draining, else
|
|
202
|
-
* the one the host names as the park's own, else the one a read was last
|
|
203
|
-
* served through, else the session the shell is on now. The park's own address
|
|
204
|
-
* comes first because a read's rows land in the transcript it was taken
|
|
205
|
-
* through, and the park — not the reader — is what they are about; its name
|
|
206
|
-
* survives the clean case, where every bucket above is empty and a park that
|
|
207
|
-
* finished would otherwise have no address at all.
|
|
208
|
-
* @param skip - an address this read already tried and could not reach. The
|
|
209
|
-
* fallback is the next candidate rather than the same one again.
|
|
210
|
-
*/
|
|
211
|
-
private target;
|
|
212
|
-
/**
|
|
213
|
-
* Ask the host for the aggregate through the session a read goes through,
|
|
214
|
-
* with the one fallback an address that stopped answering is worth: the
|
|
215
|
-
* remembered address is forgotten, and the read is taken again through the
|
|
216
|
-
* next one — the session the shell is on at the latest. A memory of a session
|
|
217
|
-
* this host no longer holds would otherwise leave the control unable to say
|
|
218
|
-
* anything at all, and a single retry is the whole price of keeping it honest.
|
|
219
|
-
*/
|
|
220
|
-
private readAggregate;
|
|
221
|
-
/**
|
|
222
|
-
* Publish one aggregate answer, unless a newer read was requested while this
|
|
223
|
-
* one was in flight: that answer would show a state the host has moved past.
|
|
224
|
-
* A served address is remembered, and one that did not answer is forgotten —
|
|
225
|
-
* that is what makes the read fall back to the next address rather than ask
|
|
226
|
-
* it again.
|
|
227
|
-
* @param sessionId - the session this read goes through.
|
|
228
|
-
* @returns whether this read came back without an answer; a superseded read is
|
|
229
|
-
* not one, because the newer read already owns the outcome.
|
|
230
|
-
*/
|
|
231
|
-
private readAt;
|
|
232
|
-
/**
|
|
233
|
-
* Open or close the decision list. Opening asks the host for the rows; there
|
|
234
|
-
* is no state to show without that answer. Opening is also a client action
|
|
235
|
-
* that reads, so the changes it sets off are absorbed rather than read back,
|
|
236
|
-
* and whether the burst owes anything is what its own read decides.
|
|
95
|
+
* Open or close the decision list. Opening asks for the rows; there is no
|
|
96
|
+
* state to show without that answer.
|
|
237
97
|
* @param open - whether the panel should be showing.
|
|
238
98
|
*/
|
|
239
99
|
setPanel(open: boolean): void;
|
|
240
|
-
/**
|
|
241
|
-
* Ask the host for the decision list through the session the user is on. The
|
|
242
|
-
* list is recorded per calling session and the decisions act only on rows
|
|
243
|
-
* that session was shown, so this read — unlike the aggregate — stays on the
|
|
244
|
-
* shell's own address.
|
|
245
|
-
*/
|
|
100
|
+
/** Ask the host for the decision list for the session the user is on. */
|
|
246
101
|
refreshTriage(): Promise<void>;
|
|
247
|
-
/**
|
|
248
|
-
* Read the aggregate again because the user asked this control to act: the
|
|
249
|
-
* address is the session the shell is on, since a press is a user action on
|
|
250
|
-
* the session the user is looking at, and the host's answer is what the
|
|
251
|
-
* control shows next.
|
|
252
|
-
* @param sessionId - the session the shell is on.
|
|
253
|
-
*/
|
|
254
|
-
private reread;
|
|
255
|
-
/** One decision-list read, addressed at the session the user is on. */
|
|
256
|
-
private readTriage;
|
|
257
102
|
/**
|
|
258
103
|
* Take one listed verb on one listed session, addressed through the session
|
|
259
|
-
* the user is on.
|
|
260
|
-
*
|
|
261
|
-
* host's answer — not this control's assumption — is what the next render
|
|
262
|
-
* shows: a decision can release a session, and the goal switch changes what
|
|
263
|
-
* the row itself says.
|
|
104
|
+
* the user is on. A refusal is published verbatim rather than silently
|
|
105
|
+
* leaving the previous rows in place.
|
|
264
106
|
* @param sessionId - the listed session to act on.
|
|
265
107
|
* @param action - which listed verb was taken.
|
|
266
108
|
*/
|
|
@@ -268,58 +110,16 @@ export declare class PauseGlobalControl {
|
|
|
268
110
|
/**
|
|
269
111
|
* Press the pill: park everything, or release everything the park owns.
|
|
270
112
|
* Which one it is comes from the host's own last answer, never from a local
|
|
271
|
-
* flip; the state shown afterwards is the host's answer again.
|
|
272
|
-
* view does not turn into a verb — every registered session is one the host
|
|
273
|
-
* will not wake — is not pressed at all.
|
|
113
|
+
* flip; the state shown afterwards is the host's answer again.
|
|
274
114
|
* @param sessionId - the session to address the verb to.
|
|
275
|
-
* @returns after the control re-reads the host.
|
|
276
115
|
*/
|
|
277
116
|
toggle(sessionId: SessionId): Promise<void>;
|
|
278
|
-
/**
|
|
117
|
+
/** Read the aggregate once and publish it. */
|
|
118
|
+
private readAggregate;
|
|
119
|
+
private reread;
|
|
120
|
+
/** One decision-list read, addressed at the session the user is on. */
|
|
121
|
+
private readTriage;
|
|
122
|
+
/** Ask the native namespace for the decision list. */
|
|
279
123
|
private readTriageRows;
|
|
280
|
-
/** Ask the host what the whole-app park state is, in the browser's vocabulary. */
|
|
281
|
-
private read;
|
|
282
124
|
private publish;
|
|
283
|
-
/**
|
|
284
|
-
* Decide what the burst owes after a read: another look while a change this
|
|
285
|
-
* browser has not answered is outstanding, or while the open panel is still
|
|
286
|
-
* owed rows, and nothing once neither holds.
|
|
287
|
-
*
|
|
288
|
-
* A registered session standing at the park point is left alone: the flush
|
|
289
|
-
* that settles it announces itself on the command channel like every other
|
|
290
|
-
* transition, so watching it from here would spend reads on a move that is
|
|
291
|
-
* going to speak for itself. A verdict that stays `waiting` because a record
|
|
292
|
-
* is stalled, unresumable or unread is not settling either: nothing in this
|
|
293
|
-
* process will change it, and a session that starts moving again registers its
|
|
294
|
-
* markers, which is what asks next.
|
|
295
|
-
*
|
|
296
|
-
* The one transition that cannot speak for itself is the one this browser's
|
|
297
|
-
* own echo window swallowed: a press reads the host, the park reaches its
|
|
298
|
-
* final phase while the window is still open, and the changes that would have
|
|
299
|
-
* announced it look exactly like the press's own registrations. An action that
|
|
300
|
-
* left the park moving therefore asks for one look when that window closes,
|
|
301
|
-
* and only then. Once nothing is owed, the last reading stays published — the
|
|
302
|
-
* verdict, the pill and the rows are exactly what the host last reported.
|
|
303
|
-
*/
|
|
304
|
-
private follow;
|
|
305
|
-
/**
|
|
306
|
-
* Whether the park this control last read still has work on its way — the only
|
|
307
|
-
* state an action's own echo could be hiding a transition behind. A record
|
|
308
|
-
* that is stalled, unresumable or unread is not moving: nothing in this
|
|
309
|
-
* process will finish it.
|
|
310
|
-
*/
|
|
311
|
-
private moving;
|
|
312
|
-
/**
|
|
313
|
-
* Whether the open panel is still owed its rows. Opening the panel reads them,
|
|
314
|
-
* so this holds only after a read that did not answer — the one debt no change
|
|
315
|
-
* created, and the one place a retry is the difference between an empty panel
|
|
316
|
-
* and the facts the host has. It is bounded by the burst like everything else.
|
|
317
|
-
*/
|
|
318
|
-
private unansweredPanel;
|
|
319
|
-
/**
|
|
320
|
-
* Follow the page in and out of view. A hidden page is not being read — and
|
|
321
|
-
* the read the burst was about to take is not lost, it waits for the page to
|
|
322
|
-
* come back.
|
|
323
|
-
*/
|
|
324
|
-
watchVisibility(): void;
|
|
325
125
|
}
|
|
@@ -14,11 +14,12 @@
|
|
|
14
14
|
* frame-wide overlay layer: it is read while looking at one conversation, and
|
|
15
15
|
* a sidebar or drawer that covers that area covers the control with it.
|
|
16
16
|
*
|
|
17
|
-
* Both controls are host-authoritative
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
17
|
+
* Both controls are host-authoritative. On a browser Host they read the
|
|
18
|
+
* native `pauseSession` stream, which keeps status reads out of the Session
|
|
19
|
+
* log. The same path serves Web and Desktop.
|
|
20
|
+
* User actions and status both use the generated native Remote namespace;
|
|
21
|
+
* no slash command is involved. Each control stays inert wherever no
|
|
22
|
+
* round-trip is available rather than rendering a state it cannot support. The
|
|
22
23
|
* header control also reads the whole-app answer the whole-app control
|
|
23
24
|
* publishes, so a park that holds nothing does not cost a host round-trip per
|
|
24
25
|
* header.
|
|
@@ -2,14 +2,11 @@
|
|
|
2
2
|
/** Simplified Chinese dictionary (the key-set source of truth). */
|
|
3
3
|
export declare const zh: {
|
|
4
4
|
'pause.aria': string;
|
|
5
|
-
'pause.tip': string;
|
|
6
|
-
'resume.aria': string;
|
|
7
5
|
'resume.tip': string;
|
|
8
6
|
'draining.aria': string;
|
|
9
7
|
'parking.aria': string;
|
|
10
8
|
'safe.aria': string;
|
|
11
9
|
'flushFailed.aria': string;
|
|
12
|
-
'state.paused': string;
|
|
13
10
|
'state.draining': string;
|
|
14
11
|
'state.parking': string;
|
|
15
12
|
'state.safe': string;
|
|
@@ -25,6 +22,8 @@ export declare const zh: {
|
|
|
25
22
|
'all.resume.aria': string;
|
|
26
23
|
'all.idle': string;
|
|
27
24
|
'all.finishing': string;
|
|
25
|
+
'all.cancel': string;
|
|
26
|
+
'all.cancel.aria': string;
|
|
28
27
|
'all.unclean': string;
|
|
29
28
|
'all.unclean.aria': string;
|
|
30
29
|
'all.safe': string;
|
|
@@ -54,7 +53,6 @@ export declare const zh: {
|
|
|
54
53
|
'triage.continue.aria': string;
|
|
55
54
|
'triage.note': string;
|
|
56
55
|
'triage.note.aria': string;
|
|
57
|
-
'triage.note.hint': string;
|
|
58
56
|
'triage.review': string;
|
|
59
57
|
'triage.review.aria': string;
|
|
60
58
|
'triage.leave': string;
|
|
@@ -10,11 +10,11 @@
|
|
|
10
10
|
* above the whole frame. The decision list hangs from the control into the
|
|
11
11
|
* conversation area below.
|
|
12
12
|
*
|
|
13
|
-
* The pill reads the
|
|
14
|
-
*
|
|
15
|
-
* than a state it would have to invent. The decision list is
|
|
16
|
-
* part of that first read
|
|
17
|
-
*
|
|
13
|
+
* The pill reads the native status stream through `./global.ts`. With no
|
|
14
|
+
* answer, or with no session to address an action through, it renders nothing
|
|
15
|
+
* rather than a state it would have to invent. The decision list is
|
|
16
|
+
* deliberately NOT part of that first read; the panel asks for its own rows
|
|
17
|
+
* when it opens.
|
|
18
18
|
* @module dsh-pause-session/client/pill
|
|
19
19
|
*/
|
|
20
20
|
import type { ReactNode } from 'react';
|