(
req,
reply,
)
| 209 | ); |
| 210 | |
| 211 | const downloadHandler: Parameters<FsRouteHost['get']>[2] = async ( |
| 212 | req, |
| 213 | reply, |
| 214 | ) => { |
| 215 | const { session_id } = req.params as { session_id: string }; |
| 216 | const wildcard = (req.params as Record<string, unknown>)['*'] as string; |
| 217 | |
| 218 | const DOWNLOAD_SUFFIX = ':download'; |
| 219 | if (!wildcard.endsWith(DOWNLOAD_SUFFIX)) { |
| 220 | return reply.send( |
| 221 | errEnvelope( |
| 222 | ErrorCode.VALIDATION_FAILED, |
| 223 | `unsupported action: ${wildcard}`, |
| 224 | req.id, |
| 225 | ), |
| 226 | ); |
| 227 | } |
| 228 | const relPath = wildcard.slice(0, -DOWNLOAD_SUFFIX.length); |
| 229 | if (relPath.length === 0) { |
| 230 | return reply.send( |
| 231 | errEnvelope( |
| 232 | ErrorCode.VALIDATION_FAILED, |
| 233 | 'path is empty', |
| 234 | req.id, |
| 235 | ), |
| 236 | ); |
| 237 | } |
| 238 | |
| 239 | let resolved: import('@moonshot-ai/agent-core').FsDownloadResolved; |
| 240 | try { |
| 241 | resolved = await ix.invokeFunction((a) => |
| 242 | a.get(IFsService).resolveDownload(session_id, relPath), |
| 243 | ); |
| 244 | } catch (err) { |
| 245 | sendMappedError(reply, req.id, err); |
| 246 | return reply; |
| 247 | } |
| 248 | |
| 249 | const ifNoneMatch = pickHeader(req.headers, 'if-none-match'); |
| 250 | if (ifNoneMatch !== undefined && ifNoneMatch === resolved.etag) { |
| 251 | return reply.code(304).header('etag', resolved.etag).send(''); |
| 252 | } |
| 253 | |
| 254 | reply.header('etag', resolved.etag); |
| 255 | reply.header( |
| 256 | 'last-modified', |
| 257 | resolved.modifiedAt.toUTCString(), |
| 258 | ); |
| 259 | reply.header( |
| 260 | 'content-disposition', |
| 261 | `attachment; filename="${sanitizeFilename(resolved.relative)}"`, |
| 262 | ); |
| 263 | reply.type(resolved.mime); |
| 264 | |
| 265 | const rangeHeader = pickHeader(req.headers, 'range'); |
| 266 | const range = parseRangeHeader(rangeHeader, resolved.size); |
| 267 | if (range !== null) { |
| 268 | reply |
nothing calls this directly
no test coverage detected