// 開発者ガイド

プラグイン開発者向けドキュメント

AnBoWork デスクトップ アプリ用のプラグインを構築します。AI 用の新しいツールを追加し、セッションの隣に独自のパネルをドッキングし、システム通知を送信し、新しいファイル形式を解析します。開始するには、manifest.json 1 つとエントリ スクリプト 1 つで十分です。

01概要

AnBoWork プラグインは、プレーンな Node.js プログラムです。インストール後、アプリはスタンドアロンの子プロセス (純粋なノード、Electron API なし) としてフォークし、プロセス間メッセージを介して通信します。 SDK パッケージは必要ありません。必要なのはprocess.on('message')とprocess.send()だけです。

プラグインが実行できるすべてのことは、manifest.json で静的に宣言されます。プレインストール同意ページとマーケットプレイスのレビューにより、プラグイン コードを実行せずに、追加するツールと必要な権限を知ることができます。すべての UI (ツールバー アイコン、設定、コマンド パレット、コンテキスト メニュー) は、ホストによって宣言からレンダリングされます。プラグイン コードはメイン ウィンドウ内で実行されることはありません。ドッキング ビューとフローティング パネルのみが独自の HTML であり、独立したサンドボックス ページで実行されます。

機能の概要

マニフェストフィールド能力ユーザーが目にする場所
toolsAI 用の呼び出し可能なツールを追加するAI が会話の中で自動的に呼び出します。ツール呼び出しはセッションに表示されます
viewsセッションの右側のサイドバーにドッキングされた永続ビューセッションツールバーの追加アイコンにより、右側にページが開きます
uiスタンドアロンのフローティング ウィンドウプラグイン一覧の「⋯」メニューから開きます
sessionActionセッションツールバーの永続アクションアイコンワンクリックで指定したツールが実行されます
configuration設定ページのエントリ設定 → プラグイン設定;値は呼び出しごとに渡されます
commandsCtrl/Cmd+K コマンド パレットのエントリコマンドパレット
keybindingsグローバルキーボードショートカットキーの組み合わせによりコマンドがトリガーされます
menusセッションのコンテキストメニュー項目セッション行の「⋯」/右クリック メニュー
documentParsers入力ボックスにドロップされたファイルを解析しますユーザーが一致するファイルをドロップすると自動的に呼び出されます
activationEventsアプリと一緒に始める見えない;バックグラウンドタイマーが必要なプラグイン用
permissions必要な権限を宣言するプレインストール同意ページ

02クイックスタート

最小限のプラグインに必要なファイルは 2 つだけです。

my-plugin/
├── manifest.json   # plugin manifest (required)
├── index.js        # entry script, referenced by manifest.main (required)
├── view.html       # docked view page (optional, manifest.views[].entry)
└── ui.html         # floating panel page (optional, manifest.ui.entry)

1.manifest.jsonを書く

{
  "id": "com.example.hello",
  "name": "Hello Plugin",
  "version": "1.0.0",
  "description": "Say hello to the user.",
  "main": "index.js",
  "permissions": [],
  "tools": [
    {
      "name": "say_hello",
      "summary": "Greet the user by name",
      "description": "Return a greeting for the given name. Call this when the user explicitly asks the plugin to say hello.",
      "parameters": {
        "type": "object",
        "properties": {
          "name": { "type": "string", "description": "Who to greet." }
        },
        "required": ["name"]
      }
    }
  ]
}

2. エントリースクリプトを書く

// The entry script runs in a standalone Node.js child process (ELECTRON_RUN_AS_NODE=1).
// Only Node built-ins and dependencies shipped inside the plugin folder are available;
// there is no Electron API.
process.on('message', (msg) => {
  if (!msg || msg.type !== 'call_tool') return;
  const { requestId, toolName, params } = msg;
  try {
    if (toolName !== 'say_hello') throw new Error(`unknown tool: ${toolName}`);
    process.send({
      type: 'tool_result',
      requestId,
      content: [{ type: 'text', text: `Hello, ${params.name}!` }],
    });
  } catch (err) {
    process.send({ type: 'tool_error', requestId, message: err.message });
  }
});

