From 9ce9db52c6bdfdd362b525d961a8f6ec66453acb Mon Sep 17 00:00:00 2001 From: snakajima Date: Mon, 28 Sep 2026 18:53:32 +0900 Subject: [PATCH] docs: ToolContext.userSpokeAt, conversationId and ToolResult.sequence Phase 5 of MulmoChat's plans/plugins-repo-and-sequence-protocol.md: the plugin guides describe what gui-chat-protocol 2.1 and 2.2 added for plugins (userSpokeAt, conversationId, sequence, and the generateImage / editImages conventions of context.app), with @gui-chat-plugin/sequence as the example. Co-Authored-By: Claude Opus 5.5 (1M context) --- README.md | 17 +++++++++++++++ TEMPLATE.md | 17 +++++++++++++++ docs/getting-started.ja.md | 2 +- docs/getting-started.md | 2 +- docs/plugin-development-guide.md | 36 ++++++++++++++++++++++++++++++++ 5 files changed, 72 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d43ce33..749095e 100644 --- a/README.md +++ b/README.md @@ -192,6 +192,23 @@ interface ToolResult { } ``` +### ToolContext + +The execute function receives a `ToolContext`: + +```typescript +interface ToolContext { + currentResult?: ToolResult | null; // Currently selected result + app?: ToolContextApp; // Host app features + userSpokeAt?: number; // 2.1: when the user last spoke (Date.now() ms) + conversationId?: string; // 2.2: which conversation the call belongs to +} +``` + +`app` holds the host's functions (check one exists before calling it; `generateImage` and +`editImages` are shared conventions). A tool that shows steps one at a time returns `sequence` on +its results. See the [API reference](https://github.com/receptron/gui-chat-protocol/blob/main/spec/API_REFERENCE.md). + ### View Component Props ```typescript diff --git a/TEMPLATE.md b/TEMPLATE.md index 1783301..a93aaa0 100644 --- a/TEMPLATE.md +++ b/TEMPLATE.md @@ -426,6 +426,15 @@ rollupOptions: { } ``` +### ⚠️ Reach the Host Only Through `context` + +`execute()` may run in the browser or on the host's server, so it doesn't `fetch` host routes or +touch `window`. Use what `ToolContext` carries: `currentResult`, `app` (check a function exists +before calling it; `generateImage(prompt)` and `editImages(prompt, imagePaths)` are shared +conventions), `userSpokeAt` (gui-chat-protocol 2.1) and `conversationId` (2.2: keep in-memory state +per conversation). A tool that shows steps one at a time returns `sequence` on its results (2.1). +See the [API reference](https://github.com/receptron/gui-chat-protocol/blob/main/spec/API_REFERENCE.md), and [`@gui-chat-plugin/sequence`](https://github.com/receptron/gui-chat-plugins/tree/main/packages/sequence) for an example. + ### ⚠️ File Structure Verification Required for `yarn dev` to work: @@ -686,6 +695,14 @@ rollupOptions: { } ``` +### ⚠️ ホストには `context` 経由でのみアクセス + +`execute()` はブラウザでもホストのサーバーでも動くことがあるので、ホストのルートを `fetch` したり +`window` に触れたりしないでください。`ToolContext` にあるものを使います:`currentResult`、`app`(呼ぶ前に関数があるか確かめる。 +`generateImage(prompt)` と `editImages(prompt, imagePaths)` は共通の決まりごと)、`userSpokeAt`(gui-chat-protocol 2.1)、 +`conversationId`(2.2:メモリに持つ状態は会話ごとに持つ)。1 ステップずつ見せるツールは結果に `sequence` を返します(2.1)。 +[API リファレンス](https://github.com/receptron/gui-chat-protocol/blob/main/spec/API_REFERENCE.md)と、例として [`@gui-chat-plugin/sequence`](https://github.com/receptron/gui-chat-plugins/tree/main/packages/sequence) を参照してください。 + --- ## チェックリスト diff --git a/docs/getting-started.ja.md b/docs/getting-started.ja.md index 5b0f537..be1720f 100644 --- a/docs/getting-started.ja.md +++ b/docs/getting-started.ja.md @@ -531,7 +531,7 @@ execute(context: ToolContext, args: GreetingArgs): Promise | 引数 | 説明 | |------|------| -| `context` | 実行コンテキスト。`currentResult`(前回の結果)などを含む | +| `context` | 実行コンテキスト。`currentResult`(前回の結果)、`app`(`generateImage` などホストの機能)、`userSpokeAt`、`conversationId`。詳しくは[プラグイン開発ガイド](./plugin-development-guide.md#toolcontext) | | `args` | LLMが渡した引数。definition.tsで定義したパラメータに基づく | ### ToolResultの構造(戻り値) diff --git a/docs/getting-started.md b/docs/getting-started.md index bbd453a..e640c1d 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -533,7 +533,7 @@ execute(context: ToolContext, args: GreetingArgs): Promise | Argument | Description | |----------|-------------| -| `context` | Execution context. Contains `currentResult` (previous result), etc. | +| `context` | Execution context: `currentResult` (previous result), `app` (host features such as `generateImage`), `userSpokeAt` and `conversationId`. See the [plugin development guide](./plugin-development-guide.md#toolcontext) | | `args` | Arguments from LLM. Based on parameters defined in definition.ts | ### ToolResult Structure (Return Value) diff --git a/docs/plugin-development-guide.md b/docs/plugin-development-guide.md index 9a53ca4..28d535d 100644 --- a/docs/plugin-development-guide.md +++ b/docs/plugin-development-guide.md @@ -142,6 +142,7 @@ interface ToolResult { instructionsRequired?: boolean; // Always send instructions updating?: boolean; // Update existing result viewState?: Record; // Persistent UI state + sequence?: SequenceStep | null; // 2.1: this result is a step of a sequence (see below) } ``` @@ -151,9 +152,44 @@ interface ToolResult { interface ToolContext { currentResult?: ToolResult | null; // Currently selected result app?: ToolContextApp; // Host app features + userSpokeAt?: number; // 2.1: when the user last spoke (Date.now() ms) + conversationId?: string; // 2.2: which conversation the call belongs to } ``` +- **`app`** is an open record: a host adds the functions it has, and a plugin checks for one before + calling it. Two are shared conventions with fixed shapes (MulmoChat, MulmoGlass): + `generateImage(prompt)` and `editImages(prompt, imagePaths)` (a new picture from 1 to 8 saved + ones under `artifacts/images/`). Both return a `ToolResult` whose `data.imageData` is the + picture and `data.imagePath` where it was saved. +- **`userSpokeAt`** is absent when the host doesn't know; a plugin then doesn't wait for the user. +- **`conversationId`**: a plugin that keeps state in memory between calls keeps it per + `conversationId`, so conversations sharing one host (browser tabs on one server) don't mix. + Compare it, don't parse it. Absent means one conversation. + +### Sequences (steps shown one at a time) + +A tool that shows a sequence one step per call, such as slides or a story's panels, returns +`sequence` on each result: where the sequence is and the call for the next step. A host that +supports sequences asks the model once to go on when it ends a reply mid-sequence, which models +do. Set `sequence: null` for a step that wasn't shown, and leave it out on results that aren't +steps. A step that waits for the user sets `waitsForUser`, and the plugin holds a later step until +`context.userSpokeAt` is after the waiting step appeared. + +```typescript +return { + toolName: TOOL_NAME, data, message, instructions, + sequence: { + step: 2, total: 5, kind: "slideshow", label: "Slide 2 of 5", + onShown: "explain it", nextCall: "call presentSlide for slide 3 of 5", + }, +}; +``` + +The full shapes, and the host side (`createSequenceKeeper`), are in the +[API reference](https://github.com/receptron/gui-chat-protocol/blob/main/spec/API_REFERENCE.md). [`@gui-chat-plugin/sequence`](https://github.com/receptron/gui-chat-plugins/tree/main/packages/sequence) (presentSlide, defineStoryboard, +presentPanel) is a working example. + --- ## Directory Structure