Skip to content

ja plugin dev components page

langbot-wiki-sync[bot] edited this page Jul 29, 2026 · 1 revision

コンポーネント:ページ

Pageコンポーネントを使用すると、プラグインはLangBot WebUIのサイドバーにカスタムビジュアルページを登録できます。ページはiframeサンドボックス内で実行され、Page SDKを介してホストと通信し、プラグインのバックエンドAPIを呼び出すことができます。

ユースケース

  • 管理パネル:プラグインに視覚的な設定やデータ管理インターフェースを提供(例:FAQ管理、分析ダッシュボード)
  • データ表示:ランタイムの統計データ、ログ、チャートなどを表示
  • インタラクティブツール:フォーム、エディタなどの対話式インターフェースを提供

ページコンポーネントの追加

プラグインディレクトリでコマンドを実行します:

lbp comp Page

ページ名を入力すると、components/pages/ディレクトリにページファイルが生成されます:

├── components
│   └── pages
│       └── dashboard
│           ├── dashboard.yaml   # ページマニフェスト
│           ├── dashboard.py     # バックエンドハンドラー
│           ├── index.html       # ページエントリポイント
│           └── i18n             # 翻訳ファイル(オプション)
│               ├── en_US.json
│               └── ja_JP.json

manifest.yamlにもコンポーネント検出設定が追加されます:

spec:
  components:
    Page:
      fromDirs:
      - path: components/pages/
        maxDepth: 2

マニフェストファイル:ページ

apiVersion: v1  # 変更しないでください
kind: Page  # 変更しないでください
metadata:
  name: dashboard  # プラグイン内で一意のページID
  label:
    en_US: Dashboard  # WebUIサイドバーに表示される名前、多言語対応
    ja_JP: ダッシュボード
spec:
  path: index.html  # HTMLエントリファイル(このYAMLファイルからの相対パス)
execution:
  python:
    path: dashboard.py  # バックエンドハンドラーファイル
    attr: DashboardPage  # ハンドラークラス名

バックエンド処理

PageコンポーネントのバックエンドハンドラーはPage基底クラスを継承し、handle_apiメソッドを実装してフロントエンドページからのAPIリクエストを処理します。

from langbot_plugin.api.definition.components.page import Page, PageRequest, PageResponse

class DashboardPage(Page):

    async def handle_api(self, request: PageRequest) -> PageResponse:
        # request.endpoint: APIエンドポイントパス(例:'/stats')
        # request.method:   HTTPメソッド(GET、POST、PUT、DELETE)
        # request.body:     リクエストボディ(解析済みJSON、またはNone)

        if request.endpoint == '/stats' and request.method == 'GET':
            # self.pluginでプラグインインスタンスの共有状態にアクセス
            return PageResponse.ok({
                'total': len(self.plugin.entries),
            })

        return PageResponse.fail(f'不明なエンドポイント: {request.endpoint}')

PageRequestフィールド

