SNA

組み込み

Electron アプリや Node サービスの中で SNA を実行します。

startSnaServer() は standalone サーバを管理された子プロセスとして fork します。ホストに応じて、2 つのエントリポイントから選びます。

import { startSnaServer } from "@sna-sdk/core/node";      // 普通の Node
import { startSnaServer } from "@sna-sdk/core/electron";  // Electron

Electron 用エントリポイントは asar-unpacked パスを解決し、 アプリが Electron ランタイム向けにリビルドした better-sqlite3 バイナリを見つけます。

ライフサイクル

const sna = await startSnaServer({
  appId: "my-electron-app",
  port: 3099,
  dbPath: path.join(app.getPath("userData"), "sna.db"),
  maxSessions: 20,
  permissionMode: "acceptEdits",
  runtimePaths: {
    claudeCode: "/opt/homebrew/bin/claude",
  },
  onLog: (line) => console.log("[sna]", line),
});

// sna.process : spawn された ChildProcess
// sna.port    : 実際のポート (自動選択後)
// sna.appId   : このサーバが作る session に付く owner ID
// sna.connection : SDK client に渡す connection object
// sna.stop()  : graceful SIGTERM

Forked mode では、親プロセスとの IPC 接続が切れると child server も 終了します。Token はその server process の寿命に紐づくものです。 長期間残るユーザー設定に保存せず、sna.connection の中で server handle と 一緒に渡してください。

Electron チェックリスト

  • node_modules/@sna-sdk/core/** を electron-builder の asarUnpack に追加します。実行時にサーバの dist/ を読める必要があります。
  • Electron ランタイム用にネイティブ依存をリビルド:
    npx electron-rebuild -f -w better-sqlite3
  • dbPathapp.getPath("userData") 配下に置きます。これにより、 アップグレード後も SQLite ファイルが残ります。
  • ユーザーが選んだランタイム CLI path は app settings に保存し、SNA 起動時に runtimePaths で渡します。
  • カスタムビルドの better_sqlite3.node をデフォルト位置外に置く 場合は、nativeBinding を渡します。

レンダラから接続

レンダラプロセスは組み込みサーバを通常の HTTP/WS ホストとして使います。

import { SnaClient } from "@sna-sdk/client";

const client = new SnaClient(sna.connection);

<SnaProvider> はヘルパーエンドポイント GET /api/sna-port を 自動的に使います。そのため、React アプリでは IPC なしでレンダラが ポートを検出できます。Host が同じ信頼済み app endpoint から { baseUrl, authToken } を返す場合、SnaProvider はその値を connection として自動的に使います。この helper は host app の境界内に置くのが安全です。 ランタイム自身の /api/sna-port ルートは保護されており、同じ token が SSE と WebSocket traffic も認証します。

目次