| ... | @@ -88,6 +88,37 @@ const McpAuthMiddlewareLive = HttpRouter.middleware<{ | ... | @@ -88,6 +88,37 @@ const McpAuthMiddlewareLive = HttpRouter.middleware<{ |
| 88 | provides: McpInvocationContext.McpInvocationContext; | 88 | provides: McpInvocationContext.McpInvocationContext; |
| 89 | }>()(makeMcpAuthMiddleware).layer; | 89 | }>()(makeMcpAuthMiddleware).layer; |
| 90 | | 90 | |
| | 91 | const previewSnapshotFailure = <E>(cause: Cause.Cause<E>) => { |
| | 92 | if (Cause.hasInterrupts(cause) || cause.reasons.some(Cause.isDieReason)) { |
| | 93 | return Effect.failCause(cause).pipe(Effect.orDie); |
| | 94 | } |
| | 95 | const failures = cause.reasons.filter(Cause.isFailReason); |
| | 96 | const firstFailure = failures[0]?.error; |
| | 97 | const errorTag = |
| | 98 | typeof firstFailure === "object" && |
| | 99 | firstFailure !== null && |
| | 100 | "_tag" in firstFailure && |
| | 101 | typeof firstFailure._tag === "string" |
| | 102 | ? firstFailure._tag |
| | 103 | : "PreviewSnapshotError"; |
| | 104 | const result = new McpSchema.CallToolResult({ |
| | 105 | isError: true, |
| | 106 | structuredContent: { |
| | 107 | error: { |
| | 108 | _tag: errorTag, |
| | 109 | operation: "snapshot", |
| | 110 | failureCount: failures.length, |
| | 111 | }, |
| | 112 | }, |
| | 113 | content: [{ type: "text", text: "Preview snapshot failed." }], |
| | 114 | }); |
| | 115 | return Effect.logWarning("preview snapshot failed", { |
| | 116 | operation: "snapshot", |
| | 117 | errorTag, |
| | 118 | failureCount: failures.length, |
| | 119 | }).pipe(Effect.as(result)); |
| | 120 | }; |
| | 121 | |
| 91 | const registerPreviewSnapshot = Effect.fn("McpHttpServer.registerPreviewSnapshot")(function* () { | 122 | const registerPreviewSnapshot = Effect.fn("McpHttpServer.registerPreviewSnapshot")(function* () { |
| 92 | const server = yield* McpServer.McpServer; | 123 | const server = yield* McpServer.McpServer; |
| 93 | const broker = yield* PreviewAutomationBroker.PreviewAutomationBroker; | 124 | const broker = yield* PreviewAutomationBroker.PreviewAutomationBroker; |
| ... | @@ -122,12 +153,8 @@ const registerPreviewSnapshot = Effect.fn("McpHttpServer.registerPreviewSnapshot | ... | @@ -122,12 +153,8 @@ const registerPreviewSnapshot = Effect.fn("McpHttpServer.registerPreviewSnapshot |
| 122 | Effect.flatMap(Effect.fromOption), | 153 | Effect.flatMap(Effect.fromOption), |
| 123 | Effect.provideService(PreviewAutomationBroker.PreviewAutomationBroker, broker), | 154 | Effect.provideService(PreviewAutomationBroker.PreviewAutomationBroker, broker), |
| 124 | Effect.provideService(McpInvocationContext.McpInvocationContext, invocation), | 155 | Effect.provideService(McpInvocationContext.McpInvocationContext, invocation), |
| 125 | Effect.matchCause({ | 156 | Effect.matchCauseEffect({ |
| 126 | onFailure: (cause) => | 157 | onFailure: previewSnapshotFailure, |
| 127 | new McpSchema.CallToolResult({ | | |
| 128 | isError: true, | | |
| 129 | content: [{ type: "text", text: Cause.pretty(cause) }], | | |
| 130 | }), | | |
| 131 | onSuccess: ({ encodedResult }) => { | 158 | onSuccess: ({ encodedResult }) => { |
| 132 | const snapshot = encodedResult as { | 159 | const snapshot = encodedResult as { |
| 133 | readonly screenshot: { | 160 | readonly screenshot: { |
| ... | @@ -147,18 +174,20 @@ const registerPreviewSnapshot = Effect.fn("McpHttpServer.registerPreviewSnapshot | ... | @@ -147,18 +174,20 @@ const registerPreviewSnapshot = Effect.fn("McpHttpServer.registerPreviewSnapshot |
| 147 | height: screenshot.height, | 174 | height: screenshot.height, |
| 148 | }, | 175 | }, |
| 149 | }; | 176 | }; |
| 150 | return new McpSchema.CallToolResult({ | 177 | return Effect.succeed( |
| 151 | isError: false, | 178 | new McpSchema.CallToolResult({ |
| 152 | structuredContent: metadata, | 179 | isError: false, |
| 153 | content: [ | 180 | structuredContent: metadata, |
| 154 | { type: "text", text: JSON.stringify(metadata) }, | 181 | content: [ |
| 155 | { | 182 | { type: "text", text: JSON.stringify(metadata) }, |
| 156 | type: "image", | 183 | { |
| 157 | data: new Uint8Array(Buffer.from(screenshot.data, "base64")), | 184 | type: "image", |
| 158 | mimeType: screenshot.mimeType, | 185 | data: new Uint8Array(Buffer.from(screenshot.data, "base64")), |
| 159 | }, | 186 | mimeType: screenshot.mimeType, |
| 160 | ], | 187 | }, |
| 161 | }); | 188 | ], |
| | 189 | }), |
| | 190 | ); |
| 162 | }, | 191 | }, |
| 163 | }), | 192 | }), |
| 164 | ); | 193 | ); |