3. アプリにインストールする

AnBoWork → トップバー「ツール」→「プラグイン」→右上隅の「ローカルにインストール」を開き、プラグイン フォルダー (またはその zip) を選択します。同意ページには、インストール前に宣言された権限とすべてのツールがリストされます。確認して有効にします。

4. 試してみる

どのセッションでも、AI に「プラグインにアリスに挨拶するよう依頼してください」と指示します。ツールの説明に基づいて、AI は say_hello を呼び出すことを決定し、呼び出しとその結果がセッションに表示されます。

ヒント
AnBoWork 内の AI はプラグインを生成することもできます (「X を実行するプラグインを書いて」と言うと、create_local_plugin が呼び出されます)。生成されたプラグインは、プラグイン ページのコードを確認して手動で有効にするまで、デフォルトでは無効になっています。このガイドは、AI によって生成されたプラグインの読み取りと変更にも同様に適用されます。

03マニフェストフィールド

分野タイプ必須説明
idstringはいリバースドメインスタイル、例: com.example.my-plugin。文字、数字、ドット、ハイフンのみ。一度作成すると不変です。同じ ID を再度インストールすると、再インストールとして扱われます。
namestringはいプラグイン名。 description とともにコンテキストとしてモデルに供給されるため、英語を推奨します。
versionstringはいセマンティックバージョン。マーケットプレイスはそれを使用して更新を検出します。
descriptionstringはいプラグインの機能を説明する 1 文 (英語)。
authorstringいいえ著者。
readmestringいいえマーケットプレイスの詳細ページに表示される長い形式の説明は、Markdown をサポートしています。その中の画像は https URL である必要があります。zip にバンドルされているファイルへの相対パスはサポートされていません。
iconstringいいえマーケットプレイスのリストと詳細ページに表示されるアイコン — zip にバンドルされているファイルへの相対パス (例: icon.png)。 SVG ではなく、少なくとも 128×128 の PNG である必要があります。
mainstringはいプラグイン フォルダーを基準としたエントリ スクリプト。 .. フォルダーをエスケープすることはできません。
permissionsstring[]はいnetwork / filesystem / notifications;空の配列である可能性があります。 「権限モデル」を参照してください。
toolsobject[]はいツール宣言。空の配列である可能性があります。 「ツールと通話プロトコル」を参照してください。
documentParsersobject[]いいえファイル解析機能。
uiobjectいいえフローティングパネル:{ entry, title }
viewsobject[]いいえドッキングされたビュー:{ id, title, icon, entry, width? }
sessionActionobjectいいえツールバー アイコン。プラグインごとに最大 1 つ。
configurationobject[]いいえ設定エントリのリスト。
commandsobject[]いいえコマンドパレットのエントリ。
keybindingsobject[]いいえショートカット。 command は、commands[] のエントリの tool を参照する必要があります。参照しない場合、インストールは拒否されます。
menusobjectいいえ現時点では、session/context の場所のみが利用可能です。
activationEventsstring[]いいえ今のところonStartupFinishedのみです。

テキストの言語規則

マニフェスト内のテキストには 2 つの対象読者がいます。 モデルの場合: name、description、tools[].description、tools[].parameters.*.description。これらを英語で書きましょう。モデルは英語のツールの説明を理解し、パラメータをより確実に入力します。 人: tools[].summary (同意ページの 1 行要約)、ui.title、views[].title、sessionAction.tooltip、configuration[].label、commands[].title、menus 内のtitle。これらをターゲット ユーザーの言語で記述します。

