@schoolai/shipyard-mcp 0.1.0-next.433

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.
@@ -0,0 +1,284 @@
1
+ import {
2
+ InputRequestSchema,
3
+ YDOC_KEYS,
4
+ createInputRequest,
5
+ logPlanEvent
6
+ } from "./chunk-LTC26IRQ.js";
7
+ import {
8
+ logger
9
+ } from "./chunk-GSGLHRWX.js";
10
+
11
+ // src/services/input-request-manager.ts
12
+ function formatDuration(totalSeconds) {
13
+ const minutes = Math.floor(totalSeconds / 60);
14
+ const seconds = totalSeconds % 60;
15
+ if (minutes === 0) {
16
+ return `${seconds} second${seconds === 1 ? "" : "s"}`;
17
+ }
18
+ const minutePart = `${minutes} minute${minutes === 1 ? "" : "s"}`;
19
+ if (seconds === 0) {
20
+ return minutePart;
21
+ }
22
+ const secondPart = `${seconds} second${seconds === 1 ? "" : "s"}`;
23
+ return `${minutePart} ${secondPart}`;
24
+ }
25
+ var InputRequestManager = class {
26
+ /**
27
+ * Create a new input request in the Y.Doc.
28
+ * Request is added to the INPUT_REQUESTS array and becomes visible in browser UI.
29
+ *
30
+ * @param ydoc - The Y.Doc to add the request to
31
+ * @param params - Request parameters (message, type, options, etc.)
32
+ * @returns The generated request ID
33
+ */
34
+ createRequest(ydoc, params) {
35
+ const request = createInputRequest(params);
36
+ ydoc.transact(() => {
37
+ const requestsArray = ydoc.getArray(YDOC_KEYS.INPUT_REQUESTS);
38
+ requestsArray.push([request]);
39
+ logPlanEvent(ydoc, "input_request_created", "Agent", {
40
+ requestId: request.id,
41
+ requestType: request.type,
42
+ requestMessage: request.message
43
+ });
44
+ });
45
+ logger.info(
46
+ { requestId: request.id, type: request.type, timeout: request.timeout },
47
+ "Created input request in Y.Doc"
48
+ );
49
+ return request.id;
50
+ }
51
+ /**
52
+ * Wait for a user to respond to an input request.
53
+ * Blocks until the request is answered, cancelled, or times out.
54
+ *
55
+ * Pattern: Based on waitForReviewDecision from review-status.ts
56
+ * - Observes Y.Doc changes via Y.Array observer
57
+ * - Polls for status changes to the specific request
58
+ * - Unsubscribes and cleans up on completion
59
+ *
60
+ * @param ydoc - The Y.Doc containing the request
61
+ * @param requestId - The ID of the request to wait for
62
+ * @param timeoutSeconds - Max time to wait (0 = no timeout, uses request.timeout if not specified)
63
+ * @returns Promise that resolves when request is answered/cancelled
64
+ */
65
+ async waitForResponse(ydoc, requestId, timeoutSeconds) {
66
+ return new Promise((resolve) => {
67
+ const requestsArray = ydoc.getArray(YDOC_KEYS.INPUT_REQUESTS);
68
+ let resolved = false;
69
+ let timeoutHandle;
70
+ let observerFn;
71
+ const findRequest = () => {
72
+ const requests = requestsArray.toJSON();
73
+ return requests.find((r) => r.id === requestId);
74
+ };
75
+ const cleanup = () => {
76
+ if (observerFn) {
77
+ requestsArray.unobserve(observerFn);
78
+ observerFn = void 0;
79
+ }
80
+ if (timeoutHandle) {
81
+ clearTimeout(timeoutHandle);
82
+ timeoutHandle = void 0;
83
+ }
84
+ if (!resolved) {
85
+ resolved = true;
86
+ }
87
+ };
88
+ const checkStatus = () => {
89
+ if (resolved) return;
90
+ const request2 = findRequest();
91
+ if (!request2) {
92
+ handleRequestNotFound();
93
+ return;
94
+ }
95
+ logger.debug({ requestId, status: request2.status }, "Checking input request status");
96
+ if (request2.status === "answered") {
97
+ handleAnsweredStatus(request2);
98
+ } else if (request2.status === "declined") {
99
+ handleDeclinedStatus();
100
+ } else if (request2.status === "cancelled") {
101
+ handleCancelledStatus();
102
+ }
103
+ };
104
+ const handleRequestNotFound = () => {
105
+ logger.warn({ requestId }, "Request not found, treating as cancelled");
106
+ resolved = true;
107
+ cleanup();
108
+ resolve({
109
+ success: false,
110
+ status: "cancelled",
111
+ reason: "Request not found in Y.Doc"
112
+ });
113
+ };
114
+ const handleAnsweredStatus = (request2) => {
115
+ logger.info({ requestId, answeredBy: request2.answeredBy }, "Input request answered");
116
+ resolved = true;
117
+ cleanup();
118
+ resolve({
119
+ success: true,
120
+ response: request2.response,
121
+ status: "answered",
122
+ answeredBy: request2.answeredBy ?? "unknown",
123
+ answeredAt: request2.answeredAt ?? Date.now()
124
+ });
125
+ };
126
+ const handleDeclinedStatus = () => {
127
+ logger.info({ requestId }, "Input request declined by user");
128
+ resolved = true;
129
+ cleanup();
130
+ resolve({
131
+ success: true,
132
+ status: "declined",
133
+ reason: "User declined to answer"
134
+ });
135
+ };
136
+ const handleCancelledStatus = () => {
137
+ logger.info({ requestId }, "Input request cancelled (timeout)");
138
+ resolved = true;
139
+ cleanup();
140
+ resolve({
141
+ success: false,
142
+ status: "cancelled",
143
+ reason: "Request timed out"
144
+ });
145
+ };
146
+ observerFn = () => {
147
+ checkStatus();
148
+ };
149
+ checkStatus();
150
+ if (resolved) {
151
+ return;
152
+ }
153
+ requestsArray.observe(observerFn);
154
+ const request = findRequest();
155
+ const effectiveTimeout = timeoutSeconds !== void 0 ? timeoutSeconds : request?.timeout !== void 0 ? request.timeout : 0;
156
+ const handleTimeout = () => {
157
+ if (resolved) return;
158
+ logger.warn({ requestId, timeout: effectiveTimeout }, "Input request timed out");
159
+ markRequestAsCancelled();
160
+ if (resolved) return;
161
+ resolved = true;
162
+ cleanup();
163
+ const timeStr = formatDuration(effectiveTimeout);
164
+ resolve({
165
+ success: false,
166
+ status: "cancelled",
167
+ reason: `Request timed out after ${timeStr}. The user likely didn't see the request in time. Please try again.`
168
+ });
169
+ };
170
+ const markRequestAsCancelled = () => {
171
+ ydoc.transact(() => {
172
+ if (resolved) return;
173
+ const currentRequest = findRequest();
174
+ if (!currentRequest || currentRequest.status !== "pending") {
175
+ return;
176
+ }
177
+ const requests = requestsArray.toJSON();
178
+ const index = requests.findIndex((r) => r.id === requestId);
179
+ if (index !== -1) {
180
+ requestsArray.delete(index, 1);
181
+ requestsArray.insert(index, [{ ...currentRequest, status: "cancelled" }]);
182
+ }
183
+ });
184
+ };
185
+ if (effectiveTimeout > 0) {
186
+ timeoutHandle = setTimeout(handleTimeout, effectiveTimeout * 1e3);
187
+ }
188
+ });
189
+ }
190
+ /**
191
+ * Cancel a pending input request.
192
+ * Marks the request as cancelled in the Y.Doc.
193
+ *
194
+ * @param ydoc - The Y.Doc containing the request
195
+ * @param requestId - The ID of the request to cancel
196
+ * @returns True if request was found and cancelled, false otherwise
197
+ */
198
+ cancelRequest(ydoc, requestId) {
199
+ let cancelled = false;
200
+ ydoc.transact(() => {
201
+ const requestsArray = ydoc.getArray(YDOC_KEYS.INPUT_REQUESTS);
202
+ const requests = requestsArray.toJSON();
203
+ const index = requests.findIndex((r) => r.id === requestId);
204
+ if (index !== -1) {
205
+ const request = requests[index];
206
+ if (request.status === "pending") {
207
+ requestsArray.delete(index, 1);
208
+ requestsArray.insert(index, [{ ...request, status: "cancelled" }]);
209
+ cancelled = true;
210
+ logger.info({ requestId }, "Cancelled input request");
211
+ } else {
212
+ logger.debug({ requestId, status: request.status }, "Request not pending, cannot cancel");
213
+ }
214
+ } else {
215
+ logger.warn({ requestId }, "Request not found for cancellation");
216
+ }
217
+ });
218
+ return cancelled;
219
+ }
220
+ /**
221
+ * Get the current state of an input request.
222
+ * Returns undefined if the request doesn't exist.
223
+ *
224
+ * @param ydoc - The Y.Doc containing the request
225
+ * @param requestId - The ID of the request to retrieve
226
+ * @returns The request object, or undefined if not found
227
+ */
228
+ getRequest(ydoc, requestId) {
229
+ const requestsArray = ydoc.getArray(YDOC_KEYS.INPUT_REQUESTS);
230
+ const requests = requestsArray.toJSON();
231
+ const request = requests.find((r) => r.id === requestId);
232
+ if (request) {
233
+ const parseResult = InputRequestSchema.safeParse(request);
234
+ if (parseResult.success) {
235
+ return parseResult.data;
236
+ }
237
+ logger.warn({ requestId, error: parseResult.error }, "Invalid request data in Y.Doc");
238
+ }
239
+ return void 0;
240
+ }
241
+ /**
242
+ * Get all pending input requests for a Y.Doc.
243
+ * Useful for UI to display all active requests.
244
+ *
245
+ * @param ydoc - The Y.Doc to query
246
+ * @returns Array of pending requests
247
+ */
248
+ getPendingRequests(ydoc) {
249
+ const requestsArray = ydoc.getArray(YDOC_KEYS.INPUT_REQUESTS);
250
+ const requests = requestsArray.toJSON();
251
+ return requests.filter((r) => r.status === "pending");
252
+ }
253
+ /**
254
+ * Clean up old completed/cancelled requests from Y.Doc.
255
+ * Removes requests older than the specified age to prevent unbounded growth.
256
+ *
257
+ * @param ydoc - The Y.Doc to clean up
258
+ * @param maxAgeMs - Maximum age in milliseconds (default: 24 hours)
259
+ * @returns Number of requests removed
260
+ */
261
+ cleanupOldRequests(ydoc, maxAgeMs = 24 * 60 * 60 * 1e3) {
262
+ let removed = 0;
263
+ const cutoff = Date.now() - maxAgeMs;
264
+ ydoc.transact(() => {
265
+ const requestsArray = ydoc.getArray(YDOC_KEYS.INPUT_REQUESTS);
266
+ const requests = requestsArray.toJSON();
267
+ for (let i = requests.length - 1; i >= 0; i--) {
268
+ const request = requests[i];
269
+ if (request.status !== "pending" && (request.answeredAt ?? request.createdAt) < cutoff) {
270
+ requestsArray.delete(i, 1);
271
+ removed++;
272
+ }
273
+ }
274
+ });
275
+ if (removed > 0) {
276
+ logger.info({ removed, maxAgeMs }, "Cleaned up old input requests");
277
+ }
278
+ return removed;
279
+ }
280
+ };
281
+
282
+ export {
283
+ InputRequestManager
284
+ };
@@ -0,0 +1,409 @@
1
+ import {
2
+ A2ADataPartSchema,
3
+ A2AFilePartSchema,
4
+ A2AMessageSchema,
5
+ A2APartSchema,
6
+ A2ATextPartSchema,
7
+ AgentActivityDataSchema,
8
+ AgentActivityTypes,
9
+ AgentPresenceSchema,
10
+ ArtifactSchema,
11
+ ChangeSchema,
12
+ ChangeTypeSchema,
13
+ ChangesResponseSchema,
14
+ ChunkMessageSchema,
15
+ ClaudeCodeMessageSchema,
16
+ ClaudeCodeOriginMetadataSchema,
17
+ ConversationExportEndSchema,
18
+ ConversationExportMetaSchema,
19
+ ConversationExportStartMetaSchema,
20
+ ConversationVersionSchema,
21
+ CreateHookSessionRequestSchema,
22
+ CreateHookSessionResponseSchema,
23
+ CreateSubscriptionRequestSchema,
24
+ CreateSubscriptionResponseSchema,
25
+ CursorOriginMetadataSchema,
26
+ DeleteSubscriptionResponseSchema,
27
+ DeliverableSchema,
28
+ DevinOriginMetadataSchema,
29
+ GetReviewStatusResponseSchema,
30
+ GitHubPRResponseSchema,
31
+ HasConnectionsResponseSchema,
32
+ HookApiErrorSchema,
33
+ ImportConversationRequestSchema,
34
+ ImportConversationResponseSchema,
35
+ InputRequestSchema,
36
+ InputRequestStatusValues,
37
+ InputRequestTypeValues,
38
+ InviteRedemptionSchema,
39
+ InviteTokenSchema,
40
+ LinkedPRSchema,
41
+ LinkedPRStatusValues,
42
+ NON_PLAN_DB_NAMES,
43
+ OriginMetadataSchema,
44
+ OriginPlatformValues,
45
+ P2PMessageType,
46
+ PLAN_INDEX_DOC_NAME,
47
+ PLAN_INDEX_EVENT_VIEWED_BY_KEY,
48
+ PLAN_INDEX_VIEWED_BY_KEY,
49
+ PRReviewCommentSchema,
50
+ PlanEventSchema,
51
+ PlanEventTypes,
52
+ PlanIdSchema,
53
+ PlanIndexEntrySchema,
54
+ PlanMetadataSchema,
55
+ PlanSnapshotSchema,
56
+ PlanStatusResponseSchema,
57
+ PlanStatusValues,
58
+ PlanViewTabValues,
59
+ ROUTES,
60
+ RegisterServerRequestSchema,
61
+ RegisterServerResponseSchema,
62
+ ReviewCommentSchema,
63
+ ReviewFeedbackSchema,
64
+ SetSessionTokenRequestSchema,
65
+ SetSessionTokenResponseSchema,
66
+ SubscriptionClientIdSchema,
67
+ ThreadCommentSchema,
68
+ ThreadSchema,
69
+ UnregisterServerRequestSchema,
70
+ UnregisterServerResponseSchema,
71
+ UpdatePlanContentRequestSchema,
72
+ UpdatePlanContentResponseSchema,
73
+ UpdatePresenceRequestSchema,
74
+ UpdatePresenceResponseSchema,
75
+ VALID_STATUS_TRANSITIONS,
76
+ YDOC_KEYS,
77
+ a2aToClaudeCode,
78
+ addArtifact,
79
+ addConversationVersion,
80
+ addDeliverable,
81
+ addPRReviewComment,
82
+ addPlanTag,
83
+ addSnapshot,
84
+ answerInputRequest,
85
+ appRouter,
86
+ approveUser,
87
+ archivePlan,
88
+ asAwarenessClientId,
89
+ asGitHubUsername,
90
+ asPlanId,
91
+ asWebRTCPeerId,
92
+ assertNever,
93
+ assertNeverP2PMessage,
94
+ buildInviteUrl,
95
+ cancelInputRequest,
96
+ claudeCodeToA2A,
97
+ clearAgentPresence,
98
+ clearEventViewedBy,
99
+ clearPlanIndexViewedBy,
100
+ conversationRouter,
101
+ createGitHubArtifact,
102
+ createHandedOffConversationVersion,
103
+ createInitialConversationVersion,
104
+ createInputRequest,
105
+ createLinkedPR,
106
+ createLocalArtifact,
107
+ createPlanSnapshot,
108
+ createPlanUrl,
109
+ createPlanUrlWithHistory,
110
+ createUserResolver,
111
+ decodeChunkMessage,
112
+ decodeExportEndMessage,
113
+ decodeExportStartMessage,
114
+ decodeP2PMessage,
115
+ decodePlan,
116
+ encodeChunkMessage,
117
+ encodeExportEndMessage,
118
+ encodeExportStartMessage,
119
+ encodePlan,
120
+ extractDeliverables,
121
+ extractMentions,
122
+ extractTextFromCommentBody,
123
+ formatAsClaudeCodeJSONL,
124
+ formatDeliverablesForLLM,
125
+ formatThreadsForLLM,
126
+ getAgentPresence,
127
+ getAgentPresences,
128
+ getAllEventViewedByForPlan,
129
+ getAllTagsFromIndex,
130
+ getAllViewedByFromIndex,
131
+ getApprovedUsers,
132
+ getArtifactUrl,
133
+ getArtifacts,
134
+ getConversationVersions,
135
+ getDeliverables,
136
+ getLatestSnapshot,
137
+ getLinkedPR,
138
+ getLinkedPRs,
139
+ getPRReviewComments,
140
+ getPRReviewCommentsForPR,
141
+ getPlanEvents,
142
+ getPlanFromUrl,
143
+ getPlanIndex,
144
+ getPlanIndexEntry,
145
+ getPlanMetadata,
146
+ getPlanMetadataWithValidation,
147
+ getPlanOwnerId,
148
+ getRejectedUsers,
149
+ getSnapshots,
150
+ getStepCompletions,
151
+ getTokenTimeRemaining,
152
+ getViewedBy,
153
+ getViewedByFromIndex,
154
+ hookRouter,
155
+ initPlanMetadata,
156
+ isApprovalRequired,
157
+ isConversationChunk,
158
+ isConversationExportEnd,
159
+ isConversationExportStart,
160
+ isEventUnread,
161
+ isInboxWorthy,
162
+ isP2PConversationMessage,
163
+ isPlanUnread,
164
+ isStepCompleted,
165
+ isThread,
166
+ isUrlEncodedPlanV1,
167
+ isUrlEncodedPlanV2,
168
+ isUserApproved,
169
+ isUserRejected,
170
+ isValidYDocKey,
171
+ linkArtifactToDeliverable,
172
+ linkPR,
173
+ logPlanEvent,
174
+ markEventAsViewed,
175
+ markPlanAsViewed,
176
+ markVersionHandedOff,
177
+ parseClaudeCodeOrigin,
178
+ parseClaudeCodeTranscriptString,
179
+ parseInviteFromUrl,
180
+ parseThreads,
181
+ planRouter,
182
+ rejectUser,
183
+ removeArtifact,
184
+ removePRReviewComment,
185
+ removePlanIndexEntry,
186
+ removePlanTag,
187
+ removeViewedByFromIndex,
188
+ resolvePRReviewComment,
189
+ revokeUser,
190
+ setAgentPresence,
191
+ setPlanIndexEntry,
192
+ setPlanMetadata,
193
+ subscriptionRouter,
194
+ summarizeA2AConversation,
195
+ toggleStepCompletion,
196
+ touchPlanIndexEntry,
197
+ transitionPlanStatus,
198
+ unarchivePlan,
199
+ unlinkPR,
200
+ unrejectUser,
201
+ updateLinkedPRStatus,
202
+ updatePlanIndexViewedBy,
203
+ validateA2AMessages
204
+ } from "./chunk-LTC26IRQ.js";
205
+ import "./chunk-JSBRDJBE.js";
206
+ export {
207
+ A2ADataPartSchema,
208
+ A2AFilePartSchema,
209
+ A2AMessageSchema,
210
+ A2APartSchema,
211
+ A2ATextPartSchema,
212
+ AgentActivityDataSchema,
213
+ AgentActivityTypes,
214
+ AgentPresenceSchema,
215
+ ArtifactSchema,
216
+ ChangeSchema,
217
+ ChangeTypeSchema,
218
+ ChangesResponseSchema,
219
+ ChunkMessageSchema,
220
+ ClaudeCodeMessageSchema,
221
+ ClaudeCodeOriginMetadataSchema,
222
+ ConversationExportEndSchema,
223
+ ConversationExportMetaSchema,
224
+ ConversationExportStartMetaSchema,
225
+ ConversationVersionSchema,
226
+ CreateHookSessionRequestSchema,
227
+ CreateHookSessionResponseSchema,
228
+ CreateSubscriptionRequestSchema,
229
+ CreateSubscriptionResponseSchema,
230
+ CursorOriginMetadataSchema,
231
+ DeleteSubscriptionResponseSchema,
232
+ DeliverableSchema,
233
+ DevinOriginMetadataSchema,
234
+ GetReviewStatusResponseSchema,
235
+ GitHubPRResponseSchema,
236
+ HasConnectionsResponseSchema,
237
+ HookApiErrorSchema,
238
+ ImportConversationRequestSchema,
239
+ ImportConversationResponseSchema,
240
+ InputRequestSchema,
241
+ InputRequestStatusValues,
242
+ InputRequestTypeValues,
243
+ InviteRedemptionSchema,
244
+ InviteTokenSchema,
245
+ LinkedPRSchema,
246
+ LinkedPRStatusValues,
247
+ NON_PLAN_DB_NAMES,
248
+ OriginMetadataSchema,
249
+ OriginPlatformValues,
250
+ P2PMessageType,
251
+ PLAN_INDEX_DOC_NAME,
252
+ PLAN_INDEX_EVENT_VIEWED_BY_KEY,
253
+ PLAN_INDEX_VIEWED_BY_KEY,
254
+ PRReviewCommentSchema,
255
+ PlanEventSchema,
256
+ PlanEventTypes,
257
+ PlanIdSchema,
258
+ PlanIndexEntrySchema,
259
+ PlanMetadataSchema,
260
+ PlanSnapshotSchema,
261
+ PlanStatusResponseSchema,
262
+ PlanStatusValues,
263
+ PlanViewTabValues,
264
+ ROUTES,
265
+ RegisterServerRequestSchema,
266
+ RegisterServerResponseSchema,
267
+ ReviewCommentSchema,
268
+ ReviewFeedbackSchema,
269
+ SetSessionTokenRequestSchema,
270
+ SetSessionTokenResponseSchema,
271
+ SubscriptionClientIdSchema,
272
+ ThreadCommentSchema,
273
+ ThreadSchema,
274
+ UnregisterServerRequestSchema,
275
+ UnregisterServerResponseSchema,
276
+ UpdatePlanContentRequestSchema,
277
+ UpdatePlanContentResponseSchema,
278
+ UpdatePresenceRequestSchema,
279
+ UpdatePresenceResponseSchema,
280
+ VALID_STATUS_TRANSITIONS,
281
+ YDOC_KEYS,
282
+ a2aToClaudeCode,
283
+ addArtifact,
284
+ addConversationVersion,
285
+ addDeliverable,
286
+ addPRReviewComment,
287
+ addPlanTag,
288
+ addSnapshot,
289
+ answerInputRequest,
290
+ appRouter,
291
+ approveUser,
292
+ archivePlan,
293
+ asAwarenessClientId,
294
+ asGitHubUsername,
295
+ asPlanId,
296
+ asWebRTCPeerId,
297
+ assertNever,
298
+ assertNeverP2PMessage,
299
+ buildInviteUrl,
300
+ cancelInputRequest,
301
+ claudeCodeToA2A,
302
+ clearAgentPresence,
303
+ clearEventViewedBy,
304
+ clearPlanIndexViewedBy,
305
+ conversationRouter,
306
+ createGitHubArtifact,
307
+ createHandedOffConversationVersion,
308
+ createInitialConversationVersion,
309
+ createInputRequest,
310
+ createLinkedPR,
311
+ createLocalArtifact,
312
+ createPlanSnapshot,
313
+ createPlanUrl,
314
+ createPlanUrlWithHistory,
315
+ createUserResolver,
316
+ decodeChunkMessage,
317
+ decodeExportEndMessage,
318
+ decodeExportStartMessage,
319
+ decodeP2PMessage,
320
+ decodePlan,
321
+ encodeChunkMessage,
322
+ encodeExportEndMessage,
323
+ encodeExportStartMessage,
324
+ encodePlan,
325
+ extractDeliverables,
326
+ extractMentions,
327
+ extractTextFromCommentBody,
328
+ formatAsClaudeCodeJSONL,
329
+ formatDeliverablesForLLM,
330
+ formatThreadsForLLM,
331
+ getAgentPresence,
332
+ getAgentPresences,
333
+ getAllEventViewedByForPlan,
334
+ getAllTagsFromIndex,
335
+ getAllViewedByFromIndex,
336
+ getApprovedUsers,
337
+ getArtifactUrl,
338
+ getArtifacts,
339
+ getConversationVersions,
340
+ getDeliverables,
341
+ getLatestSnapshot,
342
+ getLinkedPR,
343
+ getLinkedPRs,
344
+ getPRReviewComments,
345
+ getPRReviewCommentsForPR,
346
+ getPlanEvents,
347
+ getPlanFromUrl,
348
+ getPlanIndex,
349
+ getPlanIndexEntry,
350
+ getPlanMetadata,
351
+ getPlanMetadataWithValidation,
352
+ getPlanOwnerId,
353
+ getRejectedUsers,
354
+ getSnapshots,
355
+ getStepCompletions,
356
+ getTokenTimeRemaining,
357
+ getViewedBy,
358
+ getViewedByFromIndex,
359
+ hookRouter,
360
+ initPlanMetadata,
361
+ isApprovalRequired,
362
+ isConversationChunk,
363
+ isConversationExportEnd,
364
+ isConversationExportStart,
365
+ isEventUnread,
366
+ isInboxWorthy,
367
+ isP2PConversationMessage,
368
+ isPlanUnread,
369
+ isStepCompleted,
370
+ isThread,
371
+ isUrlEncodedPlanV1,
372
+ isUrlEncodedPlanV2,
373
+ isUserApproved,
374
+ isUserRejected,
375
+ isValidYDocKey,
376
+ linkArtifactToDeliverable,
377
+ linkPR,
378
+ logPlanEvent,
379
+ markEventAsViewed,
380
+ markPlanAsViewed,
381
+ markVersionHandedOff,
382
+ parseClaudeCodeOrigin,
383
+ parseClaudeCodeTranscriptString,
384
+ parseInviteFromUrl,
385
+ parseThreads,
386
+ planRouter,
387
+ rejectUser,
388
+ removeArtifact,
389
+ removePRReviewComment,
390
+ removePlanIndexEntry,
391
+ removePlanTag,
392
+ removeViewedByFromIndex,
393
+ resolvePRReviewComment,
394
+ revokeUser,
395
+ setAgentPresence,
396
+ setPlanIndexEntry,
397
+ setPlanMetadata,
398
+ subscriptionRouter,
399
+ summarizeA2AConversation,
400
+ toggleStepCompletion,
401
+ touchPlanIndexEntry,
402
+ transitionPlanStatus,
403
+ unarchivePlan,
404
+ unlinkPR,
405
+ unrejectUser,
406
+ updateLinkedPRStatus,
407
+ updatePlanIndexViewedBy,
408
+ validateA2AMessages
409
+ };