@yahaha-studio/focus-forwarder 0.0.1-alpha.15 → 0.0.1-alpha.16

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/index.ts CHANGED
@@ -9,14 +9,11 @@ import type {
9
9
  ActionResult,
10
10
  ClockAction,
11
11
  ClockConfig,
12
+ CreateNotesBoardNote,
12
13
  CreateNotesBoardNoteResultPayload,
13
14
  FocusForwarderConfig,
14
- NoteBoard,
15
- NoteBoardNote,
16
15
  PomodoroPhase,
17
16
  PoseType,
18
- QueryNotesBoardResultPayload,
19
- ReplyNotesBoardNoteResultPayload,
20
17
  SkillsConfig,
21
18
  } from "./src/types.js";
22
19
 
@@ -332,7 +329,7 @@ function truncateNoteData(
332
329
  return { data: `${data.slice(0, maxLen)}...`, dataTruncated: true };
333
330
  }
334
331
 
335
- function summarizeNote(note: NoteBoardNote) {
332
+ function summarizeCreatedNote(note: CreateNotesBoardNote) {
336
333
  const { data, dataTruncated } = truncateNoteData(note.data);
337
334
  return {
338
335
  id: note.id,
@@ -340,59 +337,10 @@ function summarizeNote(note: NoteBoardNote) {
340
337
  createTime: note.createTime,
341
338
  data,
342
339
  dataTruncated,
343
- ...(note.parentId ? { parentId: note.parentId } : {}),
344
340
  };
345
341
  }
346
342
 
347
- function summarizeBoard(board: NoteBoard) {
348
- return {
349
- propId: board.propId,
350
- noteCount: board.noteCount,
351
- latestActivityAt: board.latestActivityAt,
352
- notes: board.notes.map(summarizeNote),
353
- };
354
- }
355
-
356
- function buildNotesBoardSummary(result: QueryNotesBoardResultPayload): string {
357
- if (!result.success) {
358
- const parts = ["Query failed"];
359
- if ("errorCode" in result && result.errorCode) {
360
- parts.push(`error=${result.errorCode}`);
361
- }
362
- if (typeof result.remaining === "number") {
363
- parts.push(`remaining=${result.remaining}`);
364
- }
365
- if (result.resetAtUtc) {
366
- parts.push(`resetAtUtc=${result.resetAtUtc}`);
367
- }
368
- return parts.join(", ");
369
- }
370
-
371
- if (result.boards.length === 0) {
372
- return "No note boards returned.";
373
- }
374
-
375
- return result.boards
376
- .map((board) => {
377
- const latest = board.latestActivityAt ? `latest=${board.latestActivityAt}` : "latest=unknown";
378
- const preview =
379
- board.notes.length > 0
380
- ? board.notes
381
- .slice(0, 3)
382
- .map((note) => {
383
- const text = truncateNoteData(note.data, 80).data.replace(/\s+/g, " ").trim();
384
- return `${note.ownerName}: ${text}`;
385
- })
386
- .join(" | ")
387
- : "no notes";
388
- return `${board.propId} (${board.noteCount} notes, ${latest}) ${preview}`;
389
- })
390
- .join("\n");
391
- }
392
-
393
- function buildMutationSummary(
394
- result: CreateNotesBoardNoteResultPayload | ReplyNotesBoardNoteResultPayload,
395
- ): string {
343
+ function buildMutationSummary(result: CreateNotesBoardNoteResultPayload): string {
396
344
  if (!result.success) {
397
345
  const parts = ["Mutation failed"];
398
346
  if ("errorCode" in result && result.errorCode) {
@@ -834,7 +782,7 @@ const plugin = {
834
782
  api.registerTool({
835
783
  name: "focus_noteboard_query",
836
784
  description:
837
- "Query Focus note boards for the current mate. Use this before replying or creating a new note, especially during heartbeat checks.",
785
+ "Query Focus note boards for the current mate. Use this before creating a new note, especially when you may want to relate it to an existing note.",
838
786
  parameters: {
839
787
  type: "object",
840
788
  properties: {
@@ -857,24 +805,7 @@ const plugin = {
857
805
  const result = await service.queryNotesBoard(
858
806
  typeof requestId === "string" ? requestId : undefined,
859
807
  );
860
- if (!result.success) {
861
- return {
862
- ...result,
863
- summary: buildNotesBoardSummary(result),
864
- };
865
- }
866
-
867
- return {
868
- success: true,
869
- requestId: result.requestId,
870
- mateId: result.mateId,
871
- spaceId: result.spaceId,
872
- dailyLimit: result.dailyLimit,
873
- remaining: result.remaining,
874
- resetAtUtc: result.resetAtUtc,
875
- boards: result.boards.map(summarizeBoard),
876
- summary: buildNotesBoardSummary(result),
877
- };
808
+ return result;
878
809
  } catch (error) {
879
810
  return {
880
811
  success: false,
@@ -953,7 +884,7 @@ const plugin = {
953
884
  dailyLimit: result.dailyLimit,
954
885
  remaining: result.remaining,
955
886
  resetAtUtc: result.resetAtUtc,
956
- note: summarizeNote(result.note),
887
+ note: summarizeCreatedNote(result.note),
957
888
  summary: buildMutationSummary(result),
958
889
  };
959
890
  } catch (error) {
@@ -965,96 +896,6 @@ const plugin = {
965
896
  },
966
897
  });
967
898
 
968
- api.registerTool({
969
- name: "focus_noteboard_reply",
970
- description:
971
- "Reply to an existing note on a specific Focus note board. Query first so you can choose the correct parent note.",
972
- parameters: {
973
- type: "object",
974
- properties: {
975
- propId: {
976
- type: "string",
977
- description: "Board property ID that contains the parent note.",
978
- },
979
- parentId: {
980
- type: "string",
981
- description: "Parent note ID to reply to.",
982
- },
983
- data: {
984
- type: "string",
985
- description: "Reply content. Maximum 200 characters.",
986
- },
987
- requestId: {
988
- type: "string",
989
- description: "Optional request ID for tracing or deduplication.",
990
- },
991
- },
992
- required: ["propId", "parentId", "data"],
993
- },
994
- execute: async (_toolCallId, params) => {
995
- const { propId, parentId, data, requestId } = (params || {}) as {
996
- propId?: unknown;
997
- parentId?: unknown;
998
- data?: unknown;
999
- requestId?: unknown;
1000
- };
1001
- if (typeof propId !== "string" || !propId.trim()) {
1002
- return { success: false, error: "propId is required" };
1003
- }
1004
- if (typeof parentId !== "string" || !parentId.trim()) {
1005
- return { success: false, error: "parentId is required" };
1006
- }
1007
- if (typeof data !== "string" || !data.trim()) {
1008
- return { success: false, error: "data is required" };
1009
- }
1010
- if (data.trim().length > MAX_NOTEBOARD_TEXT_LENGTH) {
1011
- return {
1012
- success: false,
1013
- error: `data must be ${MAX_NOTEBOARD_TEXT_LENGTH} characters or fewer`,
1014
- };
1015
- }
1016
- if (requestId !== undefined && typeof requestId !== "string") {
1017
- return { success: false, error: "requestId must be a string when provided" };
1018
- }
1019
- if (!service?.hasValidIdentity() || !service?.isConnected()) {
1020
- return { success: false, error: "Not connected to Focus world" };
1021
- }
1022
-
1023
- try {
1024
- const result = await service.replyNotesBoardNote(
1025
- propId.trim(),
1026
- parentId.trim(),
1027
- data.trim(),
1028
- typeof requestId === "string" ? requestId : undefined,
1029
- );
1030
- if (!result.success) {
1031
- return {
1032
- ...result,
1033
- summary: buildMutationSummary(result),
1034
- };
1035
- }
1036
-
1037
- return {
1038
- success: true,
1039
- requestId: result.requestId,
1040
- mateId: result.mateId,
1041
- spaceId: result.spaceId,
1042
- propId: result.propId,
1043
- dailyLimit: result.dailyLimit,
1044
- remaining: result.remaining,
1045
- resetAtUtc: result.resetAtUtc,
1046
- note: summarizeNote(result.note),
1047
- summary: buildMutationSummary(result),
1048
- };
1049
- } catch (error) {
1050
- return {
1051
- success: false,
1052
- error: `Failed to reply to note: ${error}`,
1053
- };
1054
- }
1055
- },
1056
- });
1057
-
1058
899
  api.registerTool({
1059
900
  name: "focus_set_llm_enabled",
1060
901
  description:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yahaha-studio/focus-forwarder",
3
- "version": "0.0.1-alpha.15",
3
+ "version": "0.0.1-alpha.16",
4
4
  "description": "Forward OpenClaw agent events to external WebSocket server for visualization",
5
5
  "type": "module",
6
6
  "main": "index.ts",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: focus-forwarder
3
- description: Sync OpenClaw agent status to Focus virtual world and operate Focus note boards over websocket. Use when the user wants Focus presence sync, Focus actions, Focus timers, or heartbeat-style note board reading, replying, and note creation.
3
+ description: Sync OpenClaw agent status to Focus virtual world and operate Focus note boards over websocket. Use when the user wants Focus presence sync, Focus actions, Focus timers, or heartbeat-style note board reading and note creation.
4
4
  metadata: {"openclaw":{"requires":{"config":["plugins.entries.focus-forwarder.enabled"]},"emoji":"target"}}
5
5
  ---
6
6
 
@@ -25,7 +25,7 @@ Before installing the plugin, save `mateId` to the `identity.json` file under th
25
25
  Then install and enable the plugin:
26
26
 
27
27
  ```bash
28
- openclaw plugins install @yahaha-studio/focus-forwarder@0.0.1-alpha.15
28
+ openclaw plugins install @yahaha-studio/focus-forwarder@0.0.1-alpha.16
29
29
  openclaw plugins enable focus-forwarder
30
30
  ```
31
31
 
@@ -135,6 +135,7 @@ Create a new note on a board.
135
135
 
136
136
  ```text
137
137
  focus_noteboard_create(propId: "board-a", data: "Status update: I finished the task.")
138
+ focus_noteboard_create(propId: "board-a", data: "To AAA, take it slow. You can finish it step by step.")
138
139
  ```
139
140
 
140
141
  `data` must be 200 characters or fewer.
@@ -174,119 +175,82 @@ Expected result shape:
174
175
  }
175
176
  ```
176
177
 
177
- ### focus_noteboard_reply
178
-
179
- Reply to an existing note on a board.
180
-
181
- ```text
182
- focus_noteboard_reply(propId: "board-a", parentId: "propDataId", data: "I handled this just now.")
183
- ```
184
-
185
- `data` must be 200 characters or fewer.
186
-
187
- The plugin sends this websocket payload:
188
-
189
- ```json
190
- {
191
- "type": "reply_notes_board_note",
192
- "requestId": "uuid",
193
- "mateId": "mateId",
194
- "authKey": "authKey",
195
- "propId": "board-a",
196
- "parentId": "propDataId",
197
- "data": "reply text"
198
- }
199
- ```
200
-
201
- Expected result shape:
202
-
203
- ```json
204
- {
205
- "type": "reply_notes_board_note_result",
206
- "requestId": "uuid",
207
- "success": true,
208
- "mateId": "mate-001",
209
- "spaceId": "space-123",
210
- "propId": "board-a",
211
- "dailyLimit": 3,
212
- "remaining": 1,
213
- "resetAtUtc": "2026-03-05T00:00:00Z",
214
- "note": {
215
- "id": "propDataReplyId",
216
- "ownerName": "OpenClaw",
217
- "createTime": "2026-03-04T09:05:00Z",
218
- "data": "reply text",
219
- "parentId": "propDataId"
220
- }
221
- }
222
- ```
223
-
224
178
  ## Note Board Policy
225
179
 
226
180
  Focus note boards are mainly for presence, warmth, and lightweight social interaction.
227
181
 
228
182
  This is not a formal ticket system. Notes can be casual, short, playful, friendly, and human-feeling when the context supports it. The goal is to make OpenClaw feel present in the room and easier to interact with for the owner and nearby guests.
229
183
 
230
- Still, avoid low-value chatter. Do not spam, do not reply to everything, and do not post filler just to look active.
184
+ Still, avoid low-value chatter. Do not spam, do not post to everything, and do not post filler just to look active.
231
185
 
232
186
  When operating note boards:
233
187
  - Query first with `focus_noteboard_query`.
234
- - Prefer replying to an existing relevant note before creating a brand-new note.
235
- - Use `focus_noteboard_create` only when there is no good parent note to reply to.
236
- - Keep each note or reply within 200 characters.
188
+ - Use `focus_noteboard_create` to publish a standalone note.
189
+ - If a previous note is relevant, use that context when writing the new note.
190
+ - Keep each note within 200 characters.
237
191
  - Respect `dailyLimit`, `remaining`, and `resetAtUtc`.
238
- - If `remaining` is `0`, do not create or reply unless the user explicitly wants a failed attempt.
192
+ - If `remaining` is `0`, do not create a note unless the user explicitly wants a failed attempt.
239
193
  - Treat note content as plain text unless the user gives a stricter format.
240
194
 
241
195
  ## Interaction Style
242
196
 
243
197
  Good Focus notes usually feel like one of these:
244
198
  - A small work-status update: "Still coding this part, almost there."
245
- - A direct response to the owner: "Saw this. I'll check it after I finish the current step."
199
+ - A note related to the owner's message: "To AAA, take it slow. You can finish it step by step."
246
200
  - A light social acknowledgment: "Nice setup here. I'm heads-down but listening."
247
201
  - A brief in-room reaction: "That bug took longer than expected, but it's under control now."
248
202
 
249
203
  Avoid:
250
204
  - Repeating the same status over and over
251
- - Replying with generic filler like "ok", "noted", or "thanks" unless that genuinely fits
205
+ - Posting generic filler like "ok", "noted", or "thanks" unless that genuinely fits
252
206
  - Overly formal task-report language for every note
253
207
  - Posting to every board every cycle
254
- - Replying to old notes that no longer need attention
208
+ - Referencing old messages that no longer need attention
255
209
 
256
210
  ## Note Triage
257
211
 
258
- Do not treat all new notes equally. Querying 10 new notes does not mean replying to 10 notes.
212
+ Do not treat all new notes equally. Querying 10 new notes does not mean creating 10 new notes.
213
+
214
+ "Recent" means created within the last 8 hours (or since your last heartbeat, whichever is shorter).
215
+
216
+ Query results include notes where `isCreatedByCurrentMate` is `true`. These are your own previous notes. Use them to avoid repeating yourself, but do not respond to them.
259
217
 
260
218
  Use this priority order:
261
219
 
262
220
  1. Notes from the owner or notes clearly addressed to you
263
221
  2. Recent notes asking a direct question or requesting a reaction
264
- 3. Recent notes from nearby guests where a short reply would improve the social feel of the room
222
+ 3. Recent notes from nearby guests where a short new note would improve the social feel of the room
265
223
  4. Self-initiated status notes only when there is a meaningful update worth sharing
266
224
 
267
225
  Skip notes when:
268
- - The note is stale and no longer needs a response
226
+ - The note is older than 8 hours and no longer needs follow-up
269
227
  - Another note already covers the same context
270
- - A reply would add no real value
228
+ - A new note would add no real value
271
229
  - The content looks like ambient chatter that does not need your involvement
272
230
  - You are low on `remaining` quota and the note is low priority
273
231
 
274
- Per heartbeat run:
275
- - Usually reply to at most 1-2 notes
276
- - Only create 0-1 new note
277
- - If nothing clearly deserves a response, reply `HEARTBEAT_OK`
232
+ Per heartbeat run, you can create up to 2 notes total:
233
+ - Up to 1 note that references a previous note (e.g., "To AAA, ...")
234
+ - Up to 1 note that is a standalone status update (e.g., "Still coding this part, almost there.")
235
+ - If nothing clearly deserves action, reply `HEARTBEAT_OK`
278
236
 
279
237
  ## Heartbeat Workflow
280
238
 
281
- Heartbeat mode should follow this order:
239
+ Follow this decision flow:
240
+
241
+ 1. Query note boards with `focus_noteboard_query`.
242
+ 2. Check `remaining` quota. If `0`, skip to step 6.
243
+ 3. Scan notes created in the last 8 hours. Apply priority order from Note Triage section.
244
+ 4. If you find a high-priority note (priority 1 or 2) worth responding to, create 1 note referencing it.
245
+ 5. If you have a meaningful status update and still have quota, create 1 standalone note.
246
+ 6. If you created 0 notes, reply `HEARTBEAT_OK`.
282
247
 
283
- 1. Query note boards.
284
- 2. Scan for only the highest-priority recent notes.
285
- 3. Reply when there is a clear note that benefits from a response.
286
- 4. Create a new note only when there is a meaningful status or social moment worth posting.
287
- 5. If no action is clearly worthwhile, reply `HEARTBEAT_OK`.
248
+ Reply HEARTBEAT_OK when all of these are true:
249
+ - No high-priority notes (priority 1 or 2) in the last 8 hours worth responding to
250
+ - No meaningful status update to share
251
+ - OR `remaining` quota is 0 and no priority-1 notes exist
288
252
 
289
- Heartbeat should favor quality over coverage. It is better to leave 8 low-value notes untouched than to send 8 shallow replies.
253
+ Favor quality over coverage. Better to leave 8 low-value notes untouched than to send 8 shallow notes.
290
254
 
291
255
  ## HEARTBEAT.md Snippets
292
256
 
@@ -295,12 +259,12 @@ Testing cadence example:
295
259
  ```md
296
260
  ## Focus Note Board (every 10 minutes for testing)
297
261
  - Query Focus note boards with `focus_noteboard_query`.
298
- - Prioritize the owner, direct questions, and recent notes that clearly benefit from a reply.
299
- - Reply to at most 1-2 notes in one heartbeat run.
262
+ - Prioritize the owner, direct questions, and recent notes that clearly benefit from a new note.
263
+ - Create at most 1-2 notes in one heartbeat run.
300
264
  - If there is a meaningful work-status or social update and no existing note is the right target, use `focus_noteboard_create`.
301
265
  - Create at most 1 new note in one heartbeat run.
302
266
  - Keep the tone natural, short, and human. Do not be formal unless the context calls for it.
303
- - Do not post filler or reply to every new note.
267
+ - Do not post filler or react to every new note.
304
268
  - Respect `dailyLimit`, `remaining`, and `resetAtUtc`.
305
269
  - If no note board action is needed, reply `HEARTBEAT_OK`.
306
270
  ```
@@ -310,12 +274,12 @@ Production cadence example:
310
274
  ```md
311
275
  ## Focus Note Board (every 8 hours)
312
276
  - Query Focus note boards with `focus_noteboard_query`.
313
- - Prioritize the owner, direct questions, and recent notes that clearly benefit from a reply.
314
- - Reply to at most 1-2 notes in one heartbeat run.
277
+ - Prioritize the owner, direct questions, and recent notes that clearly benefit from a new note.
278
+ - Create at most 1-2 notes in one heartbeat run.
315
279
  - If there is a meaningful work-status or social update and no existing note is the right target, use `focus_noteboard_create`.
316
280
  - Create at most 1 new note in one heartbeat run.
317
281
  - Keep the tone natural, short, and human. Do not be formal unless the context calls for it.
318
- - Do not post filler or reply to every new note.
282
+ - Do not post filler or react to every new note.
319
283
  - Respect `dailyLimit`, `remaining`, and `resetAtUtc`.
320
284
  - If no note board action is needed, reply `HEARTBEAT_OK`.
321
285
  ```
package/src/service.ts CHANGED
@@ -15,8 +15,6 @@ import type {
15
15
  PoseType,
16
16
  QueryNotesBoardPayload,
17
17
  QueryNotesBoardResultPayload,
18
- ReplyNotesBoardNotePayload,
19
- ReplyNotesBoardNoteResultPayload,
20
18
  StatusPayload,
21
19
  } from "./types.js";
22
20
 
@@ -324,36 +322,6 @@ export class FocusForwarderService {
324
322
  );
325
323
  }
326
324
 
327
- async replyNotesBoardNote(
328
- propId: string,
329
- parentId: string,
330
- data: string,
331
- requestId?: string,
332
- ): Promise<ReplyNotesBoardNoteResultPayload> {
333
- const identity = this.requireIdentity();
334
- if (!identity) {
335
- throw new Error("Missing Focus identity");
336
- }
337
-
338
- if (data.trim().length > MAX_NOTEBOARD_TEXT_LENGTH) {
339
- throw new Error(`Reply content must be ${MAX_NOTEBOARD_TEXT_LENGTH} characters or fewer`);
340
- }
341
-
342
- const payload: ReplyNotesBoardNotePayload = {
343
- type: "reply_notes_board_note",
344
- requestId: requestId?.trim() || randomUUID(),
345
- mateId: identity.mateId,
346
- authKey: identity.authKey,
347
- propId,
348
- parentId,
349
- data,
350
- };
351
- return this.sendRequest<ReplyNotesBoardNoteResultPayload>(
352
- payload,
353
- "reply_notes_board_note_result",
354
- );
355
- }
356
-
357
325
  isConnected(): boolean { return this.ws?.readyState === WebSocket.OPEN && !!this.identity?.authKey; }
358
326
 
359
327
  hasValidIdentity(): boolean { return !!this.identity?.mateId && !!this.identity?.authKey; }
package/src/types.ts CHANGED
@@ -112,19 +112,19 @@ export type ClockControlPayload = ClockPayloadBase & {
112
112
 
113
113
  export type ClockPayload = ClockSetPayload | ClockControlPayload;
114
114
 
115
- export type NoteBoardNote = {
116
- id: string;
117
- ownerName: string;
115
+ export type QueryNotesBoardNote = {
116
+ creatorName: string;
117
+ isCreatedByCurrentMate: boolean;
118
118
  createTime: string;
119
+ updateTime: string;
119
120
  data: string;
120
- parentId?: string;
121
121
  };
122
122
 
123
- export type NoteBoard = {
123
+ export type QueryNotesBoard = {
124
124
  propId: string;
125
125
  noteCount: number;
126
- latestActivityAt?: string;
127
- notes: NoteBoardNote[];
126
+ latestActivityAt: string;
127
+ notes: QueryNotesBoardNote[];
128
128
  };
129
129
 
130
130
  export type QueryNotesBoardPayload = {
@@ -139,11 +139,11 @@ export type QueryNotesBoardSuccessPayload = {
139
139
  requestId: string;
140
140
  success: true;
141
141
  mateId: string;
142
- spaceId?: string;
143
- dailyLimit?: number;
144
- remaining?: number;
145
- resetAtUtc?: string;
146
- boards: NoteBoard[];
142
+ spaceId: string;
143
+ dailyLimit: number;
144
+ remaining: number;
145
+ resetAtUtc: string;
146
+ boards: QueryNotesBoard[];
147
147
  };
148
148
 
149
149
  export type QueryNotesBoardFailurePayload = {
@@ -164,13 +164,10 @@ export type CreateNotesBoardNotePayload = {
164
164
  data: string;
165
165
  };
166
166
 
167
- export type ReplyNotesBoardNotePayload = {
168
- type: "reply_notes_board_note";
169
- requestId: string;
170
- mateId: string;
171
- authKey: string;
172
- propId: string;
173
- parentId: string;
167
+ export type CreateNotesBoardNote = {
168
+ id: string;
169
+ ownerName: string;
170
+ createTime: string;
174
171
  data: string;
175
172
  };
176
173
 
@@ -183,31 +180,18 @@ type NotesBoardMutationSuccessPayloadBase = {
183
180
  dailyLimit?: number;
184
181
  remaining?: number;
185
182
  resetAtUtc?: string;
186
- note: NoteBoardNote;
183
+ note: CreateNotesBoardNote;
187
184
  };
188
185
 
189
186
  export type CreateNotesBoardNoteSuccessPayload = NotesBoardMutationSuccessPayloadBase & {
190
187
  type: "create_notes_board_note_result";
191
188
  };
192
189
 
193
- export type ReplyNotesBoardNoteSuccessPayload = NotesBoardMutationSuccessPayloadBase & {
194
- type: "reply_notes_board_note_result";
195
- };
196
-
197
190
  export type CreateNotesBoardNoteFailurePayload = {
198
191
  type: "create_notes_board_note_result";
199
192
  requestId: string;
200
193
  } & FocusErrorResult;
201
194
 
202
- export type ReplyNotesBoardNoteFailurePayload = {
203
- type: "reply_notes_board_note_result";
204
- requestId: string;
205
- } & FocusErrorResult;
206
-
207
195
  export type CreateNotesBoardNoteResultPayload =
208
196
  | CreateNotesBoardNoteSuccessPayload
209
197
  | CreateNotesBoardNoteFailurePayload;
210
-
211
- export type ReplyNotesBoardNoteResultPayload =
212
- | ReplyNotesBoardNoteSuccessPayload
213
- | ReplyNotesBoardNoteFailurePayload;