{
  "id": "com.example.full",
  "name": "Full Example",
  "version": "1.2.0",
  "description": "Every contribution point in one manifest.",
  "author": "Example Inc.",
  "readme": "## Full Example\n\nLonger Markdown shown on the marketplace detail page. Images must be https URLs.",
  "icon": "icon.png",
  "main": "index.js",
  "permissions": ["filesystem", "network", "notifications"],
  "activationEvents": ["onStartupFinished"],
  "tools": [
    {
      "name": "do_something",
      "summary": "Do one thing to the current project",
      "description": "…English. State clearly when to call this and when not to…",
      "parameters": { "type": "object", "properties": {}, "required": [] },
      "renderAs": "checklist"
    },
    { "name": "is_available", "summary": "Whether the current folder applies", "description": "…", "parameters": { "type": "object", "properties": {} } },
    { "name": "list_modes", "summary": "List selectable modes", "description": "…", "parameters": { "type": "object", "properties": {} } }
  ],
  "documentParsers": [
    { "mimeType": "text/markdown", "toolName": "parse_markdown" }
  ],
  "ui": { "entry": "ui.html", "title": "Example Panel" },
  "views": [
    { "id": "board", "title": "Example Board", "icon": "checklist", "entry": "view.html", "width": 380 }
  ],
  "sessionAction": {
    "tool": "do_something",
    "icon": "git-branch",
    "tooltip": "Do one thing to the current project",
    "visibleTool": "is_available"
  },
  "configuration": [
    { "id": "mode", "label": "Mode", "type": "select", "optionsTool": "list_modes", "defaultValue": "auto" },
    { "id": "verbose", "label": "Verbose output", "type": "boolean", "defaultValue": false },
    { "id": "prefix", "label": "Prefix", "type": "string", "defaultValue": "" },
    { "id": "limit", "label": "Max items", "type": "number", "defaultValue": 20 }
  ],
  "commands": [
    { "tool": "do_something", "icon": "git-branch", "title": "Do one thing to the current project" }
  ],
  "keybindings": [
    { "command": "do_something", "key": "mod+shift+d" }
  ],
  "menus": {
    "session/context": [
      { "tool": "do_something", "icon": "git-branch", "title": "Do one thing to this session" }
    ]
  }
}

04権限モデル

permissions は、コードが実際に行うことを正直に反映する必要があります。プレインストール同意ページにはそれぞれの同意ページがリストされているため、ユーザーはインストールするかどうかを決定できます。マーケットプレイスのレビューでは、宣言とコードもチェックされます。

許可申告しなければならない場合ホストの扱い方
filesystemユーザー ファイルの読み取りまたは書き込み (プロジェクト コードの読み取り、ドキュメントの生成、ホーム フォルダーへのデータの保存)ユーザーに示されるインフォームド・コンセント。
networkネットワーク リクエストの実行 (サードパーティ API、ダウンロード)ユーザーに示されるインフォームド・コンセント。
notificationsshow_notification リバース RPC 経由でシステム通知を表示するEnforced: 宣言なしで呼び出すと、host_error が返され、通知は表示されません。
注記
プラグインの子プロセスは完全な Node.js 環境です。 filesystem と network は現時点では同意レベルの宣言であり、実行時サンドボックスではありません。ホストは fs や fetch をインターセプトしません。だからこそ、宣言は正直でなければなりません。過少宣言したプラグインはマーケットプレイスのレビューで拒否され、発見された時点でユーザーの信頼を失います。どちらも過剰に宣言しないでください (未使用の権限はユーザーを躊躇させます)。

プライバシーとデータ

context.cwd はユーザーのプロジェクト フォルダーであり、ソース コードと機密性の高い構成が含まれる場合があります。ツールの引数にはユーザーの会話が含まれる場合があります。機能で必要な場合を除き、このデータをネットワーク経由で送信しないでください。送信する場合は、何を誰に送信するかを description と summary に明記してください。プラグイン自体の永続データは、プラグイン ID に基づいて名前が付けられたユーザーのホーム フォルダー内のファイルに保存されるため、アンインストール時に見つけやすくなります。

05ツールと通話プロトコル

宣言

