GenOffice は、Electron 上に構築されたオープンソースの AI ネイティブなオフィススイートだ。ワープロ、表計算エディタ、プレゼンテーション作成ツール、PDF ビューアが、ひとつのシェルの下にタブでまとめられている。5 つのアプリすべてが共有する約束はひとつ、ファイル形式の忠実性だ。.docx、.xlsx、.pptx を開いて編集しても、触らなかった部分はバイト単位で完全に元のまま返ってくる。GenOffice は元のファイルを解析し、変更されたブロックだけを追跡し、保存時にはその狭い範囲のパッチを元の XML に差し込む。アーカイブの残りの部分はそのままコピーされ、手を加えられることはない。
すべてのアプリが同じ AI パネルを備えている。Docs ではバージョン履歴付きのブロック単位編集、Sheets ではライブのワークブックに対してツールを呼び出すエージェント、Slides では自由形式のコードではなく固定された検証済みプリミティブの集合だけを使ってプレゼンテーションを編集する、制約付きのレイアウトスクリプトエージェントだ。この 3 つはいずれも、ツール呼び出しループを担う agent-core と、設定されたモデルバックエンドとの通信を担う ai-provider という 2 つのパッケージを裏側で共有している。
この記事の要点はまさにそこにある。ai-provider はすでに素の OpenAI 互換 HTTP を話す。デフォルトでは、GenOffice はこれを Genspark に向けている。代わりに Token Station に向ければ、アプリ側は何も変わらない。変わるのはトークンの出どころだけだ。
Token Station で動かす理由
Genspark はサインインした瞬間から使えて、デフォルトとして正しい選択だ。ただし、それはひとつのアカウント、ひとつの固定モデルラインナップ、そして Genspark の条件でチャージするクレジット残高でもある。Token Station はこの関係の形を 2 つの点で変える。どちらも、毎日使うデスクトップアプリにとって重要な点だ。
| Genspark(デフォルト) | Token Station | |
|---|---|---|
| アカウント / クレジット | 単一アカウント、単一クレジットプール | 使った分だけの従量課金、月額・年額契約なし |
| モデル | 連携先が固定するラインナップ | 25 以上のプロバイダーにまたがる 250 以上のモデルをタスクごとに選択 |
| 価格 | Genspark のプランに紐づくクレジット | ひとつの API キー、プロバイダー料金そのまま、上乗せなし |
従量課金であって契約ではない。Token Station にはサブスクリプション階層がない。クレジットカードなしで無料登録でき、登録直後に 1 ドル分のクレジットが付与される。そこから先は、実際に呼び出したモデルに対してプロバイダーの料金をそのまま支払うだけで、定期的な費用も解約すべきものも発生しない。NVIDIA NIM のような一部のモデルはまったくの無料だ。
モデルを選ぶ自由。ゲートウェイアカウントはひとつのベンダーのラインナップに縛られない。GenOffice の Docs では長文編集に Claude を使い、Sheets では日常的な数式作業に安価なモデルへ切り替え、Slides ではデッキに合った画像対応モデルを選ぶ。すべて同じ API キー、同じ OpenAI 形式のエンドポイントで行え、プロバイダーごとの個別登録は不要だ。
Token Station は GenOffice のカスタムプロバイダー枠がもともと想定している OpenAI 互換のワイヤーフォーマットをそのまま話すので、組み込みはルーティングの変更であって、書き直しではない。
セットアップ:手元の GenOffice にパッチを当てる
以下は、GenOffice の AI トラフィックを Genspark から Token Station へルーティングし直す実際の変更点だ。自分の fork やブランチにそのまま適用できる。特定の GenOffice リリースに依存する内容ではない。
1. 前提条件をインストールし、ベースのビルドが動くことを確認する
マシンに Node.js と npm が必要だ。
git clone <your-fork-url> genoffice
cd genoffice
npm install
npm run dev
シェルが起動し、AI パネルが正常に開くことを確認する。この時点ではデフォルトで Genspark 上で動いており、ログアウト状態でメッセージを送信しない限りサインインを求められることはない。
2. 共有 provider パッケージに環境変数ベースの上書きを追加する
packages/ai-provider にはすでにカスタムプロバイダーが定義されている。任意の OpenAI 互換の baseUrl / apiKey / model だ。環境変数からそれを埋める小さな関数を追加する。これは、Genspark 自身のキー(GSK_API_KEY)に対してコードベースがすでに使っているのと同じパターンだ。
packages/ai-provider/src/providers.ts
export const TOKEN_STATION_BASE_URL = 'https://models.bytefuture.ai/v1'
const TOKEN_STATION_DEFAULT_MODEL = 'anthropic/claude-opus-4-8'
export function applyTokenStationEnvOverride(
settings: AiSettings,
env: NodeJS.ProcessEnv = process.env,
): AiSettings {
const apiKey = env.TOKEN_STATION_API_KEY
if (!apiKey) return settings
return {
provider: 'custom',
providers: {
...settings.providers,
custom: {
apiKey,
model: env.TOKEN_STATION_MODEL || TOKEN_STATION_DEFAULT_MODEL,
baseUrl: TOKEN_STATION_BASE_URL,
},
},
}
}
これを defaultAiSettings や resolveAiSettings と並べて、パッケージの index.ts からエクスポートする。
3. 各アプリで Genspark 強制をやめ、上書き関数を呼び出す
Docs、Sheets、Slides はそれぞれ ai:get-settings という IPC ハンドラーを登録しており、読み込みのたびに provider を Genspark へハードリセットしている。その行を削除し、代わりに新しい上書き関数を呼び出す。3 つのファイルすべてで形はまったく同じだ。
apps/docs/src/main/docs-main.ts(apps/slides/src/main/ai-ipc.ts と apps/sheets/src/main/sheets-main.ts でも同様)
// before
ipcMain.handle('ai:get-settings', (): AiSettings => {
const stored = readJson<Partial<AiSettings> & LegacyAiSettings>(SETTINGS_PATH(), {})
const settings = resolveAiSettings(stored, defaultAiSettings())
settings.provider = 'genspark' // ← delete this
return settings
})
// after
ipcMain.handle('ai:get-settings', (): AiSettings => {
const stored = readJson<Partial<AiSettings> & LegacyAiSettings>(SETTINGS_PATH(), {})
return applyTokenStationEnvOverride(resolveAiSettings(stored, defaultAiSettings()))
})
Sheets のハンドラーは 2 点だけ見た目が異なる。文字列リテラルではなく IPC チャンネル定数を受け取ること、そして最初に sessionFor(event) のチェックを呼ぶことだ。だが本質は同じで、genspark 強制の行を削除し、新しい上書き関数を呼ぶだけでよい。
4. API キーを取得し、環境変数に設定する
Token Station に登録し、ダッシュボードから API キーを取得したら、それを永続的な環境変数として設定し、ターミナルを再起動する(環境変数はそれ以降に起動したプロセスにのみ適用される)。
# Windows (PowerShell)
[Environment]::SetEnvironmentVariable("TOKEN_STATION_API_KEY", "gw_...", "User")
# macOS / Linux — add to your shell profile
export TOKEN_STATION_API_KEY=gw_...
任意設定として、TOKEN_STATION_MODEL に Token Station 上の provider/model 形式の ID(例えば openai/gpt-5.5)を設定すればデフォルトモデルを上書きできる。GenOffice を再起動すれば、Docs、Sheets、Slides でのチャット・編集・プランニングはすべて Token Station 上で動くようになる。Slides のワンショットのデッキ生成だけは追加のパッチが必要な機能で、これはステップ 5 で扱う。
5. Slides のデッキ生成にはもうひとつパッチが必要
Slides の generate_deck / regenerate_slide ツールは、もともと provider システムを完全に迂回して Genspark 専用のクラウドエンドポイントを直接呼び出していた。これらには 3 部構成の独自パッチが必要になる。Docs と Sheets だけをルーティングするなら、ステップ 4 で止めてよい。
apps/slides/src/renderer/ai/slides-skill.ts:DeckAccess インターフェースにオプションのフィールドを 2 つ追加する。同期の aiProvider() ゲッターと、HTML マーカーの代わりに検証済みの要素リストを返す composePageElements() メソッドだ。そのうえで、両方のツールの判定を「Genspark 専用のハードコード」から現在の provider ベースの判定に切り替える。
const useCloud = cloudAvailable
&& (access.aiProvider?.() ?? 'genspark') === 'genspark'
if (!useCloud) {
// fall back to runLocalDeckGeneration() / runLocalRegenerateSlide()
}
apps/slides/src/renderer/ai/local-deck-gen.ts(新規ファイル):実際に構成処理を行うモジュールで、設定された provider に各ページのレイアウトを JSON(図形、テキストボックス、チャート、画像)として要求し、それを検証したうえで、アプリ自身のエージェントツールがすでに使っている add_shape / add_text_box / add_chart / insert_web_image のプリミティブで構築する。
apps/slides/src/renderer/ai/AiPanel.tsx:新しく追加した 2 つの DeckAccess フィールドを、generateStyleSkill / planDeckOutline がすでに使っているのと同じリクエストパスに接続する。ここは見落としやすい部分だ。接続しないと aiProvider が undefined のままになり、上記の判定が静かに Genspark へフォールバックしてしまう。
aiProvider: () => settingsRef.current.provider,
composePageElements: async (args) => {
const { system, user } = buildPageComposePrompt(args)
const r = await runLlmOnce(system, user, undefined, true, args.signal)
if (!r.ok || !r.text) return { ok: false, error: r.error ?? tGlobal('aiErrEmptyOutput') }
return parsePageElementsJson(r.text, args.canvasW, args.canvasH)
},
ローカルパス v1 の既知の制約:現状は追加専用で、新しいページは常に現在の最後のスライドを複製する。「デッキ全体の置き換え」にはまだ対応していない。ローカル版の regenerate_slide もコンテンツ要素のみを置き換え、背景とテーマの継承には手を加えない点がクラウド版と異なる。
実際の動作
アプリごとに 1 本、合計 3 本の短いデモ。すべて Token Station 上で動いている。
もっと詳しく
- Token Station:料金・登録
- Token Station:モデルカタログ全体
- GenOffice:GitHub ソースコード
- GenOffice:コントリビューションガイド
models.bytefuture.ai で登録し(1 ドル分の無料クレジット、クレジットカード不要)、TOKEN_STATION_API_KEY をエクスポートしたら、GenOffice を再起動する。ひとつの API キー、ひとつのエンドポイントで、Docs・Sheets・Slides のセッションに必要なすべてのモデルが使える。