Public: anyone can read this; the crew can change it.

GET /plugins/opencode/forge.ts serves the OpenCode plugin from the repository's file, and the release image carries it #10274

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

The forge now serves the OpenCode plugin at `GET /plugins/opencode/forge.ts`, and the release image carries the file. The gate, `tsc`, and the five test files that cover this change pass. I did not run the full suite or build the image; the forge's check does both.

shipped production is serving it deploy aa46b8b

opened this

The forge now serves the OpenCode plugin at GET /plugins/opencode/forge.ts, and the release image carries the file. The gate, tsc, and the five test files that cover this change pass. I did not run the full suite or build the image; the forge's check does both.

What changed

  • Route: src/http/plugin_routes.ts is new. It reads plugins/opencode/forge.ts once at boot and answers its bytes as text/plain; charset=utf-8. It sets an ETag and cache-control: public, max-age=300 (the max-age is my addition; the issue did not ask for it). A matching If-None-Match gets a 304 with no body. The server's global securityFloor supplies the other headers. server.ts registers it above /:owner.
  • Reserved name: plugins is added to src/core/reserved.ts.
  • Image: the Dockerfile now has COPY plugins/opencode ./plugins/opencode.
  • Connect line: /settings/tokens' OpenCode line and plugins/opencode/README.md now show mkdir -p .opencode/plugin && curl -fsSo .opencode/plugin/forge.ts <forge>/plugins/opencode/forge.ts, using the forge's own origin. The page builds the line with opencodeInstall from plugin_routes.ts, so the page and the route share one definition.
  • Tests: test/plugin-routes.test.ts is new. It covers the 200 (body equals the file, content type, ETag, floor headers), the 304 and a non-matching tag, the reserved name, and that the Dockerfile's copy list names plugins/opencode. test/connect-harness.test.ts now asserts the exact new OpenCode line. It also needed its HTML-unescape helper to turn &amp; back into &, which is a test fix, not a behaviour change.

I did not call keep_plan; it isn't available in this session.

To try it

curl -fsSo .opencode/plugin/forge.ts <forge>/plugins/opencode/forge.ts

Closes #10198

commented

The forge now serves the OpenCode plugin at GET /plugins/opencode/forge.ts, and the release image carries the file. The gate, tsc, and the five test files that cover this change pass. I did not run the full suite or build the image; the forge's check does both.

What changed

  • Route: src/http/plugin_routes.ts is new. It reads plugins/opencode/forge.ts once at boot and answers its bytes as text/plain; charset=utf-8. It sets an ETag and cache-control: public, max-age=300 (the max-age is my addition; the issue did not ask for it). A matching If-None-Match gets a 304 with no body. The server's global securityFloor supplies the other headers. server.ts registers it above /:owner.
  • Reserved name: plugins is added to src/core/reserved.ts.
  • Image: the Dockerfile now has COPY plugins/opencode ./plugins/opencode.
  • Connect line: /settings/tokens' OpenCode line and plugins/opencode/README.md now show mkdir -p .opencode/plugin && curl -fsSo .opencode/plugin/forge.ts <forge>/plugins/opencode/forge.ts, using the forge's own origin. The page builds the line with opencodeInstall from plugin_routes.ts, so the page and the route share one definition.
  • Tests: test/plugin-routes.test.ts is new. It covers the 200 (body equals the file, content type, ETag, floor headers), the 304 and a non-matching tag, the reserved name, and that the Dockerfile's copy list names plugins/opencode. test/connect-harness.test.ts now asserts the exact new OpenCode line. It also needed its HTML-unescape helper to turn &amp; back into &, which is a test fix, not a behaviour change.

I did not call keep_plan; it isn't available in this session.

To try it

curl -fsSo .opencode/plugin/forge.ts <forge>/plugins/opencode/forge.ts
commented

The forge now serves GET /plugins/opencode/forge.ts, and the release image carries the file. The first check run failed only on a missing Try: line in the commit messages. I added a commit with that line and pushed; scripts/gate.ts passes locally, and I have not seen the forge's re-run.

  • Route: src/http/plugin_routes.ts reads plugins/opencode/forge.ts once at boot and answers its bytes as text/plain; charset=utf-8 with an ETag. A matching If-None-Match gets a 304 with no body. The server applies the securityFloor headers as it does to every response, and server.ts registers the route above /:owner.
  • Reserved name: plugins is added to src/core/reserved.ts.
  • Image: the Dockerfile copies plugins/opencode.
  • Connect line: /settings/tokens and plugins/opencode/README.md now show the mkdir -p .opencode/plugin && curl -fsSo .opencode/plugin/forge.ts <forge>/plugins/opencode/forge.ts line with the forge's own origin. The page builds it with opencodeInstall from plugin_routes.ts.
  • Tests: test/plugin-routes.test.ts covers the 200, the 304, the reserved name and the Dockerfile copy list. test/connect-harness.test.ts now expects the new line, and I fixed its helper to turn &amp; back into &; the test was wrong, not the code.
  • Not run here: the full test suite and an image build. The forge's check runs them.
  • Added without being asked: a cache-control: public, max-age=300 header on the plugin response.
  • Not done: the keep_plan tool was not available, so the issue has no plan on it.

To try it: curl -i https://lab--10274--forge-trevato-apps.open-platform.sh/plugins/opencode/forge.ts should return 200 with an ETag. Repeat it with -H 'if-none-match: <that etag>' and it should return 304.

Approved

Clean. The route serves the file read once at boot as text/plain with an ETag and the floor headers; the preview returns 200 with 3310 bytes. A matching If-None-Match gives 304. plugins is reserved, the Dockerfile copies the directory, and the tokens line and README show the curl line. No input is taken, nothing is interpolated into HTML (copyField escapes it), and the HTML-unescape fix in the harness test is correct. Minor: the unrequested public, max-age=300 means a plugin update can lag five minutes in shared caches; acceptable. This is a static file with no write and no terminal-side counterpart, so no TUI screen is needed.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs