@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
|
@@ -11,12 +11,15 @@
|
|
|
11
11
|
* RoomService.postMessage) and renders through the official user node.
|
|
12
12
|
* @module @khorsheed/dsh-room/client/nodes
|
|
13
13
|
*/
|
|
14
|
+
import type { RoomDecisionEvent, RoomHelp, RoomQuestionAnswer, RoomQuestionItem } from '../types.ts';
|
|
14
15
|
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
15
16
|
import type { ConversationNodeDefinition } from '@deepseek-ai/dsh-client-ui-conversation/client';
|
|
16
17
|
/** Chat node data of one member speech row. */
|
|
17
18
|
export interface RoomSpeechData {
|
|
18
19
|
/** Partial output from a stopped or failed run; never a completed answer. */
|
|
19
20
|
readonly interrupted?: 'cancelled' | 'failed';
|
|
21
|
+
/** The member this reply was also reported to. */
|
|
22
|
+
readonly reportedTo?: string;
|
|
20
23
|
/** Seq of the room/speech event. */
|
|
21
24
|
readonly seq: number;
|
|
22
25
|
/** Unix epoch ms from the event. */
|
|
@@ -27,6 +30,10 @@ export interface RoomSpeechData {
|
|
|
27
30
|
readonly childSessionId?: SessionId;
|
|
28
31
|
/** Dispatch→settle milliseconds, when measured. */
|
|
29
32
|
readonly durationMs?: number;
|
|
33
|
+
/** The run this speech closed: its execution metadata (tokens) is keyed by it. */
|
|
34
|
+
readonly runId?: string;
|
|
35
|
+
/** The member's closing message in its own session. */
|
|
36
|
+
readonly messageId?: string;
|
|
30
37
|
}
|
|
31
38
|
/** Chat node data of one member run row. */
|
|
32
39
|
export interface RoomRunData {
|
|
@@ -57,6 +64,55 @@ export interface RoomEventData {
|
|
|
57
64
|
readonly invitedBy?: 'human' | 'agent';
|
|
58
65
|
}
|
|
59
66
|
/** Chat node data of one member-to-member notification relay row. */
|
|
67
|
+
/** Chat node data of a member's tool approval (the 允许 / 拒绝 line). */
|
|
68
|
+
export interface RoomApprovalData {
|
|
69
|
+
readonly seq: number;
|
|
70
|
+
readonly time: number;
|
|
71
|
+
readonly approvalId: string;
|
|
72
|
+
readonly member: string;
|
|
73
|
+
readonly tool: string;
|
|
74
|
+
readonly reason?: string;
|
|
75
|
+
readonly state: 'pending' | 'allowed-once' | 'rejected' | 'cancelled';
|
|
76
|
+
}
|
|
77
|
+
/** Chat node data of one decision the room made on its own (a timeline row). */
|
|
78
|
+
export interface RoomDecisionData {
|
|
79
|
+
readonly seq: number;
|
|
80
|
+
readonly time: number;
|
|
81
|
+
readonly decision: RoomDecisionEvent;
|
|
82
|
+
}
|
|
83
|
+
/** Chat node data of a cross-session help thread, in the asking room. */
|
|
84
|
+
export interface RoomHelpData {
|
|
85
|
+
readonly seq: number;
|
|
86
|
+
readonly time: number;
|
|
87
|
+
readonly help: RoomHelp;
|
|
88
|
+
}
|
|
89
|
+
/** Chat node data of a help request (or a follow-up on it), in the helper's own session. */
|
|
90
|
+
export interface RoomHelpRequestData {
|
|
91
|
+
readonly seq: number;
|
|
92
|
+
readonly time: number;
|
|
93
|
+
readonly help: string;
|
|
94
|
+
/** The asking room's session and title. */
|
|
95
|
+
readonly room: string;
|
|
96
|
+
readonly roomTitle: string;
|
|
97
|
+
/** The asking member. */
|
|
98
|
+
readonly from: string;
|
|
99
|
+
readonly op: 'request' | 'message';
|
|
100
|
+
/** The asker's own words. */
|
|
101
|
+
readonly text: string;
|
|
102
|
+
/** Another room asked this room: the member it went to, and whether the paused room holds it. */
|
|
103
|
+
readonly member?: string;
|
|
104
|
+
readonly held?: boolean;
|
|
105
|
+
}
|
|
106
|
+
/** Chat node data of a member's question card (pick-to-answer). */
|
|
107
|
+
export interface RoomQuestionData {
|
|
108
|
+
readonly seq: number;
|
|
109
|
+
readonly time: number;
|
|
110
|
+
readonly questionId: string;
|
|
111
|
+
readonly member: string;
|
|
112
|
+
readonly questions: readonly RoomQuestionItem[];
|
|
113
|
+
readonly state: 'pending' | 'answered' | 'cancelled';
|
|
114
|
+
readonly answers?: readonly RoomQuestionAnswer[];
|
|
115
|
+
}
|
|
60
116
|
export interface RoomRelayData {
|
|
61
117
|
/** Seq of the relay's latest journal event. */
|
|
62
118
|
readonly seq: number;
|
|
@@ -68,17 +124,19 @@ export interface RoomRelayData {
|
|
|
68
124
|
readonly to: string;
|
|
69
125
|
readonly content: string;
|
|
70
126
|
readonly state: 'pending' | 'confirmed' | 'dismissed' | 'sent';
|
|
127
|
+
/** Why the message waits (absent on legacy relays). */
|
|
128
|
+
readonly reason?: 'confirm' | 'hop-limit' | 'paused';
|
|
71
129
|
}
|
|
72
|
-
/** Chat node data of
|
|
73
|
-
export interface
|
|
74
|
-
/** Seq of the
|
|
130
|
+
/** Chat node data of the held-reports line for one member. */
|
|
131
|
+
export interface RoomInboxData {
|
|
132
|
+
/** Seq of the latest hold (the line sits there). */
|
|
75
133
|
readonly seq: number;
|
|
76
|
-
/** Unix epoch ms of that event. */
|
|
77
134
|
readonly time: number;
|
|
78
|
-
readonly taskId: string;
|
|
79
135
|
readonly member: string;
|
|
80
|
-
|
|
81
|
-
readonly
|
|
136
|
+
/** Held dispatch seqs not yet released. */
|
|
137
|
+
readonly held: readonly number[];
|
|
138
|
+
/** The model's yes-probability on the latest hold, when it answered. */
|
|
139
|
+
readonly probability?: number;
|
|
82
140
|
}
|
|
83
141
|
declare module '@deepseek-ai/dsh-client-ui-chat/client' {
|
|
84
142
|
interface ChatNodeDataMap {
|
|
@@ -90,8 +148,18 @@ declare module '@deepseek-ai/dsh-client-ui-chat/client' {
|
|
|
90
148
|
'room-event': RoomEventData;
|
|
91
149
|
/** room: a member-to-member notification relay (gate row). */
|
|
92
150
|
'room-relay': RoomRelayData;
|
|
93
|
-
/** room: a
|
|
94
|
-
'room-
|
|
151
|
+
/** room: a member's mode tool waiting for the human's approval. */
|
|
152
|
+
'room-approval': RoomApprovalData;
|
|
153
|
+
/** room: a decision the room made on its own (rule or decision model). */
|
|
154
|
+
'room-decision': RoomDecisionData;
|
|
155
|
+
/** room: a member's questions for the human (pick-to-answer card). */
|
|
156
|
+
'room-question': RoomQuestionData;
|
|
157
|
+
/** room: a help thread this room opened with another session. */
|
|
158
|
+
'room-help': RoomHelpData;
|
|
159
|
+
/** room: a help request another session's room sent this session. */
|
|
160
|
+
'room-help-request': RoomHelpRequestData;
|
|
161
|
+
/** room: reports the gate holds in a member's inbox. */
|
|
162
|
+
'room-inbox': RoomInboxData;
|
|
95
163
|
}
|
|
96
164
|
}
|
|
97
165
|
/**
|
|
@@ -117,6 +185,18 @@ export declare const roomRunDefinition: ConversationNodeDefinition<RoomRunData>;
|
|
|
117
185
|
* through the official user node (it is also appended as `user/message`).
|
|
118
186
|
*/
|
|
119
187
|
export declare const roomEventDefinition: ConversationNodeDefinition<RoomEventData>;
|
|
188
|
+
/** A room decision: one single-event Context per `room/decision`. */
|
|
189
|
+
export declare const roomDecisionDefinition: ConversationNodeDefinition<RoomDecisionData>;
|
|
190
|
+
/**
|
|
191
|
+
* A member's tool approval: one Context per approval, started by
|
|
192
|
+
* `room/approval` and settled in place by `room/approval-resolved`.
|
|
193
|
+
*/
|
|
194
|
+
export declare const roomApprovalDefinition: ConversationNodeDefinition<RoomApprovalData>;
|
|
195
|
+
/**
|
|
196
|
+
* A member's question card: one Context per card, started by `room/question`
|
|
197
|
+
* and settled in place (with the answers) by `room/question-resolved`.
|
|
198
|
+
*/
|
|
199
|
+
export declare const roomQuestionDefinition: ConversationNodeDefinition<RoomQuestionData>;
|
|
120
200
|
/**
|
|
121
201
|
* The relay Definition: one Context per relay (matched on the relay id),
|
|
122
202
|
* started by the `room/relay` event (pending) and updated by each
|
|
@@ -124,13 +204,28 @@ export declare const roomEventDefinition: ConversationNodeDefinition<RoomEventDa
|
|
|
124
204
|
*/
|
|
125
205
|
export declare const roomRelayDefinition: ConversationNodeDefinition<RoomRelayData>;
|
|
126
206
|
/**
|
|
127
|
-
* The
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
207
|
+
* The held-reports line: one Context per member (its gate verdicts), visible
|
|
208
|
+
* while the gate holds reports for it — 「📥 dsh 的收件箱里有 2 条回报,先攒着」
|
|
209
|
+
* with a 现在交给 button — and hidden once they are released. It moves to the
|
|
210
|
+
* latest hold, so it always sits after the reply that was held.
|
|
211
|
+
*/
|
|
212
|
+
export declare const roomInboxDefinition: ConversationNodeDefinition<RoomInboxData>;
|
|
213
|
+
/**
|
|
214
|
+
* A help thread in the asking room: one Context per thread, started by
|
|
215
|
+
* `room/help` and folded in place by its `room/help-message` and
|
|
216
|
+
* `room/help-state` events (one row whose state and messages update).
|
|
217
|
+
*/
|
|
218
|
+
export declare const roomHelpDefinition: ConversationNodeDefinition<RoomHelpData>;
|
|
219
|
+
/**
|
|
220
|
+
* A help request in the helper's session: the `user/message` the room queued
|
|
221
|
+
* there (its `room-help` source) renders as a card naming the asking room
|
|
222
|
+
* instead of a plain injected-context row.
|
|
223
|
+
*/
|
|
224
|
+
export declare const roomHelpRequestDefinition: ConversationNodeDefinition<RoomHelpRequestData>;
|
|
225
|
+
/**
|
|
226
|
+
* Another room asked this room for help (`room/help-in`): the same request
|
|
227
|
+
* card, naming the member it went to (and that it waits while this room is
|
|
228
|
+
* paused), with a jump back to the asking room.
|
|
134
229
|
*/
|
|
135
|
-
export declare const
|
|
230
|
+
export declare const roomHelpInDefinition: ConversationNodeDefinition<RoomHelpRequestData>;
|
|
136
231
|
//# sourceMappingURL=nodes.d.ts.map
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isAppendSurfaceEvent } from '@deepseek-ai/dsh-session/surface';
|
|
1
2
|
/** The shared final-node materialization (single shape across the three kinds). */
|
|
2
3
|
function viewNode(context, kind, visibility = 'visible') {
|
|
3
4
|
if (context.state === undefined)
|
|
@@ -33,8 +34,11 @@ export const roomSpeechDefinition = {
|
|
|
33
34
|
member: event.data.member,
|
|
34
35
|
text: event.data.text,
|
|
35
36
|
...event.data.interrupted === undefined ? {} : { interrupted: event.data.interrupted },
|
|
37
|
+
...event.data.reportedTo === undefined ? {} : { reportedTo: event.data.reportedTo },
|
|
36
38
|
...event.data.childSessionId === undefined ? {} : { childSessionId: event.data.childSessionId },
|
|
37
39
|
...event.data.durationMs === undefined ? {} : { durationMs: event.data.durationMs },
|
|
40
|
+
...event.data.runId === undefined ? {} : { runId: event.data.runId },
|
|
41
|
+
...event.data.messageId === undefined ? {} : { messageId: event.data.messageId },
|
|
38
42
|
};
|
|
39
43
|
},
|
|
40
44
|
update: context => context.state,
|
|
@@ -127,6 +131,86 @@ export const roomEventDefinition = {
|
|
|
127
131
|
update: context => context.state,
|
|
128
132
|
buildViewNode: context => viewNode(context, 'room-event'),
|
|
129
133
|
};
|
|
134
|
+
/** A room decision: one single-event Context per `room/decision`. */
|
|
135
|
+
export const roomDecisionDefinition = {
|
|
136
|
+
kind: 'room-decision',
|
|
137
|
+
target: 'chat',
|
|
138
|
+
match: event => event.type === 'room/decision' ? { id: event.data.id, role: 'start' } : null,
|
|
139
|
+
start: (_context, match) => {
|
|
140
|
+
const event = match.event;
|
|
141
|
+
if (event.type !== 'room/decision')
|
|
142
|
+
throw new Error('room-decision start requires a room/decision event');
|
|
143
|
+
return { seq: event.seq, time: event.time, decision: event.data };
|
|
144
|
+
},
|
|
145
|
+
update: context => context.state,
|
|
146
|
+
buildViewNode: context => viewNode(context, 'room-decision'),
|
|
147
|
+
};
|
|
148
|
+
/**
|
|
149
|
+
* A member's tool approval: one Context per approval, started by
|
|
150
|
+
* `room/approval` and settled in place by `room/approval-resolved`.
|
|
151
|
+
*/
|
|
152
|
+
export const roomApprovalDefinition = {
|
|
153
|
+
kind: 'room-approval',
|
|
154
|
+
target: 'chat',
|
|
155
|
+
match: (event) => {
|
|
156
|
+
switch (event.type) {
|
|
157
|
+
case 'room/approval':
|
|
158
|
+
return { id: event.data.id, role: 'start' };
|
|
159
|
+
case 'room/approval-resolved':
|
|
160
|
+
return { id: event.data.id, role: 'update' };
|
|
161
|
+
default:
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
start: (_context, match) => {
|
|
166
|
+
const event = match.event;
|
|
167
|
+
if (event.type !== 'room/approval')
|
|
168
|
+
throw new Error('room-approval start requires a room/approval event');
|
|
169
|
+
return {
|
|
170
|
+
seq: event.seq, time: event.time, approvalId: event.data.id, member: event.data.member, tool: event.data.tool,
|
|
171
|
+
...event.data.reason === undefined ? {} : { reason: event.data.reason },
|
|
172
|
+
state: 'pending',
|
|
173
|
+
};
|
|
174
|
+
},
|
|
175
|
+
update: (context, match) => {
|
|
176
|
+
const event = match.event;
|
|
177
|
+
if (event.type !== 'room/approval-resolved')
|
|
178
|
+
return context.state;
|
|
179
|
+
return { ...context.state, state: event.data.outcome };
|
|
180
|
+
},
|
|
181
|
+
buildViewNode: context => viewNode(context, 'room-approval'),
|
|
182
|
+
};
|
|
183
|
+
/**
|
|
184
|
+
* A member's question card: one Context per card, started by `room/question`
|
|
185
|
+
* and settled in place (with the answers) by `room/question-resolved`.
|
|
186
|
+
*/
|
|
187
|
+
export const roomQuestionDefinition = {
|
|
188
|
+
kind: 'room-question',
|
|
189
|
+
target: 'chat',
|
|
190
|
+
match: (event) => {
|
|
191
|
+
switch (event.type) {
|
|
192
|
+
case 'room/question':
|
|
193
|
+
return { id: event.data.id, role: 'start' };
|
|
194
|
+
case 'room/question-resolved':
|
|
195
|
+
return { id: event.data.id, role: 'update' };
|
|
196
|
+
default:
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
start: (_context, match) => {
|
|
201
|
+
const event = match.event;
|
|
202
|
+
if (event.type !== 'room/question')
|
|
203
|
+
throw new Error('room-question start requires a room/question event');
|
|
204
|
+
return { seq: event.seq, time: event.time, questionId: event.data.id, member: event.data.member, questions: event.data.questions, state: 'pending' };
|
|
205
|
+
},
|
|
206
|
+
update: (context, match) => {
|
|
207
|
+
const event = match.event;
|
|
208
|
+
if (event.type !== 'room/question-resolved')
|
|
209
|
+
return context.state;
|
|
210
|
+
return { ...context.state, state: event.data.outcome, ...event.data.answers === undefined ? {} : { answers: event.data.answers } };
|
|
211
|
+
},
|
|
212
|
+
buildViewNode: context => viewNode(context, 'room-question'),
|
|
213
|
+
};
|
|
130
214
|
/**
|
|
131
215
|
* The relay Definition: one Context per relay (matched on the relay id),
|
|
132
216
|
* started by the `room/relay` event (pending) and updated by each
|
|
@@ -156,6 +240,7 @@ export const roomRelayDefinition = {
|
|
|
156
240
|
from: event.data.from,
|
|
157
241
|
to: event.data.to,
|
|
158
242
|
content: event.data.content,
|
|
243
|
+
...event.data.reason === undefined ? {} : { reason: event.data.reason },
|
|
159
244
|
state: 'pending',
|
|
160
245
|
};
|
|
161
246
|
},
|
|
@@ -168,45 +253,131 @@ export const roomRelayDefinition = {
|
|
|
168
253
|
buildViewNode: context => viewNode(context, 'room-relay'),
|
|
169
254
|
};
|
|
170
255
|
/**
|
|
171
|
-
* The
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
* at the moment of completion — only when the task closes done: the dim
|
|
176
|
-
* advance line `✓ ada 完成了「API 定稿」── 目标进度 2/5`. (The goal progress
|
|
177
|
-
* suffix is computed by the renderer from the room store, not folded here.)
|
|
256
|
+
* The held-reports line: one Context per member (its gate verdicts), visible
|
|
257
|
+
* while the gate holds reports for it — 「📥 dsh 的收件箱里有 2 条回报,先攒着」
|
|
258
|
+
* with a 现在交给 button — and hidden once they are released. It moves to the
|
|
259
|
+
* latest hold, so it always sits after the reply that was held.
|
|
178
260
|
*/
|
|
179
|
-
export const
|
|
180
|
-
kind: 'room-
|
|
261
|
+
export const roomInboxDefinition = {
|
|
262
|
+
kind: 'room-inbox',
|
|
263
|
+
target: 'chat',
|
|
264
|
+
match: (event) => {
|
|
265
|
+
if (event.type !== 'room/report-gate' || event.data.verdict === 'deliver')
|
|
266
|
+
return null;
|
|
267
|
+
return { id: event.data.memberId, role: event.data.verdict === 'hold' ? 'start' : 'update' };
|
|
268
|
+
},
|
|
269
|
+
start: (context, match) => {
|
|
270
|
+
const event = match.event;
|
|
271
|
+
if (event.type !== 'room/report-gate')
|
|
272
|
+
throw new Error('room-inbox requires a room/report-gate event');
|
|
273
|
+
const previous = context.state?.held ?? [];
|
|
274
|
+
return {
|
|
275
|
+
seq: event.seq, time: event.time, member: event.data.member,
|
|
276
|
+
held: [...previous.filter(seq => seq !== event.data.dispatchSeq), event.data.dispatchSeq],
|
|
277
|
+
...event.data.probability === undefined ? {} : { probability: event.data.probability },
|
|
278
|
+
};
|
|
279
|
+
},
|
|
280
|
+
update: (context, match) => {
|
|
281
|
+
const event = match.event;
|
|
282
|
+
if (event.type !== 'room/report-gate' || context.state === undefined)
|
|
283
|
+
return context.state;
|
|
284
|
+
if (event.data.verdict === 'hold') {
|
|
285
|
+
return { ...context.state, seq: event.seq, time: event.time, held: [...context.state.held.filter(seq => seq !== event.data.dispatchSeq), event.data.dispatchSeq],
|
|
286
|
+
...event.data.probability === undefined ? {} : { probability: event.data.probability } };
|
|
287
|
+
}
|
|
288
|
+
return { ...context.state, held: context.state.held.filter(seq => seq !== event.data.dispatchSeq) };
|
|
289
|
+
},
|
|
290
|
+
buildViewNode: context => viewNode(context, 'room-inbox', context.state !== undefined && context.state.held.length > 0 ? 'visible' : 'hidden'),
|
|
291
|
+
};
|
|
292
|
+
/**
|
|
293
|
+
* A help thread in the asking room: one Context per thread, started by
|
|
294
|
+
* `room/help` and folded in place by its `room/help-message` and
|
|
295
|
+
* `room/help-state` events (one row whose state and messages update).
|
|
296
|
+
*/
|
|
297
|
+
export const roomHelpDefinition = {
|
|
298
|
+
kind: 'room-help',
|
|
181
299
|
target: 'chat',
|
|
182
300
|
match: (event) => {
|
|
183
301
|
switch (event.type) {
|
|
184
|
-
case 'room/
|
|
302
|
+
case 'room/help':
|
|
185
303
|
return { id: event.data.id, role: 'start' };
|
|
186
|
-
case 'room/
|
|
187
|
-
|
|
304
|
+
case 'room/help-message':
|
|
305
|
+
case 'room/help-state':
|
|
306
|
+
return { id: event.data.help, role: 'update' };
|
|
188
307
|
default:
|
|
189
308
|
return null;
|
|
190
309
|
}
|
|
191
310
|
},
|
|
192
311
|
start: (_context, match) => {
|
|
193
312
|
const event = match.event;
|
|
194
|
-
if (event.type !== 'room/
|
|
195
|
-
throw new Error('room-
|
|
196
|
-
return {
|
|
197
|
-
seq: event.seq,
|
|
198
|
-
time: event.time,
|
|
199
|
-
taskId: event.data.id,
|
|
200
|
-
member: event.data.member,
|
|
201
|
-
title: event.data.title,
|
|
202
|
-
status: event.data.status,
|
|
203
|
-
};
|
|
313
|
+
if (event.type !== 'room/help')
|
|
314
|
+
throw new Error('room-help start requires a room/help event');
|
|
315
|
+
return { seq: event.seq, time: event.time, help: { ...event.data, state: 'queued', since: event.time, messages: [], time: event.time } };
|
|
204
316
|
},
|
|
205
317
|
update: (context, match) => {
|
|
206
318
|
const event = match.event;
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
319
|
+
const help = context.state.help;
|
|
320
|
+
if (event.type === 'room/help-message') {
|
|
321
|
+
return { ...context.state, help: { ...help, messages: [...help.messages, { ...event.data, time: event.time }] } };
|
|
322
|
+
}
|
|
323
|
+
if (event.type === 'room/help-state') {
|
|
324
|
+
const { error: _previous, ...rest } = help;
|
|
325
|
+
return { ...context.state, help: { ...rest, state: event.data.state, since: help.state === event.data.state ? help.since : event.time, ...event.data.error === undefined ? {} : { error: event.data.error } } };
|
|
326
|
+
}
|
|
327
|
+
return context.state;
|
|
328
|
+
},
|
|
329
|
+
buildViewNode: context => viewNode(context, 'room-help'),
|
|
330
|
+
};
|
|
331
|
+
/** A message source's help fields, when it is a room help source. */
|
|
332
|
+
function helpSourceOf(source) {
|
|
333
|
+
const value = source;
|
|
334
|
+
if (value?.kind !== 'room-help' || typeof value.help !== 'string' || typeof value.room !== 'string')
|
|
335
|
+
return undefined;
|
|
336
|
+
const text = (key) => typeof value[key] === 'string' ? value[key] : '';
|
|
337
|
+
return { help: value.help, room: value.room, roomTitle: text('roomTitle'), from: text('from'), op: value.op === 'message' ? 'message' : 'request', text: text('text') };
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* A help request in the helper's session: the `user/message` the room queued
|
|
341
|
+
* there (its `room-help` source) renders as a card naming the asking room
|
|
342
|
+
* instead of a plain injected-context row.
|
|
343
|
+
*/
|
|
344
|
+
export const roomHelpRequestDefinition = {
|
|
345
|
+
kind: 'room-help-request',
|
|
346
|
+
target: 'chat',
|
|
347
|
+
match: (event) => {
|
|
348
|
+
if (event.type !== 'user/message' || !isAppendSurfaceEvent(event) || helpSourceOf(event.data.source) === undefined)
|
|
349
|
+
return null;
|
|
350
|
+
return { id: String(event.seq), role: 'start' };
|
|
351
|
+
},
|
|
352
|
+
start: (_context, match) => {
|
|
353
|
+
const event = match.event;
|
|
354
|
+
const source = event.type === 'user/message' ? helpSourceOf(event.data.source) : undefined;
|
|
355
|
+
if (source === undefined)
|
|
356
|
+
throw new Error('room-help-request start requires a room-help message');
|
|
357
|
+
return { seq: event.seq, time: event.time, ...source };
|
|
210
358
|
},
|
|
211
|
-
|
|
359
|
+
update: context => context.state,
|
|
360
|
+
buildViewNode: context => viewNode(context, 'room-help-request'),
|
|
361
|
+
};
|
|
362
|
+
/**
|
|
363
|
+
* Another room asked this room for help (`room/help-in`): the same request
|
|
364
|
+
* card, naming the member it went to (and that it waits while this room is
|
|
365
|
+
* paused), with a jump back to the asking room.
|
|
366
|
+
*/
|
|
367
|
+
export const roomHelpInDefinition = {
|
|
368
|
+
kind: 'room-help-in',
|
|
369
|
+
target: 'chat',
|
|
370
|
+
match: event => event.type === 'room/help-in' ? { id: String(event.seq), role: 'start' } : null,
|
|
371
|
+
start: (_context, match) => {
|
|
372
|
+
const event = match.event;
|
|
373
|
+
if (event.type !== 'room/help-in')
|
|
374
|
+
throw new Error('room-help-in start requires a room/help-in event');
|
|
375
|
+
const data = event.data;
|
|
376
|
+
return {
|
|
377
|
+
seq: event.seq, time: event.time, help: data.id, room: data.room, roomTitle: data.roomTitle, from: data.from,
|
|
378
|
+
op: data.op, text: data.text, member: data.member, ...data.held === true ? { held: true } : {},
|
|
379
|
+
};
|
|
380
|
+
},
|
|
381
|
+
update: context => context.state,
|
|
382
|
+
buildViewNode: context => viewNode(context, 'room-help-request'),
|
|
212
383
|
};
|