分野説明
name小文字とアンダースコアで構成されるツール名。アプリ全体で一意です (組み込みツールや他のプラグインのツールとともにモデルに登録されます)。
descriptionモデルの説明 (英語)。ツールが何をするか、ツールを呼び出す必要がある場合と呼び出すべきではない場合にユーザーが言うことの 3 つのことを述べます。これは、AI がプラグインを使用するかどうかを決定する最も重要なフィールドです。
summary同意ページに表示される人間が判読できる 1 行の概要。オプションですが、強くお勧めします。それ以外の場合は、代わりに切り詰められた説明が表示されます。
parametersすべてのプロパティに description が付いている標準の JSON スキーマ オブジェクト。モデルはそこから引数を入力し、ホストは追加の検証なしでそれらを渡すため、コード内の必須フィールドを確認してください。
renderAsオプション。現在は checklist のみ: ホストは呼び出し引数からの todos 配列をチェックリスト カードとしてレンダリングします。以下を参照してください。
注記
モデルは、ここで tools[] で宣言されたツール名のみを呼び出すことができます。sessionAction.tool、commands[].tool、および menus 内の tool フィールドは、インストール時に空でない文字列であるかどうかのみチェックされます。ホストは、名前が tools[] で宣言されているかどうかを検証しません が、ボタン、ショートカット、またはメニュー項目がトリガーされたときにその名前で呼び出しをディスパッチします。したがって、純粋に UI によってトリガーされたアクションは、tools[] に表示されることなく、完全に独自の index.js で処理できます。ただし、AI はそれを確認したり呼び出したりすることはできません。クリックとチャット リクエストに応じて動作する AI の両方で同じアクションをトリガーできるようにしたい場合は、tools[] でも同じ名前を宣言して、両方のエントリ ポイントが 1 つのハンドラーを共有するようにします。 UI のみを維持する場合は、宣言しないままにしておきます。完全に見えるようにするためだけにエントリを追加する必要はありません。

メッセージプロトコル

ホストは call_tool を送信します。プラグインは、同じ requestId を含む tool_result または tool_error で応答する必要があります。 30 秒以内に応答がない呼び出しはタイムアウトになり、モデルはエラーを受け取ります。

// host → plugin
{
  "type": "call_tool",
  "requestId": "0b2d…",          // unique per call, echo it back unchanged
  "toolName": "do_something",
  "params": { "name": "…" },     // arguments validated against tools[].parameters
  "context": {
    "cwd": "/Users/me/project",  // project folder of the calling session; a temp folder for chat sessions; empty string for document parsing
    "config": { "mode": "auto", "verbose": false }   // present only when configuration is declared; keys are configuration[].id
  }
}

content は、text ブロックと image ブロックのみを受け入れます (base64 data に mimeType を加えたイメージ)。他のタイプはドロップされます。 details は、モデルに決して供給されない任意の構造化データです。これはホスト UI レンダリングと独自のドッキング ビュー用です。

ファイル結果: ファイル カード

// When the result is a file: include the absolute path and file name. The session
// renders a clickable file card that previews in-app (docx/xlsx/pdf/markdown/code…).
process.send({
  type: 'tool_result',
  requestId,
  content: [{ type: 'text', text: `Generated [${fileName}](${filePath})` }],
  details: { filePath, fileName },
});

チェックリスト レンダリング: renderAs チェックリスト

// For tools with renderAs: "checklist", the host renders the todos array from the call arguments:
{
  "todos": [
    { "id": "1", "content": "Initialize repository", "status": "completed" },
    { "id": "2", "content": "Write unit tests", "status": "in_progress" },
    { "id": "3", "content": "Publish", "status": "pending" }
  ]
}

適切な説明を書く

