favicon colors

This commit is contained in:
Ian Gulliver
2026-10-16 13:51:17 -07:00
parent 518c042cac
commit 8f873788d7
5 changed files with 12 additions and 11 deletions
+2 -2
View File
@@ -12,7 +12,7 @@
- `internal/codex`: the `codex app-server` JSON-RPC client, with types generated from the CLI's schema by `go generate ./internal/codex` (see `docs/codex-protocol.md`). - `internal/codex`: the `codex app-server` JSON-RPC client, with types generated from the CLI's schema by `go generate ./internal/codex` (see `docs/codex-protocol.md`).
- `internal/tailscale`: `tailscale serve` for task previews (see "Previews"). - `internal/tailscale`: `tailscale serve` for task previews (see "Previews").
- `internal/workflow`: validating workflow definitions and reading and writing their YAML files (see "Workflows"). - `internal/workflow`: validating workflow definitions and reading and writing their YAML files (see "Workflows").
- `web/`: the SPA, frameworkless TypeScript compiled file-by-file to ES modules (no bundler). `web/src/*.ts` is the source; `web/src/api.gen.ts` holds types generated from `api/openapi.yaml`, and `web/src/api.ts` is the typed client over them. `go generate ./web` runs `npm ci`, regenerates the types and compiles `web/dist/`, which is committed so `go install` needs no Node. The binary embeds `index.html`, `style.css`, `favicon.svg` (a lead dot in the accent colour with spokes to five task-coloured dots; its colours are copies of the `web/style.css` palette, switching with the light/dark scheme), `favicon.png` (the same icon in its dark colours on an opaque dark `--surface` square at 180×180, rendered from `web/favicon-tile.svg`, which is not embedded; opaque because Orion puts a transparent icon on a white tile; linked as a second icon and as the `apple-touch-icon`, which Orion prefers over the SVG for its tab icon; Orion's icon store (`~/Library/Application Support/Orion/Defaults/website_icons`, kept apart from its cache) keys icons by hostname without the port, so another server on the same hostname can supply byre's tab icon; `favicon-tile.svg` repeats the shapes and dark colours of `favicon.svg`, so change both together, then regenerate the PNG with `rsvg-convert --width 180 --height 180 --output web/favicon.png web/favicon-tile.svg`), `dist/`, `src/` (for source maps), `fonts/` and `vendor/` (Mermaid, see "Inbox"; xterm.js, see "Terminals"). `byre serve --dev` serves `./web` from disk instead (run from the repo root); pair it with `npm --prefix web exec tsc -- --watch`. - `web/`: the SPA, frameworkless TypeScript compiled file-by-file to ES modules (no bundler). `web/src/*.ts` is the source; `web/src/api.gen.ts` holds types generated from `api/openapi.yaml`, and `web/src/api.ts` is the typed client over them. `go generate ./web` runs `npm ci`, regenerates the types and compiles `web/dist/`, which is committed so `go install` needs no Node. The binary embeds `index.html`, `style.css`, `favicon.svg` (a lead dot in the accent colour with spokes to five task-coloured dots; its colours are saturated versions of the `web/style.css` accent and task hues, not copies of the palette, since the palette's pastels blur together at 16px; they switch with the light/dark scheme), `favicon.png` (the same icon in its dark colours on an opaque dark `--surface` square at 180×180, rendered from `web/favicon-tile.svg`, which is not embedded; opaque because Orion puts a transparent icon on a white tile; linked as a second icon and as the `apple-touch-icon`, which Orion prefers over the SVG for its tab icon; Orion's icon store (`~/Library/Application Support/Orion/Defaults/website_icons`, kept apart from its cache) keys icons by hostname without the port, so another server on the same hostname can supply byre's tab icon; `favicon-tile.svg` repeats the shapes and dark colours of `favicon.svg`, so change both together, then regenerate the PNG with `rsvg-convert --width 180 --height 180 --output web/favicon.png web/favicon-tile.svg`), `dist/`, `src/` (for source maps), `fonts/` and `vendor/` (Mermaid, see "Inbox"; xterm.js, see "Terminals"). `byre serve --dev` serves `./web` from disk instead (run from the repo root); pair it with `npm --prefix web exec tsc -- --watch`.
## Data ## Data
@@ -245,7 +245,7 @@ There is no snoozing. The `snoozed_until` and `snooze_until` columns are still i
Every Markdown view (inbox items and the transcript) renders a line `<details><summary>Title</summary>` (or `<details>` with the `<summary>` on the next line), Markdown content, and a line `</details>` as a collapsed section (`web/src/markdown.ts`; sections nest) showing only the title; session guidance and the `ask_human` schema tell agents to put long supporting detail in them. Every Markdown view (inbox items and the transcript) renders a line `<details><summary>Title</summary>` (or `<details>` with the `<summary>` on the next line), Markdown content, and a line `</details>` as a collapsed section (`web/src/markdown.ts`; sections nest) showing only the title; session guidance and the `ask_human` schema tell agents to put long supporting detail in them.
Markdown images (`![alt](src)`, or `![alt](<src>)`; the plain form also accepts spaces, since worktree paths under `Application Support` have one) render inline, linking to the full image. A `src` that is an absolute path, a path relative to the worktree or a `file://` URL is loaded from `GET /api/tasks/{taskId}/image?path=` for the item's or event's task; a `data:image/` URL of PNG, JPEG, GIF or WebP is used as is; any other scheme, `http(s)` included, shows as a link with the alt text and is never fetched. An image that fails to load is replaced by "image not available: <src>". An inbox `image` attachment renders the same way from its `image` (data URL) or `path`. Markdown images (`![alt](src)`, or `![alt](<src>)`; the plain form also accepts spaces, since worktree paths under `Application Support` have one) render inline, linking to the full image. A `src` that is an absolute path, a path relative to the worktree or a `file://` URL is loaded from `GET /api/tasks/{taskId}/image?path=` for the item's or event's task, which refuses (403) a path that resolves outside the task's worktree, so the `ask_human` description tells agents to copy a scratch image into the worktree first; a `data:image/` URL of PNG, JPEG, GIF or WebP is used as is; any other scheme, `http(s)` included, shows as a link with the alt text and is never fetched. An image that fails to load is replaced by "image not available: <src>". An inbox `image` attachment renders the same way from its `image` (data URL) or `path`.
A code block fenced as `mermaid`, and an inbox `diagram` attachment, render as a Mermaid diagram (`web/src/mermaid.ts`). The library is vendored: `web/package.json` pins `mermaid` as a devDependency, and `go generate ./web` copies `node_modules/mermaid/dist/mermaid.min.js` and its LICENSE into `web/vendor/`, which is committed and embedded. To upgrade, change the pinned version, `npm --prefix web install`, and regenerate. Nothing loads it until the first diagram is drawn; that injects one `<script src="/vendor/mermaid.min.js">` and initializes Mermaid with `securityLevel: "strict"` and the `base` theme, coloured from the custom properties in `web/style.css` as they resolve at that moment (so a light/dark switch applies from the next page load). Each diagram shows its source until its SVG is ready; source Mermaid rejects stays as source with "diagram not rendered: <error>" under it. The endpoint (`internal/server/images.go`) serves PNG, JPEG, GIF, WebP and SVG by extension, resolves symlinks on both the worktree and the file and answers 403 for anything outside the worktree, 404 for a missing file, 400 for another extension or a non-file, and 409 once the task is closed (its worktree is gone). Responses carry `X-Content-Type-Options: nosniff` and a sandboxing `Content-Security-Policy`, so an SVG opened directly runs no script, and `Cache-Control: no-cache` with `Last-Modified`, so a changed file is refetched. A code block fenced as `mermaid`, and an inbox `diagram` attachment, render as a Mermaid diagram (`web/src/mermaid.ts`). The library is vendored: `web/package.json` pins `mermaid` as a devDependency, and `go generate ./web` copies `node_modules/mermaid/dist/mermaid.min.js` and its LICENSE into `web/vendor/`, which is committed and embedded. To upgrade, change the pinned version, `npm --prefix web install`, and regenerate. Nothing loads it until the first diagram is drawn; that injects one `<script src="/vendor/mermaid.min.js">` and initializes Mermaid with `securityLevel: "strict"` and the `base` theme, coloured from the custom properties in `web/style.css` as they resolve at that moment (so a light/dark switch applies from the next page load). Each diagram shows its source until its SVG is ready; source Mermaid rejects stays as source with "diagram not rendered: <error>" under it. The endpoint (`internal/server/images.go`) serves PNG, JPEG, GIF, WebP and SVG by extension, resolves symlinks on both the worktree and the file and answers 403 for anything outside the worktree, 404 for a missing file, 400 for another extension or a non-file, and 409 once the task is closed (its worktree is gone). Responses carry `X-Content-Type-Options: nosniff` and a sandboxing `Content-Security-Policy`, so an SVG opened directly runs no script, and `Cache-Control: no-cache` with `Last-Modified`, so a changed file is refetched.
+2 -1
View File
@@ -43,7 +43,8 @@ func (m *Manager) askTool(l *live) mcp.Tool {
"its example, code, commands and trade-offs, so the human never has to match a paragraph above to an option below. " + "its example, code, commands and trade-offs, so the human never has to match a paragraph above to an option below. " +
"Text above the list covers only what all the choices share. " + "Text above the list covers only what all the choices share. " +
"To choose between images (icons, screenshots, mockups), give each choice exactly one indented line, its image " + "To choose between images (icons, screenshots, mockups), give each choice exactly one indented line, its image " +
"(`![alt](path)`, the path absolute or relative to your worktree), and nothing else: the choices then show side by side as a grid " + "(`![alt](path)`, the path relative to your worktree or absolute inside it; byre serves no image from outside the worktree, " +
"so an image in a scratch or temp directory shows as \"image not available\": copy it into the worktree first), and nothing else: the choices then show side by side as a grid " +
"so the human can compare them at a glance. " + "so the human can compare them at a glance. " +
"End your turn after asking; the answer arrives as your next message. " + "End your turn after asking; the answer arrives as your next message. " +
"An answer of \"Use your judgment for this decision and continue within the existing task instructions.\" lets you settle that one decision yourself; " + "An answer of \"Use your judgment for this decision and continue within the existing task instructions.\" lets you settle that one decision yourself; " +
+6 -6
View File
@@ -8,11 +8,11 @@
<line x1="16" y1="16" x2="4.6" y2="12.3"/> <line x1="16" y1="16" x2="4.6" y2="12.3"/>
</g> </g>
<g transform="translate(2 2.5)"> <g transform="translate(2 2.5)">
<circle fill="#8ab4ff" cx="16" cy="16" r="6"/> <circle fill="#3d7dff" cx="16" cy="16" r="6"/>
<circle fill="#fe9fa6" cx="16" cy="4" r="3.5"/> <circle fill="#ff3b4e" cx="16" cy="4" r="3.5"/>
<circle fill="#ffa383" cx="27.4" cy="12.3" r="3.5"/> <circle fill="#ff9500" cx="27.4" cy="12.3" r="3.5"/>
<circle fill="#99d079" cx="23.1" cy="25.7" r="3.5"/> <circle fill="#34d058" cx="23.1" cy="25.7" r="3.5"/>
<circle fill="#b6b4fe" cx="8.9" cy="25.7" r="3.5"/> <circle fill="#b05cff" cx="8.9" cy="25.7" r="3.5"/>
<circle fill="#2fd4ec" cx="4.6" cy="12.3" r="3.5"/> <circle fill="#00d5f0" cx="4.6" cy="12.3" r="3.5"/>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 744 B

After

Width:  |  Height:  |  Size: 744 B

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

+2 -2
View File
@@ -1,10 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<style> <style>
line { stroke: #4a5260; stroke-width: 1.5; } line { stroke: #4a5260; stroke-width: 1.5; }
.l { fill: #1a45bd; } .a { fill: #a4273f; } .b { fill: #9f3501; } .c { fill: #376e00; } .d { fill: #5849b2; } .e { fill: #046a77; } .l { fill: #2563eb; } .a { fill: #e0182d; } .b { fill: #f08000; } .c { fill: #1fa83f; } .d { fill: #9a3cf0; } .e { fill: #00a8c8; }
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
line { stroke: #a9b1bc; } line { stroke: #a9b1bc; }
.l { fill: #8ab4ff; } .a { fill: #fe9fa6; } .b { fill: #ffa383; } .c { fill: #99d079; } .d { fill: #b6b4fe; } .e { fill: #2fd4ec; } .l { fill: #3d7dff; } .a { fill: #ff3b4e; } .b { fill: #ff9500; } .c { fill: #34d058; } .d { fill: #b05cff; } .e { fill: #00d5f0; }
} }
</style> </style>
<line x1="16" y1="16" x2="16" y2="4"/> <line x1="16" y1="16" x2="16" y2="4"/>

Before

Width:  |  Height:  |  Size: 952 B

After

Width:  |  Height:  |  Size: 952 B