feat(kap-server): add GET /api/v1/fs:content endpoint for host files - #2012
Conversation
- serve any host file by absolute path as raw content with Content-Type, ETag caching, and single-range support - extract shared file metadata helpers (binary detection, line counting, etag, mime/language guessing) into agent-core-v2 _base/utils/fileMeta - extract pickHeader/parseRangeHeader into kap-server lib/httpRange for reuse across download/content routes
🦋 Changeset detectedLatest commit: e662260 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
commit: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3298e5de0f
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| return; | ||
| } | ||
|
|
||
| if (st.isDirectory) { |
There was a problem hiding this comment.
Reject non-regular host paths before streaming
When an authenticated client requests a non-regular absolute path such as /dev/zero, a FIFO, or a socket, stat reports neither directory nor file, so this check falls through to sampling/streaming with content-length derived from st.size (often 0). That can hang the request, stream unbounded device data, or send a malformed response; please require st.isFile before reading or return a wire error for non-file nodes.
Useful? React with 👍 / 👎.
| @@ -0,0 +1,108 @@ | |||
| /** | |||
There was a problem hiding this comment.
Use the agent-core-v2 header convention
packages/agent-core-v2/AGENTS.md requires package comments to be header-only and to start with <domain> domain (Ln) — .... This new helper's top block starts with a generic description instead, so it violates the documented convention for touched agent-core-v2 files; please rewrite it to the required domain identity header and avoid additional symbol-level comments below.
Useful? React with 👍 / 👎.
Return the reply.send(stream) result through the handler promise instead of using return-await, matching the session fs download route pattern.
Device nodes, FIFOs, sockets, and zero-size virtual files (/proc, /sys) would otherwise hang the request or stream unbounded data. Addresses review feedback; also folds fileMeta symbol comments into the header block per the agent-core-v2 header-only comment convention.
Related Issue
No linked issue — the problem is explained below.
Problem
Frontends served by kap-server (web UI, inspector, future file pickers) currently have no way to read a file outside a session workspace. The session fs routes (
/api/v1/sessions/{id}/fs:*) are strictly confined to the workspace root by design, and the only global fs endpoint (/api/v1/fs:browse) lists directories but cannot return file content. Reading an arbitrary host file is only possible through the debug RPC surface (/api/v1/debug/hostFileSystem/*), which is loopback-only and gated behind--debug-endpoints, so it is not usable by regular clients.What changed
GET /api/v1/fs:content?path=<absolute-path>to kap-server, serving any host file as a raw byte stream: best-effortContent-Type(extension-based, with a leading-bytes sample to distinguishtext/plainfromapplication/octet-streamfor unknown extensions),ETag/If-None-Match(304), and single-rangeRangerequests (206). Responses are streamed, so there is no size cap and browsers can render previews directly. Errors keep the envelope form: relative path 40001, not found 40409, permission denied 40411, directory 40906.IHostFileSystemprimitives — deliberately no new "unconfined read" domain Service in agent-core-v2. The endpoint's only access gate is the existing global bearer auth, same as the rest of/api/v1.sessionFsintoagent-core-v2/_base/utils/fileMetaso both read surfaces classify content identically; extractpickHeader/parseRangeHeaderinto kap-serverlib/httpRangeshared by the session download route and the new route.Checklist
gen-changesetsskill, or this PR needs no changeset.gen-docsskill, or this PR needs no doc update.