トリガーを命令文 (「ユーザーが…を要求したときにこれを呼び出す」) で記述し、除外項目を記述します (「… ではこれを呼び出さないでください」)。結果がファイルの場合は、生成されたと主張するのではなく、返されたファイル リンクを参照するようにモデルに依頼します。引数が外部生成 API に転送される場合は、どの言語で引数を使用するかを指定します。「ToDo の管理」などのワンライナーは避けてください。モデルはいつツールを使用すべきかわかりません。

06ドッキングされたビュー (ビュー)

ドッキング ビューは、セッションの右側のサイドバーにある永続的なページです。追加のアイコンがセッション ツールバーに表示され、開くと HTML が右側に表示されます。ページの状態 (スクロール位置、下書き) は、セッションの切り替えや折りたたみ/展開後も存続します。これは、VS Code のサイドバー ビューと同じセマンティクスです。

分野説明
idプラグイン内で一意です。
titleアイコンのツールチップ テキスト (人間が判読できる)。
iconホスト許可リストから選択します: git-branch、checklist。アプリ全体でアイコンの一貫性を保ちます。カスタム画像は受け付けられません。
entryプラグインフォルダーを基準とした HTML ファイル。
widthオプションのデフォルトのパネル幅 (ピクセル単位)、240 ~ 640、デフォルトは 360。ユーザーはドラッグしてサイズを変更でき、サイズは記憶されます。

ページの実行時間

このページはサンドボックス (sandbox + contextIsolation、ノードなし、ホスト アプリ データへのアクセスなし) で実行され、window.pluginHost のいくつかのメソッドを通じてのみ独自のプラグイン プロセスと通信できます。独自のスタイルを持ち込んでください。以下の例のように、アプリの明暗スキームに従うことをお勧めします。

interface PluginHost {
  // Call a tool declared in this plugin's manifest.tools; same call_tool channel the AI uses
  invoke(toolName: string, params: unknown): Promise<
    { content: unknown[]; details?: unknown } | { error: string }
  >;
  // Subscribe to ui_push messages from the plugin process; returns an unsubscribe function
  onPush(callback: (channel: string, payload: unknown) => void): () => void;
  // Current light/dark scheme and subsequent changes
  getColorScheme(): Promise<'light' | 'dark'>;
  onColorSchemeChange(callback: (scheme: 'light' | 'dark') => void): () => void;
}
declare const pluginHost: PluginHost; // exposed as window.pluginHost

推奨パターン: 最初の読み込み時に、invoke() で独自のクエリ ツールの 1 つを呼び出し、details で構造化データを返すようにします。その後、ポーリングの代わりに ui_push を使用して、プラグイン プロセスからのすべての変更をプッシュします。 AI が会話内のデータを変更すると、パネルはすぐに更新されます。

07フローティングパネル (ui)

ui: { entry, title } ユーザーがプラグイン リストの「⋯」メニューから開くスタンドアロンのフローティング ウィンドウ (900×700) を宣言します。閉じると破壊されます。ページ環境と window.pluginHost API はドッキング ビューと同一であり、ui_push はフローティング パネルとドッキング ビューの両方に配信されます。時々開く大きなパネルに適しています。セッションの隣に置くコンテンツには views を使用します。

08セッションツールバーアイコン (sessionAction)

永続アイコンはプラグインごとに最大 1 つです。これをクリックすると、空の引数を指定して tool が呼び出されるため、このツールはパラメーターなしで意味のある処理を実行する必要があります。

分野説明
toolクリックで呼び出すツール。
icon許可リストに登録されたアイコン名。
tooltipホバーテキスト。
visibleToolオプション。設定すると、レンダリング前に空の引数を指定して呼び出され、結果のブール値 details.visible によってアイコンが表示されるかどうかが決まります。 「現在のフォルダーは git リポジトリであるか」などの実行時チェックに役立ちます。
// The host calls visibleTool with empty params and shows the icon based on details.visible
process.send({
  type: 'tool_result',
  requestId,
  content: [{ type: 'text', text: isGitRepo ? 'git repo' : 'not a git repo' }],
  details: { visible: isGitRepo },
});

09設定(構成)