フィールド 説明
endpoint str APIエンドポイントパス(例:'/entries'
method str HTTPメソッド(GETPOSTPUTDELETE
body Any リクエストボディ(解析済みJSON、またはNone

PageResponseの構築

メソッド 説明
PageResponse.ok(data) 成功レスポンス。dataはJSON変換可能な任意の値
PageResponse.fail(error) エラーレスポンス。errorはエラーメッセージ文字列

フロントエンドページ開発

HTMLファイルにPage SDKを読み込んで、プラグインバックエンドと通信します:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <style>
    body {
      background: var(--langbot-bg, #ffffff);
      color: var(--langbot-text, #0a0a0a);
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
      padding: 24px;
    }
  </style>
</head>
<body>
  <h1 data-i18n="title">ダッシュボード</h1>
  <p id="stats"></p>

  <script src="/api/v1/plugins/_sdk/page-sdk.js"></script>
  <script>
    langbot.onReady(async function(ctx) {
      // バックエンドAPIを呼び出す
      var data = await langbot.api('/stats', null, 'GET');
      document.getElementById('stats').textContent = '合計: ' + data.total;
    });
  </script>
</body>
</html>

Page SDK API

メソッド 説明
langbot.onReady(callback) SDK準備完了時に呼ばれる。callbackctxthemelanguageを含む)を受け取る
langbot.api(endpoint, body?, method?) プラグインのhandle_apiを呼び出す。Promiseを返す
langbot.t(key, fallback?) 翻訳文字列を取得
langbot.onThemeChange(callback) テーマ変更時のコールバック
langbot.onLanguageChange(callback) 言語変更時のコールバック
langbot.applyI18n() data-i18n翻訳を手動で再適用

ダークモード

SDKはページにCSSカスタムプロパティを自動設定します。直接使用できます:

CSS変数 用途
--langbot-bg ページ背景色
--langbot-bg-card カード背景色
--langbot-text メインテキスト色
--langbot-text-muted サブテキスト色
--langbot-border ボーダー色
--langbot-accent アクセント色

ページi18n

ページディレクトリ内にi18n/ディレクトリを作成し、JSON翻訳ファイルを配置します:

pages/dashboard/
├── index.html
└── i18n/
    ├── en_US.json
    └── ja_JP.json

翻訳ファイルはフラットなJSONキーバリューペアです:

{
  "title": "ダッシュボード",
  "totalEntries": "エントリ数"
}

HTML要素にdata-i18n属性を追加すると、SDKが自動的にテキストを翻訳します:

<h1 data-i18n="title">Dashboard</h1>

完全な例:FAQ管理ページ

FAQエントリのCRUD操作を実装した完全なPageコンポーネントの例です。

バックエンドハンドラーcomponents/pages/manager/manager.py):

from langbot_plugin.api.definition.components.page import Page, PageRequest, PageResponse

class ManagerPage(Page):

    async def handle_api(self, request: PageRequest) -> PageResponse:
        plugin = self.plugin

        if request.endpoint == '/entries' and request.method == 'GET':
            return PageResponse.ok({'entries': plugin.entries})

        if request.endpoint == '/entries' and request.method == 'POST':
            question = (request.body or {}).get('question', '').strip()
            answer = (request.body or {}).get('answer', '').strip()
            if not question or not answer:
                return PageResponse.fail('質問と回答は必須です')
            entry = plugin.add_entry(question, answer)
            await plugin.persist()
            return PageResponse.ok({'entry': entry})

        if request.endpoint == '/entries' and request.method == 'DELETE':
            entry_id = (request.body or {}).get('id', '')
            if plugin.delete_entry(entry_id):
                await plugin.persist()
                return PageResponse.ok({'deleted': entry_id})
            return PageResponse.fail('エントリが見つかりません')

        return PageResponse.fail(f'不明: {request.method} {request.endpoint}')

フロントエンドページcomponents/pages/manager/index.html)ではlangbot.api()でバックエンドを呼び出します:

// エントリを読み込む
var data = await langbot.api('/entries', null, 'GET');

// エントリを追加
await langbot.api('/entries', { question: '...', answer: '...' }, 'POST');

// エントリを削除
await langbot.api('/entries', { id: '...' }, 'DELETE');

完全なサンプルコードはFAQManagerプラグインを参照してください。

注意事項

  • ページはsandbox="allow-scripts allow-forms"のiframe内で実行され、ポップアップを開いたり親ページをナビゲートすることはできません
  • self.pluginでプラグインインスタンスの共有状態にアクセスできます — PageとToolコンポーネントはデータを共有できます
  • PageResponse.ok()PageResponse.fail()を使用してレスポンスを構築し、一貫したフォーマットを確保してください
  • Page SDKの<script>タグは、langbotオブジェクトを使用するコードの前に配置する必要があります

LangBot Documentation

Home

简体中文
指南
开发者
文章
API 参考
Other pages
English
Guides
Developers
Articles
API Reference
Other pages
日本語
ガイド
開発者
記事
API リファレンス
Other pages

Clone this wiki locally