@khorsheed/dsh-room 0.2.2 → 0.2.4
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 +58 -0
- package/README.en.md +29 -62
- package/README.i18n.yaml +2 -2
- package/README.md +28 -61
- package/lib/client.js +14620 -5705
- package/lib/index.js +4069 -730
- package/lib/journal-B4FOGO6S.js +482 -0
- package/lib/journal-Rid9AAnD.js +485 -0
- package/lib/tool.js +112 -166
- package/lib/typert.host.js +2031 -374
- package/lib/typert.remote-client.d.ts +34 -10
- package/lib/typert.remote-client.js +1599 -210
- package/lib/types/agent-setup.d.ts +1 -1
- package/lib/types/client/InviteAgentAction.js +4 -16
- package/lib/types/client/InviteDialog.d.ts +28 -6
- package/lib/types/client/InviteDialog.js +76 -12
- package/lib/types/client/MemberCard.d.ts +5 -1
- package/lib/types/client/MemberCard.js +4 -4
- package/lib/types/client/MembersView.d.ts +1 -1
- package/lib/types/client/MembersView.js +58 -22
- package/lib/types/client/RemoveMemberConfirm.d.ts +40 -0
- package/lib/types/client/RemoveMemberConfirm.js +85 -0
- package/lib/types/client/RoomApprovalView.d.ts +11 -0
- package/lib/types/client/RoomApprovalView.js +28 -0
- package/lib/types/client/RoomComposer.d.ts +1 -1
- package/lib/types/client/RoomComposer.js +195 -29
- package/lib/types/client/RoomDecisionView.d.ts +22 -0
- package/lib/types/client/RoomDecisionView.js +35 -0
- package/lib/types/client/RoomHelpView.d.ts +17 -0
- package/lib/types/client/RoomHelpView.js +56 -0
- package/lib/types/client/RoomInboxView.d.ts +10 -0
- package/lib/types/client/RoomInboxView.js +14 -0
- package/lib/types/client/RoomQuestionView.d.ts +13 -0
- package/lib/types/client/RoomQuestionView.js +61 -0
- package/lib/types/client/RoomRelayView.js +1 -1
- package/lib/types/client/RoomRunView.d.ts +3 -1
- package/lib/types/client/RoomRunView.js +12 -5
- package/lib/types/client/RoomSettingsView.d.ts +19 -0
- package/lib/types/client/RoomSettingsView.js +30 -0
- package/lib/types/client/RoomSpeechView.d.ts +22 -8
- package/lib/types/client/RoomSpeechView.js +94 -11
- package/lib/types/client/RoomStatsLine.d.ts +26 -5
- package/lib/types/client/RoomStatsLine.js +53 -7
- package/lib/types/client/RoomTaskCapsule.d.ts +19 -0
- package/lib/types/client/RoomTaskCapsule.js +37 -0
- package/lib/types/client/TasksTab.d.ts +41 -0
- package/lib/types/client/TasksTab.js +43 -0
- package/lib/types/client/TasksView.d.ts +44 -0
- package/lib/types/client/TasksView.js +149 -0
- package/lib/types/client/TeamView.d.ts +33 -0
- package/lib/types/client/TeamView.js +210 -0
- package/lib/types/client/at-menu.d.ts +127 -0
- package/lib/types/client/at-menu.js +173 -0
- package/lib/types/client/draft-chips.d.ts +67 -0
- package/lib/types/client/draft-chips.js +95 -0
- package/lib/types/client/executions.d.ts +0 -30
- package/lib/types/client/executions.js +4 -34
- package/lib/types/client/icons-local.d.ts +25 -0
- package/lib/types/client/icons-local.js +10 -0
- package/lib/types/client/icons.d.ts +2 -1
- package/lib/types/client/icons.js +1 -0
- package/lib/types/client/index.js +276 -72
- package/lib/types/client/locales.d.ts +482 -52
- package/lib/types/client/locales.js +490 -60
- package/lib/types/client/nodes.d.ts +112 -17
- package/lib/types/client/nodes.js +197 -26
- package/lib/types/client/slots.d.ts +117 -47
- package/lib/types/client/task-tag.d.ts +32 -0
- package/lib/types/client/task-tag.js +33 -0
- package/lib/types/client/tasks.d.ts +50 -0
- package/lib/types/client/tasks.js +82 -0
- package/lib/types/client/team.d.ts +73 -0
- package/lib/types/client/team.js +187 -0
- package/lib/types/decisions.d.ts +49 -0
- package/lib/types/decisions.js +101 -0
- package/lib/types/deliveries.d.ts +17 -1
- package/lib/types/deliveries.js +82 -6
- package/lib/types/dispatch.d.ts +102 -4
- package/lib/types/dispatch.js +498 -109
- package/lib/types/help.d.ts +137 -0
- package/lib/types/help.js +216 -0
- package/lib/types/helps.d.ts +26 -0
- package/lib/types/helps.js +47 -0
- package/lib/types/index.d.ts +292 -52
- package/lib/types/index.js +1421 -199
- package/lib/types/jobs.d.ts +22 -0
- package/lib/types/jobs.js +77 -0
- package/lib/types/journal.d.ts +17 -27
- package/lib/types/journal.js +120 -43
- package/lib/types/messaging.d.ts +65 -0
- package/lib/types/messaging.js +160 -0
- package/lib/types/plan-service.js +7 -1
- package/lib/types/report-gate.d.ts +81 -0
- package/lib/types/report-gate.js +89 -0
- package/lib/types/tool-definition.d.ts +43 -20
- package/lib/types/tool-definition.js +145 -212
- package/lib/types/tool.d.ts +2 -2
- package/lib/types/tool.js +3 -2
- package/lib/types/types.d.ts +755 -78
- package/locale/zh.json +1 -1
- package/package.json +3 -3
- package/lib/types/client/RoomActivityDock.d.ts +0 -19
- package/lib/types/client/RoomActivityDock.js +0 -105
- package/lib/types/client/RoomDockCapsules.d.ts +0 -64
- package/lib/types/client/RoomDockCapsules.js +0 -277
- package/lib/types/client/RoomPlanTab.d.ts +0 -15
- package/lib/types/client/RoomPlanTab.js +0 -13
- package/lib/types/client/RoomTaskLineView.d.ts +0 -13
- package/lib/types/client/RoomTaskLineView.js +0 -21
|
@@ -6,7 +6,7 @@ import type { LocalAgentUi } from '@khorsheed/dsh-local-agent/client';
|
|
|
6
6
|
import type { ReactNode } from 'react';
|
|
7
7
|
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
8
8
|
import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
9
|
-
import type { RoomProviderList } from '../types.ts';
|
|
9
|
+
import type { RoomProviderList, RoomQuestionAnswer, RoomRemoval, RoomSettings } from '../types.ts';
|
|
10
10
|
import type { LocalAgentModelInfo, LocalAgentPromptResult } from '@khorsheed/dsh-local-agent/types';
|
|
11
11
|
import type { RoomChromeVisibility } from './preset-visibility.ts';
|
|
12
12
|
import type { RoomStore } from './room-store.ts';
|
|
@@ -17,23 +17,23 @@ export type RoomMutationOutcome = {
|
|
|
17
17
|
readonly ok: false;
|
|
18
18
|
readonly message: string;
|
|
19
19
|
};
|
|
20
|
+
/** A removal's outcome: what it did (for the undo line), or the failure copy. */
|
|
21
|
+
export type RoomRemovalOutcome = {
|
|
22
|
+
readonly ok: true;
|
|
23
|
+
readonly value: RoomRemoval;
|
|
24
|
+
} | {
|
|
25
|
+
readonly ok: false;
|
|
26
|
+
readonly message: string;
|
|
27
|
+
};
|
|
20
28
|
/** Injected action face of the session-header 邀请 agent action. */
|
|
21
29
|
export type InviteAgentInjected = RoomInviteInjected;
|
|
22
30
|
/** Full props of the 'conversation.session.header.actions' entry. */
|
|
23
31
|
export type InviteAgentActionProps = PropsRuntime<'conversation.session.header.actions'> & InjectFace<InviteAgentInjected> & PropsLocale<'room'>;
|
|
24
|
-
/**
|
|
25
|
-
export interface
|
|
26
|
-
/** The
|
|
32
|
+
/** The room goal action (the task page's goal line). */
|
|
33
|
+
export interface RoomGoalInjected {
|
|
34
|
+
/** The room store the views read. */
|
|
27
35
|
readonly roomStore: RoomStore;
|
|
28
|
-
/**
|
|
29
|
-
readonly addTask: (member: string, title: string, blockedBy?: string) => Promise<RoomMutationOutcome>;
|
|
30
|
-
/**
|
|
31
|
-
* Close an open task. The status is the closing state: 'done' by default;
|
|
32
|
-
* the failed row's [关闭] passes 'cancelled' — the failure already speaks
|
|
33
|
-
* for itself, and a failed task must not count as goal progress.
|
|
34
|
-
*/
|
|
35
|
-
readonly closeTask: (taskId: string, status?: 'done' | 'cancelled') => Promise<RoomMutationOutcome>;
|
|
36
|
-
/** Set (or, with a blank text, clear) the room's goal. */
|
|
36
|
+
/** Set (or, with a blank text, clear) the room goal. */
|
|
37
37
|
readonly setGoal: (text: string) => Promise<RoomMutationOutcome>;
|
|
38
38
|
}
|
|
39
39
|
/**
|
|
@@ -48,8 +48,8 @@ export interface RoomInviteInjected {
|
|
|
48
48
|
readonly roomCwd?: string | undefined;
|
|
49
49
|
/** Invite a CLI member. */
|
|
50
50
|
readonly invite: (values: RoomInviteValues) => Promise<RoomInviteOutcome>;
|
|
51
|
-
/** List the invitable providers (undefined on transport failure). */
|
|
52
|
-
readonly listProviders: () => Promise<RoomProviderList | undefined>;
|
|
51
|
+
/** List the invitable providers (undefined on transport failure); with a session, its mode rides along (`sessionPreset`). */
|
|
52
|
+
readonly listProviders: (sessionId?: SessionId) => Promise<RoomProviderList | undefined>;
|
|
53
53
|
/**
|
|
54
54
|
* Pick a member-level working directory through the official picker call
|
|
55
55
|
* (`uiWorkspace.pickDirectory` on host 0.1.2 — the picker UI itself is not
|
|
@@ -149,28 +149,48 @@ export interface RoomModelDirectory {
|
|
|
149
149
|
}
|
|
150
150
|
/**
|
|
151
151
|
* Injected face of the composer takeover entry: the dispatch submit plus the
|
|
152
|
-
* task
|
|
153
|
-
*
|
|
154
|
-
*
|
|
152
|
+
* task capsule's entry to the task page and the composer's task tag
|
|
153
|
+
* (sessionId binds at inject time), because the takeover renders the dock
|
|
154
|
+
* itself — the `conversation.input.dock` seat rides the hidden official
|
|
155
|
+
* fallback. The takeover also inherits the official bar's
|
|
155
156
|
* Stop duty: the fallback's Stop button hides with it, so `stop` re-homes the
|
|
156
157
|
* main agent's turn cancel (the runtime session face's `cancel()`). The
|
|
157
|
-
* invite share rides along for the fresh-room
|
|
158
|
+
* invite share rides along for the fresh-room invite capsule.
|
|
158
159
|
* `modelDirectory` is the official per-session model directory for the room's
|
|
159
160
|
* own main agent (bare messages ARE its turns); undefined on a host without
|
|
160
161
|
* ui-model-selection — the picker simply does not render.
|
|
161
162
|
*/
|
|
162
|
-
export interface RoomComposerInjected extends
|
|
163
|
-
|
|
164
|
-
readonly
|
|
165
|
-
|
|
166
|
-
readonly
|
|
167
|
-
readonly stopExecution?: ((name: string, run: import('../types.ts').RoomMemberRun) => Promise<RoomMutationOutcome>) | undefined;
|
|
163
|
+
export interface RoomComposerInjected extends RoomGoalInjected, RoomInviteInjected {
|
|
164
|
+
/** Open the task page (at one task); absent without the right sidebar. */
|
|
165
|
+
readonly openTasks?: ((task?: string) => void) | undefined;
|
|
166
|
+
/** The composer's task tag store (see task-tag.ts). */
|
|
167
|
+
readonly taskTags?: import('./task-tag.ts').RoomTaskTags | undefined;
|
|
168
168
|
readonly reconcileDelivery?: ((deliveryId: string, outcome: 'done' | 'cancelled', evidence: string) => Promise<RoomMutationOutcome>) | undefined;
|
|
169
|
-
readonly planCommand?: ((command: string) => Promise<RoomMutationOutcome>) | undefined;
|
|
170
169
|
readonly openPlanSession?: ((sessionId: string) => void) | undefined;
|
|
171
170
|
readonly renderMemberInbox?: LocalAgentUi['renderMemberInbox'] | undefined;
|
|
172
171
|
readonly renderMemberConfiguration?: LocalAgentUi['renderMemberConfiguration'] | undefined;
|
|
173
172
|
readonly stopMember?: ((name: string, expectedRunId?: string) => void) | undefined;
|
|
173
|
+
/**
|
|
174
|
+
* Preview one draft chip through its owning trigger source (the official
|
|
175
|
+
* editor's chip-click gesture; a quote chip opens its full-text card).
|
|
176
|
+
* @returns whether a source accepted. Absent without the input-trigger service.
|
|
177
|
+
*/
|
|
178
|
+
readonly openReference?: ((source: string, ref: string) => boolean) | undefined;
|
|
179
|
+
/**
|
|
180
|
+
* Other sessions for the @ menu: the host's session-reference candidates
|
|
181
|
+
* (the recent list merged with the query's own lookup), rooms flagged.
|
|
182
|
+
* Absent without the session-reference service.
|
|
183
|
+
*/
|
|
184
|
+
readonly listSessions?: ((query: string, signal: AbortSignal) => Promise<readonly import('./at-menu.ts').SessionCandidate[]>) | undefined;
|
|
185
|
+
/**
|
|
186
|
+
* Insert the host's session chip for a picked session over a detect-coordinate span.
|
|
187
|
+
* @returns whether the input machine took it (false: the composer falls back to text).
|
|
188
|
+
*/
|
|
189
|
+
readonly insertSessionReference?: ((candidate: import('./at-menu.ts').SessionCandidate, span: {
|
|
190
|
+
readonly start: number;
|
|
191
|
+
readonly end: number;
|
|
192
|
+
readonly draftRev: number;
|
|
193
|
+
}) => boolean) | undefined;
|
|
174
194
|
/**
|
|
175
195
|
* Dispatch a message into the room and refresh the store on success. EVERY
|
|
176
196
|
* send routes here, bare text included (the host routes bare text to the
|
|
@@ -180,8 +200,10 @@ export interface RoomComposerInjected extends RoomTasksInjected, RoomInviteInjec
|
|
|
180
200
|
* the dispatch engine runs in parallel). `targets` carries the
|
|
181
201
|
* mention-menu picks (explicit addressing wherever the `@name` sits in
|
|
182
202
|
* the sentence); the host unions them with the parsed leading tokens.
|
|
203
|
+
* `task` is the composer's tag (`new` or a task root id): it files the
|
|
204
|
+
* message under that task instead of letting dsh decide.
|
|
183
205
|
*/
|
|
184
|
-
readonly submit: (sessionId: SessionId, text: string, targets?: readonly string[]) => Promise<RoomMutationOutcome>;
|
|
206
|
+
readonly submit: (sessionId: SessionId, text: string, targets?: readonly string[], task?: string) => Promise<RoomMutationOutcome>;
|
|
185
207
|
/** Interrupt the room's own main-agent turn (the hidden official bar's Stop). */
|
|
186
208
|
readonly stop: () => void;
|
|
187
209
|
/**
|
|
@@ -206,12 +228,20 @@ export type MembersViewProps = PropsRuntime<'conversation.view'> & InjectFace<Ro
|
|
|
206
228
|
export interface RoomInviteValues {
|
|
207
229
|
readonly provider: string;
|
|
208
230
|
readonly name: string;
|
|
231
|
+
/** Short public role (omitted = none). */
|
|
232
|
+
readonly role?: string;
|
|
233
|
+
/** `native`: a DSH child agent in this host (omitted = a CLI member). */
|
|
234
|
+
readonly kind?: 'cli' | 'native';
|
|
235
|
+
/** Native only: the host agent preset (omitted = the host default). */
|
|
236
|
+
readonly preset?: string;
|
|
209
237
|
readonly instructions?: string;
|
|
210
238
|
/** Member-level working directory (omitted = inherits the room session's cwd). */
|
|
211
239
|
readonly cwd?: string;
|
|
212
240
|
readonly firstTask?: string;
|
|
213
241
|
/** The delegation's invite-time model (omitted = follow the harness default). */
|
|
214
242
|
readonly model?: string;
|
|
243
|
+
/** The delegation's invite-time reasoning effort (omitted = follow the harness default). */
|
|
244
|
+
readonly effort?: string;
|
|
215
245
|
}
|
|
216
246
|
/** The invite outcome: the receipt's pendingFirstTask picks the success copy. */
|
|
217
247
|
export type RoomInviteOutcome = {
|
|
@@ -230,7 +260,15 @@ export interface RoomMembersInjected extends RoomInviteInjected {
|
|
|
230
260
|
readonly openSession: (sessionId: SessionId) => void;
|
|
231
261
|
/** Remove the named member from the roster. */
|
|
232
262
|
readonly setCoordinator?: ((memberId: string, expectedRevision: number) => Promise<RoomMutationOutcome>) | undefined;
|
|
233
|
-
readonly removeMember: (member: string) => Promise<
|
|
263
|
+
readonly removeMember: (member: string) => Promise<RoomRemovalOutcome>;
|
|
264
|
+
/** Undo a removal: the member rejoins on its own session. */
|
|
265
|
+
readonly restoreMember: (member: string) => Promise<RoomMutationOutcome>;
|
|
266
|
+
/** Open the team page in the right sidebar, optionally revealing one member. Absent without a sidebar. */
|
|
267
|
+
readonly openTeam?: ((member?: string) => void) | undefined;
|
|
268
|
+
/** Take an outside session off the member list (its own session is untouched). */
|
|
269
|
+
readonly unlinkSession?: ((target: string) => void) | undefined;
|
|
270
|
+
/** Change the room's collaboration settings. */
|
|
271
|
+
readonly setSettings: (patch: Partial<RoomSettings>) => Promise<RoomMutationOutcome>;
|
|
234
272
|
/**
|
|
235
273
|
* Edit the named member: rename, cwd override (null clears back to
|
|
236
274
|
* inheriting the room cwd), role instructions (null clears them), intended
|
|
@@ -265,10 +303,14 @@ export interface RoomMemberPatch {
|
|
|
265
303
|
readonly rename?: string;
|
|
266
304
|
/** New role instructions; null clears them. */
|
|
267
305
|
readonly instructions?: string | null;
|
|
306
|
+
/** New public role; null clears it. */
|
|
307
|
+
readonly role?: string | null;
|
|
268
308
|
/** New cwd override; null clears back to inheriting the room cwd. */
|
|
269
309
|
readonly cwd?: string | null;
|
|
270
310
|
/** New intended model; null clears back to the harness default. */
|
|
271
311
|
readonly model?: string | null;
|
|
312
|
+
/** New intended reasoning effort; null clears back to the harness default. */
|
|
313
|
+
readonly effort?: string | null;
|
|
272
314
|
}
|
|
273
315
|
/** Injected face of the member-speech chat node. */
|
|
274
316
|
export interface RoomSpeechInjected {
|
|
@@ -276,6 +318,11 @@ export interface RoomSpeechInjected {
|
|
|
276
318
|
readonly roomStore: RoomStore;
|
|
277
319
|
/** Open a session (the speech's child-session jump). */
|
|
278
320
|
readonly openSession: (sessionId: SessionId) => void;
|
|
321
|
+
/**
|
|
322
|
+
* Open Context Lens at the member's round (its session + closing message);
|
|
323
|
+
* absent when the composition has no Context Lens.
|
|
324
|
+
*/
|
|
325
|
+
readonly openDetail?: ((sessionId: SessionId, messageId: string) => void) | undefined;
|
|
279
326
|
}
|
|
280
327
|
/** Full props of the 'room-speech' chat-node renderer. */
|
|
281
328
|
export type RoomSpeechViewProps = PropsRuntime<'conversation.chat.node', 'room-speech'> & InjectFace<RoomSpeechInjected> & PropsLocale<'room'>;
|
|
@@ -304,24 +351,47 @@ export interface RoomRelayInjected {
|
|
|
304
351
|
}
|
|
305
352
|
/** Full props of the 'room-relay' chat-node renderer. */
|
|
306
353
|
export type RoomRelayViewProps = PropsRuntime<'conversation.chat.node', 'room-relay'> & InjectFace<RoomRelayInjected> & PropsLocale<'room'>;
|
|
307
|
-
/** Injected face of
|
|
308
|
-
export interface
|
|
309
|
-
/**
|
|
310
|
-
readonly
|
|
354
|
+
/** Injected face of a member's tool approval line. */
|
|
355
|
+
export interface RoomApprovalInjected {
|
|
356
|
+
/** Answer the approval (allow once / reject); resolves with an error message when it already ended. */
|
|
357
|
+
readonly answerApproval: (approvalId: string, outcome: 'allowed-once' | 'rejected') => Promise<string | undefined>;
|
|
311
358
|
}
|
|
312
|
-
/**
|
|
313
|
-
export
|
|
314
|
-
/**
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
359
|
+
/** Injected face of a room decision row. */
|
|
360
|
+
export interface RoomDecisionInjected {
|
|
361
|
+
/** Open Context Lens at this decision's model request; absent without Context Lens. */
|
|
362
|
+
readonly openDecision?: ((decisionId: string) => void) | undefined;
|
|
363
|
+
}
|
|
364
|
+
/** Full props of the 'room-decision' chat-node renderer. */
|
|
365
|
+
export type RoomDecisionViewProps = PropsRuntime<'conversation.chat.node', 'room-decision'> & InjectFace<RoomDecisionInjected> & PropsLocale<'room'>;
|
|
366
|
+
/** Injected face of a member's question card. */
|
|
367
|
+
export interface RoomQuestionInjected {
|
|
368
|
+
/** Submit the answers; resolves with an error message when the card already ended. */
|
|
369
|
+
readonly answerQuestion: (questionId: string, answers: readonly RoomQuestionAnswer[]) => Promise<string | undefined>;
|
|
370
|
+
}
|
|
371
|
+
/** Full props of the 'room-question' chat-node renderer. */
|
|
372
|
+
export type RoomQuestionViewProps = PropsRuntime<'conversation.chat.node', 'room-question'> & InjectFace<RoomQuestionInjected> & PropsLocale<'room'>;
|
|
373
|
+
/** Injected face of the help rows (the asking room's thread row, the helper's request card). */
|
|
374
|
+
export interface RoomHelpInjected {
|
|
375
|
+
/** Open another session (the helper's, or the asking room). */
|
|
376
|
+
readonly openSession: (sessionId: SessionId) => void;
|
|
377
|
+
/** Keep an outside session on the member list (the third ask's hint). */
|
|
378
|
+
readonly linkSession?: ((target: string, title: string) => void) | undefined;
|
|
379
|
+
/** Dismiss that hint for good. */
|
|
380
|
+
readonly dismissNudge?: ((target: string) => void) | undefined;
|
|
381
|
+
/** The client-side room state store (the reminder setting). */
|
|
382
|
+
readonly roomStore?: RoomStore | undefined;
|
|
383
|
+
}
|
|
384
|
+
/** Full props of the 'room-help' chat-node renderer. */
|
|
385
|
+
export type RoomHelpViewProps = PropsRuntime<'conversation.chat.node', 'room-help'> & InjectFace<RoomHelpInjected> & PropsLocale<'room'>;
|
|
386
|
+
/** Full props of the 'room-help-request' chat-node renderer. */
|
|
387
|
+
export type RoomHelpRequestViewProps = PropsRuntime<'conversation.chat.node', 'room-help-request'> & InjectFace<RoomHelpInjected> & PropsLocale<'room'>;
|
|
388
|
+
/** Full props of the 'room-approval' chat-node renderer. */
|
|
389
|
+
export type RoomApprovalViewProps = PropsRuntime<'conversation.chat.node', 'room-approval'> & InjectFace<RoomApprovalInjected> & PropsLocale<'room'>;
|
|
390
|
+
/** Injected face of the held-reports line. */
|
|
391
|
+
export interface RoomInboxInjected {
|
|
392
|
+
/** Hand the named member its held reports now. */
|
|
393
|
+
readonly releaseReports: (member: string) => Promise<void>;
|
|
394
|
+
}
|
|
395
|
+
/** Full props of the 'room-inbox' chat-node renderer. */
|
|
396
|
+
export type RoomInboxViewProps = PropsRuntime<'conversation.chat.node', 'room-inbox'> & InjectFace<RoomInboxInjected> & PropsLocale<'room'>;
|
|
327
397
|
//# sourceMappingURL=slots.d.ts.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The composer's task tag, per room session: the task page's 「追问」 and
|
|
3
|
+
* 「+ 新任务」 put a removable 「任务 N」 / 「新任务」 chip on the main
|
|
4
|
+
* composer (the page has no input of its own), the next send carries it as
|
|
5
|
+
* postMessage's `task`, and removing the chip leaves the filing to dsh.
|
|
6
|
+
* Every set bumps a revision so the composer takes focus even when the
|
|
7
|
+
* same tag is set twice.
|
|
8
|
+
*/
|
|
9
|
+
/** A tag on the composer. */
|
|
10
|
+
export interface RoomTaskTag {
|
|
11
|
+
/** `new`, or the task's root id. */
|
|
12
|
+
readonly task: string;
|
|
13
|
+
/** The chip text (「任务 3」 / 「新任务」). */
|
|
14
|
+
readonly label: string;
|
|
15
|
+
readonly revision: number;
|
|
16
|
+
}
|
|
17
|
+
/** The shared tag store; one per client plugin. */
|
|
18
|
+
export declare class RoomTaskTags {
|
|
19
|
+
private readonly tags;
|
|
20
|
+
private readonly listeners;
|
|
21
|
+
private revision;
|
|
22
|
+
/** Subscribe to tag changes (useSyncExternalStore shape). */
|
|
23
|
+
readonly subscribe: (listener: () => void) => (() => void);
|
|
24
|
+
/** The session's current tag. */
|
|
25
|
+
readonly get: (sessionId: string) => RoomTaskTag | undefined;
|
|
26
|
+
/** Put a tag on the session's composer, or clear it. */
|
|
27
|
+
set(sessionId: string, tag: {
|
|
28
|
+
readonly task: string;
|
|
29
|
+
readonly label: string;
|
|
30
|
+
} | undefined): void;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=task-tag.d.ts.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The composer's task tag, per room session: the task page's 「追问」 and
|
|
3
|
+
* 「+ 新任务」 put a removable 「任务 N」 / 「新任务」 chip on the main
|
|
4
|
+
* composer (the page has no input of its own), the next send carries it as
|
|
5
|
+
* postMessage's `task`, and removing the chip leaves the filing to dsh.
|
|
6
|
+
* Every set bumps a revision so the composer takes focus even when the
|
|
7
|
+
* same tag is set twice.
|
|
8
|
+
*/
|
|
9
|
+
/** The shared tag store; one per client plugin. */
|
|
10
|
+
export class RoomTaskTags {
|
|
11
|
+
tags = new Map();
|
|
12
|
+
listeners = new Set();
|
|
13
|
+
revision = 0;
|
|
14
|
+
/** Subscribe to tag changes (useSyncExternalStore shape). */
|
|
15
|
+
subscribe = (listener) => {
|
|
16
|
+
this.listeners.add(listener);
|
|
17
|
+
return () => { this.listeners.delete(listener); };
|
|
18
|
+
};
|
|
19
|
+
/** The session's current tag. */
|
|
20
|
+
get = (sessionId) => this.tags.get(sessionId);
|
|
21
|
+
/** Put a tag on the session's composer, or clear it. */
|
|
22
|
+
set(sessionId, tag) {
|
|
23
|
+
if (tag === undefined) {
|
|
24
|
+
if (!this.tags.delete(sessionId))
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
this.tags.set(sessionId, { ...tag, revision: ++this.revision });
|
|
29
|
+
}
|
|
30
|
+
for (const listener of this.listeners)
|
|
31
|
+
listener();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure projections the task page and the composer's task capsule share:
|
|
3
|
+
* which tasks need the human, a task's subtask tree (who handed what to
|
|
4
|
+
* whom, from each delivery's `parent`), and the time segments its rows and
|
|
5
|
+
* swimlanes draw.
|
|
6
|
+
*/
|
|
7
|
+
import type { RoomDelivery, RoomJob, RoomRelay, RoomState } from '../types.ts';
|
|
8
|
+
/** One stretch of a delivery's life on the timeline. */
|
|
9
|
+
export interface TaskSegment {
|
|
10
|
+
/** queue = waiting to start, held = a finished report waiting to be handed over, exec = running. */
|
|
11
|
+
readonly kind: 'queue' | 'held' | 'exec';
|
|
12
|
+
readonly from: number;
|
|
13
|
+
readonly to: number;
|
|
14
|
+
}
|
|
15
|
+
/** A delivery placed in its task's tree. */
|
|
16
|
+
export interface SubtaskNode {
|
|
17
|
+
readonly delivery: RoomDelivery;
|
|
18
|
+
readonly children: readonly SubtaskNode[];
|
|
19
|
+
}
|
|
20
|
+
/** The list filters, in order. */
|
|
21
|
+
export declare const TASK_FILTERS: readonly ['running', 'attention', 'done', 'all'];
|
|
22
|
+
export type TaskFilter = typeof TASK_FILTERS[number];
|
|
23
|
+
/** Completed tasks shown by default; older ones stay in the log. */
|
|
24
|
+
export declare const DONE_SHOWN = 20;
|
|
25
|
+
/** Whether a delivery is still open (queued, running or a held report). */
|
|
26
|
+
export declare function isOpenDelivery(row: RoomDelivery): boolean;
|
|
27
|
+
/** Relays waiting for the human's confirmation. */
|
|
28
|
+
export declare function pendingRelays(state: RoomState): readonly RoomRelay[];
|
|
29
|
+
/** How many things wait on the human: deliveries with an unknown outcome, held relays, and members' tool approvals. */
|
|
30
|
+
export declare function attentionCount(state: RoomState): number;
|
|
31
|
+
/** Whether a task needs the human: an uncertain delivery, or a relay held inside it. */
|
|
32
|
+
export declare function needsAttention(state: RoomState, job: RoomJob): boolean;
|
|
33
|
+
/** The tasks a filter shows (`running` includes those needing attention, as both are open). */
|
|
34
|
+
export declare function filterJobs(state: RoomState, filter: TaskFilter): readonly RoomJob[];
|
|
35
|
+
/** A task's deliveries, in dispatch order. */
|
|
36
|
+
export declare function jobDeliveries(state: RoomState, job: RoomJob): readonly RoomDelivery[];
|
|
37
|
+
/**
|
|
38
|
+
* The task's subtask tree: work handed out (reports travel back up the tree
|
|
39
|
+
* and are not nodes), each delivery under the delivery whose round sent it.
|
|
40
|
+
* A delivery whose sender is outside the task — the human, or a round of
|
|
41
|
+
* another task — is a root.
|
|
42
|
+
*/
|
|
43
|
+
export declare function subtaskTree(state: RoomState, job: RoomJob): readonly SubtaskNode[];
|
|
44
|
+
/** A delivery's time segments up to `now` for the open edges. */
|
|
45
|
+
export declare function segmentsOf(row: RoomDelivery, now: number): readonly TaskSegment[];
|
|
46
|
+
/** How long a task has taken: to its last settlement, or until now while open. */
|
|
47
|
+
export declare function jobElapsed(job: RoomJob, now: number): number;
|
|
48
|
+
/** The members still working on a task (running), by id, in first-start order. */
|
|
49
|
+
export declare function runningMembers(state: RoomState, job: RoomJob): readonly string[];
|
|
50
|
+
//# sourceMappingURL=tasks.d.ts.map
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/** The list filters, in order. */
|
|
2
|
+
export const TASK_FILTERS = ['running', 'attention', 'done', 'all'];
|
|
3
|
+
/** Completed tasks shown by default; older ones stay in the log. */
|
|
4
|
+
export const DONE_SHOWN = 20;
|
|
5
|
+
const OPEN = new Set(['queued', 'running', 'held']);
|
|
6
|
+
/** Whether a delivery is still open (queued, running or a held report). */
|
|
7
|
+
export function isOpenDelivery(row) {
|
|
8
|
+
return OPEN.has(row.status);
|
|
9
|
+
}
|
|
10
|
+
/** Relays waiting for the human's confirmation. */
|
|
11
|
+
export function pendingRelays(state) {
|
|
12
|
+
return state.relays.filter(relay => relay.state === 'pending');
|
|
13
|
+
}
|
|
14
|
+
/** How many things wait on the human: deliveries with an unknown outcome, held relays, and members' tool approvals. */
|
|
15
|
+
export function attentionCount(state) {
|
|
16
|
+
return (state.deliveries ?? []).filter(row => row.status === 'uncertain').length + pendingRelays(state).length + (state.approvals?.length ?? 0) + (state.questions?.length ?? 0);
|
|
17
|
+
}
|
|
18
|
+
/** Whether a task needs the human: an uncertain delivery, or a relay held inside it. */
|
|
19
|
+
export function needsAttention(state, job) {
|
|
20
|
+
return job.status === 'attention' || pendingRelays(state).some(relay => relay.intent?.task === job.id);
|
|
21
|
+
}
|
|
22
|
+
/** The tasks a filter shows (`running` includes those needing attention, as both are open). */
|
|
23
|
+
export function filterJobs(state, filter) {
|
|
24
|
+
const jobs = state.jobs ?? [];
|
|
25
|
+
switch (filter) {
|
|
26
|
+
case 'running': return jobs.filter(job => job.status === 'running' || needsAttention(state, job));
|
|
27
|
+
case 'attention': return jobs.filter(job => needsAttention(state, job));
|
|
28
|
+
case 'done': return jobs.filter(job => job.status === 'done' || job.status === 'stopped').slice(0, DONE_SHOWN);
|
|
29
|
+
case 'all': return jobs.slice(0, DONE_SHOWN + jobs.filter(job => job.status !== 'done' && job.status !== 'stopped').length);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/** A task's deliveries, in dispatch order. */
|
|
33
|
+
export function jobDeliveries(state, job) {
|
|
34
|
+
const ids = new Set(job.deliveries);
|
|
35
|
+
return (state.deliveries ?? []).filter(row => ids.has(row.id));
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* The task's subtask tree: work handed out (reports travel back up the tree
|
|
39
|
+
* and are not nodes), each delivery under the delivery whose round sent it.
|
|
40
|
+
* A delivery whose sender is outside the task — the human, or a round of
|
|
41
|
+
* another task — is a root.
|
|
42
|
+
*/
|
|
43
|
+
export function subtaskTree(state, job) {
|
|
44
|
+
const rows = jobDeliveries(state, job).filter(row => row.origin !== 'report');
|
|
45
|
+
const ids = new Set(rows.map(row => row.id));
|
|
46
|
+
const children = new Map();
|
|
47
|
+
for (const row of rows) {
|
|
48
|
+
const parent = row.parent !== undefined && ids.has(row.parent) ? row.parent : undefined;
|
|
49
|
+
children.set(parent, [...children.get(parent) ?? [], row]);
|
|
50
|
+
}
|
|
51
|
+
const build = (parent, seen) => (children.get(parent) ?? []).filter(row => !seen.has(row.id))
|
|
52
|
+
.map(row => ({ delivery: row, children: build(row.id, new Set([...seen, row.id])) }));
|
|
53
|
+
return build(undefined, new Set());
|
|
54
|
+
}
|
|
55
|
+
/** A delivery's time segments up to `now` for the open edges. */
|
|
56
|
+
export function segmentsOf(row, now) {
|
|
57
|
+
const segments = [];
|
|
58
|
+
const end = row.endedAt ?? (isOpenDelivery(row) ? now : row.startedAt ?? row.queuedAt);
|
|
59
|
+
const started = row.startedAt ?? (row.status === 'queued' || row.status === 'held' ? now : end);
|
|
60
|
+
if (row.heldAt !== undefined) {
|
|
61
|
+
const released = row.releasedAt ?? Math.min(started, now);
|
|
62
|
+
if (row.heldAt > row.queuedAt)
|
|
63
|
+
segments.push({ kind: 'queue', from: row.queuedAt, to: row.heldAt });
|
|
64
|
+
segments.push({ kind: 'held', from: row.heldAt, to: released });
|
|
65
|
+
if (started > released)
|
|
66
|
+
segments.push({ kind: 'queue', from: released, to: started });
|
|
67
|
+
}
|
|
68
|
+
else if (started > row.queuedAt) {
|
|
69
|
+
segments.push({ kind: 'queue', from: row.queuedAt, to: started });
|
|
70
|
+
}
|
|
71
|
+
if (row.startedAt !== undefined && end > row.startedAt)
|
|
72
|
+
segments.push({ kind: 'exec', from: row.startedAt, to: end });
|
|
73
|
+
return segments;
|
|
74
|
+
}
|
|
75
|
+
/** How long a task has taken: to its last settlement, or until now while open. */
|
|
76
|
+
export function jobElapsed(job, now) {
|
|
77
|
+
return Math.max(0, (job.endedAt ?? now) - job.startedAt);
|
|
78
|
+
}
|
|
79
|
+
/** The members still working on a task (running), by id, in first-start order. */
|
|
80
|
+
export function runningMembers(state, job) {
|
|
81
|
+
return [...new Set(jobDeliveries(state, job).filter(row => row.status === 'running').map(row => row.memberId))];
|
|
82
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { RoomDelivery, RoomHelp, RoomMember, RoomState } from '../types.ts';
|
|
2
|
+
/** The human, as a tree root. */
|
|
3
|
+
export declare const TEAM_ROOT = "you";
|
|
4
|
+
/** One delivery a member received. */
|
|
5
|
+
export interface TeamDelivery {
|
|
6
|
+
readonly id: string;
|
|
7
|
+
readonly seq: number;
|
|
8
|
+
/** Sender name, or {@link TEAM_ROOT} for the human. */
|
|
9
|
+
readonly from: string;
|
|
10
|
+
readonly text: string;
|
|
11
|
+
readonly status: RoomDelivery['status'];
|
|
12
|
+
readonly kind: 'task' | 'notify' | 'report';
|
|
13
|
+
}
|
|
14
|
+
/** One member node. */
|
|
15
|
+
export interface TeamNode {
|
|
16
|
+
/** Member id (name for legacy members without one). */
|
|
17
|
+
readonly id: string;
|
|
18
|
+
readonly member: RoomMember;
|
|
19
|
+
/** Parent node id, or {@link TEAM_ROOT}. */
|
|
20
|
+
readonly parent: string;
|
|
21
|
+
readonly coordinator: boolean;
|
|
22
|
+
readonly status: 'running' | 'idle' | 'failed';
|
|
23
|
+
/** The running delivery's task title, when running. */
|
|
24
|
+
readonly current?: string;
|
|
25
|
+
readonly model?: string;
|
|
26
|
+
readonly tokens: number;
|
|
27
|
+
readonly elapsedMs: number;
|
|
28
|
+
readonly rounds: number;
|
|
29
|
+
/** Newest first. */
|
|
30
|
+
readonly deliveries: readonly TeamDelivery[];
|
|
31
|
+
/** An outside session: asked for help (and/or kept on the member list). */
|
|
32
|
+
readonly external?: {
|
|
33
|
+
readonly sessionId: string;
|
|
34
|
+
/** On the member list (「加入房间成员」). */
|
|
35
|
+
readonly linked: boolean;
|
|
36
|
+
/** A room target (asked through that room's roster): never linkable. */
|
|
37
|
+
readonly room: boolean;
|
|
38
|
+
/** Every ask has ended (replied or failed). */
|
|
39
|
+
readonly done: boolean;
|
|
40
|
+
readonly helps: readonly RoomHelp[];
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/** What flowed from one node to another. */
|
|
44
|
+
export interface TeamEdge {
|
|
45
|
+
readonly from: string;
|
|
46
|
+
readonly to: string;
|
|
47
|
+
readonly tasks: number;
|
|
48
|
+
readonly reports: number;
|
|
49
|
+
readonly notifies: number;
|
|
50
|
+
}
|
|
51
|
+
/** The whole projection. */
|
|
52
|
+
export interface Team {
|
|
53
|
+
readonly nodes: readonly TeamNode[];
|
|
54
|
+
readonly edges: readonly TeamEdge[];
|
|
55
|
+
readonly totals: {
|
|
56
|
+
readonly members: number;
|
|
57
|
+
readonly running: number;
|
|
58
|
+
readonly deliveries: number;
|
|
59
|
+
readonly tokens: number;
|
|
60
|
+
readonly elapsedMs: number;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Project the room state into the team tree.
|
|
65
|
+
* @param state - the replayed room state.
|
|
66
|
+
* @returns nodes in tree order (parents before children), edges and totals.
|
|
67
|
+
*/
|
|
68
|
+
export declare function teamOf(state: RoomState): Team;
|
|
69
|
+
/** The id of an outside session's node. */
|
|
70
|
+
export declare const externalId: (sessionId: string, member?: string) => string;
|
|
71
|
+
/** Compact token count: 1.2M / 288k / 512. */
|
|
72
|
+
export declare function formatTokens(tokens: number): string;
|
|
73
|
+
//# sourceMappingURL=team.d.ts.map
|