宣言されたエントリは、設定ページのプラグイン設定の下に表示されます。ホストは、ユーザーが変更した値を保存し、呼び出しが AI、ツールバー アイコン、またはパネルからのものであるかどうかに関係なく、call_tool (id によってキー設定され、defaultValue にフォールバック) ごとにそれらを context.config として渡します。それらを求める必要はありません。

type次のようにレンダリングされますデフォルト値のタイプ
select単一選択リスト。オプションはoptionsToolからですstring
booleanトグルスイッチboolean
stringテキスト入力、ブラーにコミットstring
number数値入力number
// For type: "select" settings, the host calls optionsTool with empty params to fetch options
process.send({
  type: 'tool_result',
  requestId,
  content: [{ type: 'text', text: '2 options' }],
  details: {
    options: [
      { value: 'fast', label: 'Fast' },
      { value: 'accurate', label: 'Accurate' },
    ],
  },
});
// The host automatically prepends an "Auto" option whose value equals this
// configuration entry's defaultValue; the plugin must not return it again.

10コマンドパレット/ショートカット/コンテキストメニュー

3 つはすべて、「空の引数を使用してツールを呼び出す」ための異なるエントリ ポイントです。プラグインは複数を宣言できます。

分野形説明
commands{ tool, icon, title }[]Ctrl/Cmd+K コマンド パレットに表示され、ユーザーが検索した後にトリガーされます。
keybindings{ command, key }[]command は、commands[] のエントリの tool と等しくなければなりません。 key は mod+shift+g 表記を使用します。ここで、mod は macOS では Cmd、その他の場所では Ctrl です。他のショートカットとの競合は静的にチェックされないため、一般的ではない組み合わせを選択してください。
menus{ "session/context": { tool, icon, title }[] }セッション行のメニューに追加されました。現時点ではこの場所のみが利用可能です。

11ドキュメントパーサー (documentParsers)

ユーザーがファイルを入力ボックスにドロップすると、ホストは有効なプラグインによって宣言されたパーサーを MIME タイプで検索し、ファイルの内容を Base64 として一致する toolName に渡します。これは AI が呼び出すことを決定したツールではないため、ではなく tools の下にパーサー ツールをリストしてください。そうしないと、AI 呼び出し可能なツールとして公開されます。

// The toolName declared in documentParsers is called when the user drops a file into the input:
// params = { base64: "<file content as base64>" }
// Return: details must be { success: true, text } or { success: false, reason }
process.on('message', (msg) => {
  if (msg.type !== 'call_tool' || msg.toolName !== 'parse_markdown') return;
  const text = Buffer.from(msg.params.base64, 'base64').toString('utf8');
  process.send({
    type: 'tool_result',
    requestId: msg.requestId,
    content: [{ type: 'text', text: 'parsed' }],
    details: { success: true, text },
  });
});

12リバース RPC (host_request)

プラグイン プロセスには Electron API がありません。実際のシステム機能が必要な場合、ホストに host_request を送信し、ホストは host_response または host_error で応答します。このチャンネルはcall_toolから完全に独立しています。ツール呼び出しの処理中またはタイマーから使用できます。

capabilityparamsresult前提条件
show_notification{ title, body?, viewId? }{ shown: true } / { shown: false, reason: "disabled" | "unsupported" }notifications 権限が必要です。ユーザーが設定でデスクトップ通知をオフにした場合、エラーではなく無効を返します。 viewId がドッキング ビューの 1 つをポイントしている場合、通知をクリックするとアプリが前面に表示され、そのビューが展開されます。
render_pdf{ outputPath, title, content }{}コンテンツはマークダウンです。ホストは、内蔵レンダラーを使用して PDF を OutputPath にレンダリングします。
const crypto = require('crypto');
const pending = new Map();

