Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ Static site for **ByteFuture**, served from GitHub Pages (`.nojekyll`, `CNAME`
Layout:

- `index.html` — ByteFuture home: company intro, the hybrid-inference thesis, the two products, and a "Writings" teaser.
- `blog/` — the **Writings** section (listing + articles). Rules below.
- `posts.json` — content manifest for Writings (repo root; the site fetches it at `/posts.json`).
- `src/content/writings/<lang>/<slug>.md` — the article sources (Astro content collection); the build generates `/blog/<slug>[-lang].html`. See **Authoring model — Astro** below.
- `blog/` — the **Writings** section listing pages + article assets/covers (the listing `index*.html` are still hand-maintained static files).
- `posts.json` (+ `posts-{zh,ja,ko}.json`) — the Writings manifest served at `/posts.json`, **generated at build** from the collection by `src/pages/posts*.json.ts` (the root `posts*.json` files are stale legacy, no longer served).
- `sitemap.xml` — hand-maintained (no Astro sitemap integration); new articles need manual `<url>` entries.
- `CNAME`, `.nojekyll` — GitHub Pages config.

## HARD RULE — NEVER touch analytics or ads tracking
Expand Down Expand Up @@ -152,7 +154,20 @@ The `blog/` folder is the **ByteFuture Writings** section. It contains:
- `blog/<slug>.html` — one file per published article.
- cover images and article assets, also under `blog/`.

The post index is driven by `posts.json` (repo root); `blog/index.html` fetches it at `/posts.json` and renders the cards. The **HARD RULE above applies to every page under `blog/`.**
The post index is driven by `posts.json`; `blog/index.html` fetches it at `/posts.json` and renders the cards. The **HARD RULE above applies to every page under `blog/`.**

### Authoring model — Astro (current, authoritative)

The site is now built with **Astro** (`astro.config.mjs`, `output: 'static'`, `format: 'file'`). Articles are authored as **Markdown in a content collection**, not as hand-written HTML. This section is authoritative and supersedes the older per-file HTML instructions further down (the `cp blog/post-template.html`, "fill every `▼ EDIT ▼` marker", "copy the redirect script / GA / hreflang / view-counter verbatim into each page" steps): those describe the pre-Astro static pages and are kept only as reference for the legacy files still on disk.

What changed, and where things live now:

- **One Markdown file per language per article:** `src/content/writings/<lang>/<slug>.md` where `<lang>` ∈ `en | zh | ja | ko`. Frontmatter fields (validated by `src/content.config.ts`): `slug`, `lang`, `title`, `summary`, `category`, `date` (`YYYY-MM-DD`), `cta` (URL, defaults to Token Station intro), `cover` (optional, repo-root-relative), `draft` (optional bool). The article body is Markdown/HTML below the frontmatter.
- **URLs are generated, unchanged:** `src/pages/blog/[...slug].astro` emits `/blog/<slug>.html` for `en` and `/blog/<slug>-<lang>.html` for the others (the `-zh/-ja/-ko` suffix is derived from `lang`, so you never hand-name files).
- **Chrome is centralized — do NOT copy it per article.** `src/layouts/WritingLayout.astro` injects, for every article automatically: the viewport meta, the i18n redirect script + `bf_lang` cookie logic, `canonical` / `og:locale` / all four `hreflang` alternates, the **GA4 tag** (`G-KQ0EX9QGK6`), the nav + language `<select>`, the footer, the **GoatCounter** view counter, and the `.prose` / mobile CSS. The HARD RULE still protects the GA and GoatCounter snippets — they now live in the layout, so never strip them there.
- **The manifests are generated, not hand-edited:** `src/pages/posts.json.ts` (+ `posts-zh/ja/ko.json.ts`) build `/posts.json` etc. from the collection via `src/lib/posts-manifest.ts` (drops drafts, filters by `lang`, sorts newest-first). Add/rename/retire an article by adding/renaming/removing its Markdown files — the manifests follow. The stale root `posts*.json` files are legacy and are no longer served (this is why `scripts/sync-legacy-public.mjs` stopped copying them).
- **Still hand-maintained static files** (copied verbatim into `public/` by `scripts/sync-legacy-public.mjs`): the listing pages `blog/index.html` + `index-{zh,ja,ko}.html`, the home `index*.html`, and **`sitemap.xml`**. Consequences that still bind (see the rules below): the **category closed set** is enforced in those listing files, and **`sitemap.xml` entries are added by hand** — there is no `@astrojs/sitemap` integration.
- **Build & verify:** `npm run build` (runs `sync-legacy-public.mjs` then `astro build` into `dist/`); `npm run check:legacy-links` and `npm run check:mobile -- <url>` for the checks.

### Branding (non-negotiable)

Expand Down Expand Up @@ -258,7 +273,7 @@ Root-level `posts.json` is a JSON array. Each object:

Rules:

- **Categories are a closed set.** They must match the filter pills in `blog/index.html` (`#cat-filter` `data-cat`) **and** the `validCats` map in its posts engine. To add a category, update all three.
- **Categories are a closed set** (`engineering`, `product`, `research`, `tutorial`) and it's the `category` frontmatter field. This still binds under Astro: the value must match, in each `blog/index*.html` listing, the filter pills (`#cat-filter` `data-cat`), the `validCats` map, **and** the `CAT_LABELS` table (all four languages) in its posts engine. On top of that, `WritingLayout.astro` prints the raw `category` string in the article header and uses it as the Topics-link label + `?cat=` param — so an off-list value leaks as untranslated literal text (e.g. `model-launches`), can't be filtered, and its Topics link dead-ends to **All**. To add a genuinely new category, update the pills + `validCats` + `CAT_LABELS` (×4 langs) in every `index*.html`; otherwise pick one of the four.
- **The hero is automatic: the newest post by `date` always leads.** On the **All** tab the most recent post renders in the hero and is pulled out of the grid; the rest follow newest-first. There is no manual `featured` flag (the engine ignores it) — to put an article on top, give it the latest `date`.
- Dates are real publish dates; newest sorts first.

Expand Down
99 changes: 99 additions & 0 deletions blog/asset-sources/gpt-5-6-token-station-cover.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&family=Source+Serif+4:ital,opsz,wght@1,8..60,400&display=swap');
* { margin:0; padding:0; box-sizing:border-box; }
body { width:1200px; height:630px; background:#faf9f5; font-family:'Space Grotesk',sans-serif; overflow:hidden; position:relative; }

.grid {
position:absolute; inset:0;
background-image: radial-gradient(rgba(24,24,27,0.07) 1.2px, transparent 1.2px);
background-size: 28px 28px;
}
.wash {
position:absolute; top:-220px; right:-160px; width:680px; height:680px; border-radius:50%;
background: radial-gradient(circle, rgba(37,99,235,0.16) 0%, rgba(13,148,136,0.08) 45%, transparent 70%);
}

/* one endpoint routing to three variants, upper-right */
.routes { position:absolute; right:70px; top:118px; width:430px; height:250px; opacity:0.98; }

.content { position:absolute; inset:0; padding:64px 72px; display:flex; flex-direction:column; }

.kicker {
font-family:'JetBrains Mono',monospace; font-size:17px; font-weight:600;
letter-spacing:0.16em; text-transform:uppercase; color:#0D9488; margin-bottom:24px;
}

h1 { font-size:78px; font-weight:700; letter-spacing:-0.035em; line-height:1.02; color:#18181b; max-width:720px; }
h1 .model { color:#2563EB; }
h1 .sub { display:block; font-family:'Source Serif 4',serif; font-style:italic; font-weight:400; font-size:38px; letter-spacing:-0.01em; color:#52525b; margin-top:22px; }

.bottom { margin-top:auto; display:flex; align-items:flex-end; justify-content:space-between; }
.chips { display:flex; gap:14px; align-items:center; }
.chip {
background:#ffffff; border:1.5px solid #e4e4e7; border-radius:50px; padding:13px 26px;
font-size:22px; font-weight:600; color:#18181b;
}
.chip.accent { border-color:rgba(37,99,235,0.40); color:#2563EB; background:#eff4ff; }

.brand { display:flex; align-items:center; gap:13px; }
.brand span { font-size:23px; font-weight:600; color:#52525b; }

/* route node graphic */
.node-label { font-family:'JetBrains Mono',monospace; font-size:19px; font-weight:600; fill:#18181b; }
.node-hub { font-family:'JetBrains Mono',monospace; font-size:17px; font-weight:600; fill:#2563EB; letter-spacing:0.04em; }
</style>
</head>
<body>
<div class="grid"></div>
<div class="wash"></div>

<svg class="routes" viewBox="0 0 430 250" fill="none">
<!-- links from single endpoint to three routes -->
<path d="M60 125 C 170 125, 190 34, 300 34" stroke="#2563EB" stroke-width="4" stroke-linecap="round" opacity="0.55"/>
<path d="M60 125 C 170 125, 190 125, 300 125" stroke="#2563EB" stroke-width="4" stroke-linecap="round" opacity="0.55"/>
<path d="M60 125 C 170 125, 190 216, 300 216" stroke="#2563EB" stroke-width="4" stroke-linecap="round" opacity="0.55"/>

<!-- endpoint hub -->
<circle cx="60" cy="125" r="28" fill="#2563EB" fill-opacity="0.10" stroke="#2563EB" stroke-width="2.4"/>
<circle cx="60" cy="125" r="8.5" fill="#2563EB"/>

<!-- three variant nodes -->
<circle cx="300" cy="34" r="14" fill="none" stroke="#0D9488" stroke-width="3"/>
<circle cx="300" cy="125" r="14" fill="none" stroke="#0D9488" stroke-width="3"/>
<circle cx="300" cy="216" r="14" fill="none" stroke="#0D9488" stroke-width="3"/>

<text x="326" y="41" class="node-label">Sol</text>
<text x="326" y="132" class="node-label">Terra</text>
<text x="326" y="223" class="node-label">Luna</text>
</svg>

<div class="content">
<div class="kicker">OpenAI &middot; GPT-5.6 &middot; Coding agents</div>
<h1><span class="model">GPT-5.6</span> is now supported
<span class="sub">Sol, Terra, and Luna from one endpoint.</span>
</h1>

<div class="bottom">
<div class="chips">
<div class="chip">Sol</div>
<div class="chip">Terra</div>
<div class="chip">Luna</div>
<div class="chip accent">on Token Station</div>
</div>
<div class="brand">
<svg width="40" height="40" viewBox="0 0 32 32" fill="none">
<rect x="2.5" y="2.5" width="27" height="27" rx="8" fill="#2563EB" fill-opacity="0.10" stroke="#2563EB" stroke-width="1.6"/>
<circle cx="12" cy="16" r="3.4" fill="#2563EB"/>
<circle cx="21.5" cy="16" r="3.4" fill="none" stroke="#0D9488" stroke-width="1.8"/>
<path d="M15.4 16h2.7" stroke="#0D9488" stroke-width="1.8" stroke-linecap="round"/>
</svg>
<span>ByteFuture</span>
</div>
</div>
</div>
</body>
</html>
Binary file added blog/gpt-5-6-token-station-cover.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 0 additions & 4 deletions scripts/sync-legacy-public.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@ const copyNames = [
'index-zh.html',
'index-ja.html',
'index-ko.html',
'posts.json',
'posts-zh.json',
'posts-ja.json',
'posts-ko.json',
'CNAME',
'.nojekyll',
'robots.txt',
Expand Down
20 changes: 20 additions & 0 deletions sitemap.xml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,26 @@
<lastmod>2026-06-18</lastmod>
<priority>0.6</priority>
</url>
<url>
<loc>https://bytefuture.ai/blog/gpt-5-6-token-station.html</loc>
<lastmod>2026-07-13</lastmod>
<priority>0.7</priority>
</url>
<url>
<loc>https://bytefuture.ai/blog/gpt-5-6-token-station-zh.html</loc>
<lastmod>2026-07-13</lastmod>
<priority>0.6</priority>
</url>
<url>
<loc>https://bytefuture.ai/blog/gpt-5-6-token-station-ja.html</loc>
<lastmod>2026-07-13</lastmod>
<priority>0.6</priority>
</url>
<url>
<loc>https://bytefuture.ai/blog/gpt-5-6-token-station-ko.html</loc>
<lastmod>2026-07-13</lastmod>
<priority>0.6</priority>
</url>
<url>
<loc>https://bytefuture.ai/blog/glm-5-2-zai-stock-jump.html</loc>
<lastmod>2026-06-15</lastmod>
Expand Down
1 change: 1 addition & 0 deletions src/content.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const writings = defineCollection({
category: z.string().default('tutorial'),
date: z.coerce.date(),
cta: z.string().url().default('https://models.bytefuture.ai/intro.html'),
cover: z.string().optional(),
draft: z.boolean().default(false),
}),
});
Expand Down
126 changes: 126 additions & 0 deletions src/content/writings/en/gpt-5-6-token-station.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
---
slug: gpt-5-6-token-station
lang: en
title: "GPT-5.6 is now on Token Station: try it in your coding agent routes"
summary: "Token Station now supports GPT-5.6 across OpenAI-compatible API and coding-agent routes, including Codex and Copilot surfaces. Use one endpoint to compare Sol, Terra, Luna, and Claude Fable 5 in real workflows."
category: product
date: 2026-07-13
cta: https://models.bytefuture.ai/intro.html
cover: blog/gpt-5-6-token-station-cover.png
---

GPT-5.6 is now available on Token Station.

For coding-agent teams, what matters is that GPT-5.6 can be tested through the routes developers already use: a direct OpenAI-compatible API, OpenAI Codex-style workflows, and GitHub Copilot routes where the supported catalog exposes the model.

That turns GPT-5.6 from a launch announcement into something you can actually route, compare, and adopt without rebuilding your agent stack.

## What Token Station supports

Token Station exposes the GPT-5.6 family through direct OpenAI-compatible routes:

- `openai/gpt-5.6`
- `openai/gpt-5.6-sol`
- `openai/gpt-5.6-terra`
- `openai/gpt-5.6-luna`

And GitHub Copilot routes where the supported catalog publishes availability:

- `github-copilot/gpt-5.6-sol`
- `github-copilot/gpt-5.6-terra`
- `github-copilot/gpt-5.6-luna`

OpenAI Codex-style workflows use these same `openai/` routes, so there is no separate Codex route to set up.

The result is simple: you can test the same model family from the surface that matches your workflow instead of treating each provider interface as a separate integration project.

## Try GPT-5.6 from one endpoint

The endpoint is the standard Token Station OpenAI-compatible API:

```bash
curl https://models.bytefuture.ai/v1/chat/completions \
-H "Authorization: Bearer TOKEN_STATION_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-5.6-sol",
"messages": [
{"role": "user", "content": "Plan a safe refactor for a pricing module and list the tests to run."}
]
}'
```

To try a Copilot route, use:

```json
{
"model": "github-copilot/gpt-5.6-luna"
}
```

Your application still talks to the same endpoint. The route changes; the integration stays stable.

## GPT-5.6 Sol, Terra, and Luna

A coding agent is not one API call. A real session may include planning, repository search, patch generation, test repair, code review, and delegated subtasks. Those steps do not all need the same model tier.

The three named variants give teams a useful testing ladder:

- **GPT-5.6 Sol**: the flagship route for the hardest coding-agent steps.
- **GPT-5.6 Terra**: a middle route for repeated implementation and debugging loops.
- **GPT-5.6 Luna**: a lower-cost route for exploration, triage, and subtask fan-out.

A practical routing pattern looks like this:

- Use a cheaper route for exploration, triage, and repeated iteration.
- Move to a stronger route for hard reasoning, risky patches, and final review.
- Keep the endpoint stable so your harness, agent, and evaluation scripts do not need to change every time you compare a model.

Agent workloads are uneven. A repository-wide plan, a subtle failing test, and a boilerplate file edit should not automatically use the same cost tier. Model choice becomes a route name, not a new integration project.

## Pricing and cache accounting

Token Station exposes GPT-5.6 pricing in the categories agent operators actually need to track: input, output, cached input, cache writes, and long-context tiers above 272K input tokens.

For coding agents, cache accounting matters because repository context repeats. Agents send file summaries, diffs, test output, task state, and previous plans again and again. Prompt caching can lower repeated-context cost, but only if cache writes and cached reads are handled separately.

Token Station normalizes GPT-5.6 `cache_write_tokens` usage so cache writes are charged in the cache-creation bucket without double-counting them as ordinary input tokens.

A practical price frame inside Token Station:

- GPT-5.6 Sol / `openai/gpt-5.6`: $5/M input, $30/M output, $0.50/M cached input, and $6.25/M cache writes up to 272K input tokens.
- GPT-5.6 Terra: $2.50/M input and $15/M output up to 272K input tokens.
- GPT-5.6 Luna: $1/M input and $6/M output up to 272K input tokens.
- Claude Fable 5: $10/M input, $50/M output, $1/M cache reads, $12.50/M prompt-cache writes, and $20/M one-hour cache writes.

Above 272K input tokens, GPT-5.6 uses a long-context tier: Sol doubles input and cached-input prices and moves output to $45/M; Terra moves to $5/M input and $22.50/M output; Luna moves to $2/M input and $9/M output.

## How to compare GPT-5.6 with Claude Fable 5

Claude Fable 5 is still a natural comparison point for long-running coding agents. It is configured in Token Station with a 1M context window and a higher $10/$50 price profile.

GPT-5.6 brings a different operating shape: OpenAI-native routes, Codex and Copilot surfaces, and multiple price tiers in the same family.

A simple starting point:

- Reach for the GPT-5.6 family when you want OpenAI-native routes, Codex or Copilot surfaces, or a cheaper tier for high-volume steps. Pick Sol, Terra, or Luna by task, as above.
- Reach for Claude Fable 5 when you specifically want Anthropic's long-running-agent behavior and its 1M context, and are willing to pay the higher rate.
- Compare them inside Token Station when workflow fit matters more than model-brand loyalty.

## Azure and unavailable provider catalogs

The integration also includes commented Azure OpenAI GPT-5.6 preview templates and support for Azure's `/openai/v1` surface through `azure_api_version = "v1"`.

Those templates are intentionally not enabled with guessed prices. Azure GPT-5.6 meters were not published at the time of integration, so operators should fill in pricing when their Azure deployment exposes the model.

GMI Cloud and AWS Bedrock OpenAI catalogs were not added because their public catalogs did not list GPT-5.6 support at the time. Token Station should make model routing easier, not pretend every surface supports every model on day one.

## Try GPT-5.6 through Token Station

If you already use Token Station, GPT-5.6 is now another route family you can test in your coding-agent workflow.

Start with the direct OpenAI route for a simple API check. Use the same `openai/` route in your Codex setup for terminal coding tasks. Try the Copilot route if your workflow depends on GitHub Copilot's supported model catalog.

Token Station gives you one place to compare those routes without rewriting your agent stack for every model launch.

[Try Token Station](https://models.bytefuture.ai/intro.html)
Loading
Loading