function requestHost(capability, params) {
  const requestId = crypto.randomUUID();
  return new Promise((resolve, reject) => {
    const timer = setTimeout(() => {
      pending.delete(requestId);
      reject(new Error(`host capability "${capability}" timed out`));
    }, 30_000);
    pending.set(requestId, { resolve, reject, timer });
    process.send({ type: 'host_request', requestId, capability, params });
  });
}

process.on('message', (msg) => {
  if (msg.type === 'host_response' || msg.type === 'host_error') {
    const p = pending.get(msg.requestId);
    if (!p) return;
    pending.delete(msg.requestId);
    clearTimeout(p.timer);
    if (msg.type === 'host_error') p.reject(new Error(msg.message));
    else p.resolve(msg.result);
  }
});

// usage
await requestHost('show_notification', {
  title: '3 todos for today',
  body: '• Write weekly report\n• Reply to emails',
  viewId: 'board',      // optional: expand this docked view when the notification is clicked
});
// => { shown: true } or { shown: false, reason: 'disabled' | 'unsupported' }

await requestHost('render_pdf', {
  outputPath: '/abs/path/report.pdf',
  title: 'Report',
  content: '# Title\n\nBody (Markdown)',
});

13ライフサイクル

ステージ行動
始めるデフォルトでは遅延: アプリは起動されず、ツール (AI、ツールバー アイコン、パネル、コマンド、ドキュメント解析) の 1 つへの最初の呼び出し時にフォークされます。 activationEvents: ["onStartupFinished"] を宣言するプラグインは、アプリの起動終了直後に開始されます。これは、バックグラウンド タイマー (リマインダー、ポーリング) を必要とするプラグインにのみ使用し、通常のツール プラグインには使用しません。
居住者プロセスは開始されると存続し、ツール呼び出し全体で再利用されます。状態をメモリにキャッシュできますが、いつでも再起動できることを前提としています。
クラッシュプロセスが予期せず終了した場合、ホストはすぐにプロセスを再起動し、その後 5 秒後と 15 秒後に再起動します。 3 回連続して失敗すると、「クラッシュ」とマークされ、再試行されなくなります。ユーザーはプラグイン ページでステータスを確認できます。実行中の呼び出しはすべてエラーを返します。
無効化/アンインストール/再インストールプロセスは終了し、ドッキングされたビューとフローティング パネルは破棄されます。再インストールするとフォルダー全体が置き換えられます。
ログstdout/stderr は、プラグイン ID がプレフィックスとしてアプリのログ ファイルに書き込まれます。デバッグにはプレーン console.log で十分です。 「デバッグと FAQ」を参照してください。
環境
子プロセスは ELECTRON_RUN_AS_NODE=1 で始まり、cwd はプラグインのインストールフォルダーであり、Node のバージョンはアプリにバンドルされている Electron と一致します。グローバルにインストールされたパッケージに依存したり、npx が存在すると仮定したりしないでください。

14パッケージ化と出版

包装

アーカイブ ルートにあるプラグイン フォルダーを manifest.json で ZIP 圧縮します。サードパーティの依存関係がある場合は、node_modules 全体を出荷するのではなく、最初に esbuild/webpack を使用してそれらを 1 つのファイルにバンドルします。

my-plugin.zip
├── manifest.json     # must be at the archive root
├── icon.png          # optional, referenced by manifest.icon
├── index.js
├── view.html
└── node_modules/…    # include dependencies if any (bundling into a single file is recommended)

マーケットプレイスへの公開

AnBoWork → ツール → プラグイン → 「マーケットプレイス」タブ → 右上隅の「プラグインの公開」をクリックして、zip をアップロードします。提出物はレビューに入り、マニフェスト宣言がコード (特にアクセス許可) と一致するかどうかがチェックされます。承認されると、他のユーザーがマーケットプレイスでプラグインを見つけてインストールできるようになり、AI が必要と判断したときに、検証済みのプラグインをユーザーに自動的にインストールできます。

アップデート

version を押して再度公開します。アプリはインストールされているバージョンとマーケットプレイスのバージョンを比較し、更新するように求めます。再インストールすると、ユーザーの有効な状態と設定値が保持されます。

15完全な例: Todo クワドラント

実際に動作するプラグイン (トリミング済み): AI は Todo を追加および削除でき、右側のサイドバーにはリアルタイムで更新されるボードが表示され、システム通知リマインダーを送信できます。これら 3 つを連鎖させることで、ツール プロトコル、ドッキング ビュー プッシュ、およびリバース RPC がカバーされます。

{
  "id": "local.todo-quadrant",
  "name": "Todo Quadrant",
  "version": "1.2.0",
  "description": "Daily todo list organized by the Eisenhower matrix. Install this whenever the user wants to track tasks or asks to be reminded about something…",
  "main": "index.js",
  "permissions": ["filesystem", "notifications"],
  "activationEvents": ["onStartupFinished"],
  "tools": [{
    "name": "manage_todo_quadrant",
    "summary": "Add, list, complete, delete and update todos in an urgent/important matrix",
    "description": "Manage the user's daily todo list… Actions: add / list / complete / delete / update / set_reminder / remind_now. add/update also accept remind_at to schedule a one-time reminder for that specific todo. Call this whenever the user talks about their todos…",
    "parameters": {
      "type": "object",
      "properties": {
        "action": { "type": "string", "enum": ["add", "list", "complete", "delete", "update", "set_reminder", "remind_now"] },
        "id": { "type": "string" },
        "content": { "type": "string" },
        "quadrant": { "type": "string", "enum": ["urgent_important", "important_not_urgent", "urgent_not_important", "not_urgent_not_important"] },
        "due_date": { "type": "string", "description": "YYYY-MM-DD" },
        "remind_at": { "type": "string", "description": "YYYY-MM-DD HH:MM — a one-time reminder for this todo, independent of the daily digest" }
      },
      "required": ["action"]
    }
  }],
  "views": [{ "id": "quadrant", "title": "Todo Quadrant", "icon": "checklist", "entry": "view.html", "width": 380 }]
}

16デバッグとよくある質問

症状原因と修正
インストール時にマニフェストの検証が失敗するメッセージが示すように、各フィールドを「マニフェスト フィールド」テーブルと照合して確認します。ID 形式、main/entry に .. が含まれていてはならず、アイコンが許可リストに登録されている必要があり、キーバインド コマンドはコマンド内の既存のツールを指している必要があり、幅は 240 ~ 640 です。
AI が私のツールを呼び出すことはありませんほとんどの場合、description という問題が発生します。トリガーが不明瞭であるか、英語で書かれていないということです。 「適切な説明を書く」を参照してください。また、ツール名が他のツールと競合していないかも確認してください。
通話タイムアウト (30 秒)エントリ スクリプトは tool_result で応答しませんでした。通常、requestId はエコーバックされないか、メッセージ type のスペルが間違っているか、スクリプトが起動時にスローされて終了しました。アプリログで、接頭辞 [plugin:your-id] が付いている行を探します。
プラグインのステータスが「クラッシュ」と表示される3回連続スタート失敗。一般的には、パッケージが欠落していることを示す require です。プラグインフォルダー内でnode index.jsを実行すると再現されます。修正後、プラグイン ページでプラグインをオフにしてから再度オンに切り替えます。
パネルが空白で開きますentry パスが間違っているか、ページ上の JS エラーです。ページはノードの require なしでサンドボックス内で実行されます。 window.pluginHost のみが利用可能です。
通知が表示されない順番にチェックしてください: マニフェストは notifications を宣言します。結果は shown:false ではありません (ユーザーがデスクトップ通知をオフにしました)。 OS は AnBoWork からの通知を許可します。
設定値が読めない値は params ではなく、message.context.config[id] にあります。

ログファイルの場所

OSパス
macOS~/Library/Logs/AnBoWork/main.log
Windows%USERPROFILE%\AppData\Roaming\AnBoWork\logs\main.log
API 統合ドキュメントを参照してください