@gui-chat-plugin/template 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ja.md +258 -0
- package/README.md +248 -0
- package/README.npm.md +93 -0
- package/dist/core/definition.d.ts +6 -0
- package/dist/core/index.d.ts +10 -0
- package/dist/core/plugin.d.ts +10 -0
- package/dist/core/samples.d.ts +5 -0
- package/dist/core/types.d.ts +23 -0
- package/dist/core.cjs +1 -0
- package/dist/core.js +146 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +9 -0
- package/dist/react/Preview.d.ts +8 -0
- package/dist/react/View.d.ts +8 -0
- package/dist/react/index.d.ts +24 -0
- package/dist/react.cjs +8 -0
- package/dist/react.js +398 -0
- package/dist/style.css +1 -0
- package/dist/vue/Preview.vue.d.ts +7 -0
- package/dist/vue/View.vue.d.ts +12 -0
- package/dist/vue/index.d.ts +24 -0
- package/dist/vue.cjs +3 -0
- package/dist/vue.js +146 -0
- package/package.json +92 -0
package/README.ja.md
ADDED
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
# GUIChat プラグインテンプレート
|
|
2
|
+
|
|
3
|
+
**チャットデモ環境統合**を備えたGUIChat/MulmoChat用プラグインテンプレート。
|
|
4
|
+
|
|
5
|
+
このテンプレートは、ジュニアエンジニアがプラグインとLLMの連携を実際のチャットインターフェースで確認しながらプラグイン開発を学べるように設計されています。
|
|
6
|
+
|
|
7
|
+
> **Note**: このテンプレートには**Quizプラグインが動作サンプル**として含まれています。Quizプラグインは、ユーザー入力を受け付けるインタラクティブなプラグインの作成方法を示しています。自分のプラグイン実装に置き換えてください。
|
|
8
|
+
|
|
9
|
+
## 特徴
|
|
10
|
+
|
|
11
|
+
- **チャット統合デモ**: 実際のチャットインターフェースでプラグインをテスト
|
|
12
|
+
- **Mockモード**: APIキー不要で開発
|
|
13
|
+
- **Real APIモード**: 本番環境に近いOpenAI APIでテスト
|
|
14
|
+
- **フレームワーク非依存のCore**: プラグインロジックをUIフレームワークから分離
|
|
15
|
+
- **Vue + React対応**: 両フレームワークをすぐに使用可能
|
|
16
|
+
- **TypeScript**: 完全な型安全性
|
|
17
|
+
- **Tailwind CSS 4**: モダンなスタイリング
|
|
18
|
+
|
|
19
|
+
## クイックスタート
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# 依存関係をインストール
|
|
23
|
+
yarn install
|
|
24
|
+
|
|
25
|
+
# 開発サーバーを起動
|
|
26
|
+
yarn dev # Vueデモ
|
|
27
|
+
yarn dev:react # Reactデモ
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
http://localhost:5173 を開いてデモを確認。
|
|
31
|
+
|
|
32
|
+
### デモ機能
|
|
33
|
+
|
|
34
|
+
1. **チャットパネル**: メッセージを送信してLLMの応答を確認
|
|
35
|
+
2. **Mockモード**: APIキー不要でテスト(「quiz」「hello」キーワードを認識)
|
|
36
|
+
3. **Real APIモード**: OpenAI APIキーで実際のLLM連携
|
|
37
|
+
4. **Viewコンポーネント**: プラグインの結果表示を確認
|
|
38
|
+
5. **Previewコンポーネント**: サイドバーサムネイルを確認
|
|
39
|
+
6. **Quick Samples**: プラグインサンプルを直接実行
|
|
40
|
+
|
|
41
|
+
## 独自プラグインの作成
|
|
42
|
+
|
|
43
|
+
### ステップ1: テンプレートをコピー
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
cp -r GUIChatPluginTemplate GUIChatPluginMyPlugin
|
|
47
|
+
cd GUIChatPluginMyPlugin
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### ステップ2: package.jsonを更新
|
|
51
|
+
|
|
52
|
+
パッケージ名を変更:
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"name": "guichat-plugin-my-plugin",
|
|
56
|
+
"description": "プラグインの説明"
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### ステップ3: プラグインを実装
|
|
61
|
+
|
|
62
|
+
`src/core/`のファイルを編集(Vue/React共通):
|
|
63
|
+
|
|
64
|
+
1. **types.ts** - データ型を定義
|
|
65
|
+
2. **definition.ts** - ツール名とJSONスキーマを定義
|
|
66
|
+
3. **samples.ts** - テストデータを追加
|
|
67
|
+
4. **plugin.ts** - execute関数を実装
|
|
68
|
+
|
|
69
|
+
#### Vueの場合
|
|
70
|
+
|
|
71
|
+
`src/vue/`のファイルを編集:
|
|
72
|
+
|
|
73
|
+
1. **View.vue** - メインUIコンポーネント
|
|
74
|
+
2. **Preview.vue** - サイドバーサムネイル
|
|
75
|
+
|
|
76
|
+
開発サーバー起動: `yarn dev`
|
|
77
|
+
|
|
78
|
+
#### Reactの場合
|
|
79
|
+
|
|
80
|
+
`src/react/`のファイルを編集:
|
|
81
|
+
|
|
82
|
+
1. **View.tsx** - メインUIコンポーネント
|
|
83
|
+
2. **Preview.tsx** - サイドバーサムネイル
|
|
84
|
+
|
|
85
|
+
開発サーバー起動: `yarn dev:react`
|
|
86
|
+
|
|
87
|
+
### ステップ4: モックレスポンスを更新(オプション)
|
|
88
|
+
|
|
89
|
+
`demo/shared/chat-utils.ts`を編集してプラグイン用のモックレスポンスを追加:
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
export const DEFAULT_MOCK_RESPONSES: Record<string, MockResponse> = {
|
|
93
|
+
// プラグインのモックレスポンスを追加
|
|
94
|
+
myKeyword: {
|
|
95
|
+
toolCall: {
|
|
96
|
+
name: "myToolName",
|
|
97
|
+
args: { /* 引数 */ },
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
// ...
|
|
101
|
+
};
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## プラグイン構造
|
|
105
|
+
|
|
106
|
+
✏️ = 編集するファイル 🚫 = 編集しない(そのまま使う)
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
GUIChatPluginTemplate/
|
|
110
|
+
│
|
|
111
|
+
├── src/ # 📦 npmパッケージとして配布される部分
|
|
112
|
+
│ │ # MulmoChatなどのアプリから使用される
|
|
113
|
+
│ ├── index.ts # 🚫 デフォルトエクスポート(core)
|
|
114
|
+
│ ├── style.css # 🚫 Tailwind CSSエントリー
|
|
115
|
+
│ ├── core/ # フレームワーク非依存(Vue/React依存なし)
|
|
116
|
+
│ │ ├── index.ts # 🚫 Coreエクスポート
|
|
117
|
+
│ │ ├── types.ts # ✏️ プラグイン固有の型
|
|
118
|
+
│ │ ├── definition.ts # ✏️ ツール定義(LLM用スキーマ)
|
|
119
|
+
│ │ ├── samples.ts # ✏️ テスト用サンプルデータ
|
|
120
|
+
│ │ └── plugin.ts # ✏️ Execute関数
|
|
121
|
+
│ ├── vue/ # Vue固有の実装
|
|
122
|
+
│ │ ├── index.ts # 🚫 Vueプラグイン(core + コンポーネント)
|
|
123
|
+
│ │ ├── View.vue # ✏️ メインビューコンポーネント
|
|
124
|
+
│ │ └── Preview.vue # ✏️ サイドバープレビュー
|
|
125
|
+
│ └── react/ # React固有の実装
|
|
126
|
+
│ ├── index.ts # 🚫 Reactプラグイン(core + コンポーネント)
|
|
127
|
+
│ ├── View.tsx # ✏️ メインビューコンポーネント
|
|
128
|
+
│ └── Preview.tsx # ✏️ サイドバープレビュー
|
|
129
|
+
│
|
|
130
|
+
└── demo/ # 🔧 開発・テスト用(配布されない)
|
|
131
|
+
│ # プラグイン動作確認のためのチャットデモ
|
|
132
|
+
│ # 🚫 基本的に編集不要
|
|
133
|
+
├── vue/ # Vueデモ
|
|
134
|
+
├── react/ # Reactデモ
|
|
135
|
+
└── shared/
|
|
136
|
+
└── chat-utils.ts # ✏️ モックレスポンス追加時のみ編集
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
> **初心者向け解説**:
|
|
140
|
+
> - `src/` = あなたが作るプラグイン本体。npm公開後、他のアプリからインポートして使う
|
|
141
|
+
> - `demo/` = 開発中にプラグインをテストするための環境。npm公開時には含まれない
|
|
142
|
+
> - ✏️ のファイルだけ編集すればプラグインが作れる
|
|
143
|
+
|
|
144
|
+
## チャットフローの理解
|
|
145
|
+
|
|
146
|
+
通常はOpenAI APIを通じてLLMと通信します。Mockモードは**開発時のテスト用**で、APIキー不要でプラグインの動作確認ができます。
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
ユーザー入力
|
|
150
|
+
↓
|
|
151
|
+
useChat.sendMessage()
|
|
152
|
+
↓
|
|
153
|
+
┌─────────────────────────────────────┐
|
|
154
|
+
│ Mockモード?(テスト用) │
|
|
155
|
+
│ ├─ Yes → モックレスポンスを返す │
|
|
156
|
+
│ └─ No → OpenAI APIを呼び出す ←通常│
|
|
157
|
+
└─────────────────────────────────────┘
|
|
158
|
+
↓
|
|
159
|
+
LLMレスポンス(tool_callsを含む場合あり)
|
|
160
|
+
↓
|
|
161
|
+
┌─────────────────────────────────────┐
|
|
162
|
+
│ tool_callsあり? │
|
|
163
|
+
│ ├─ Yes → plugin.execute(args) │
|
|
164
|
+
│ │ → 結果を更新 │
|
|
165
|
+
│ │ → Viewコンポーネントに表示 │
|
|
166
|
+
│ │ → APIを再呼び出し │
|
|
167
|
+
│ │ → LLMの応答を取得 │
|
|
168
|
+
│ └─ No → テキストレスポンスを表示 │
|
|
169
|
+
└─────────────────────────────────────┘
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## 重要な概念
|
|
173
|
+
|
|
174
|
+
### ToolResult
|
|
175
|
+
|
|
176
|
+
execute関数は`ToolResult`を返します:
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
interface ToolResult<T, J> {
|
|
180
|
+
toolName: string; // TOOL_NAMEと一致必須(必須)
|
|
181
|
+
message: string; // LLM向けの簡潔なステータス
|
|
182
|
+
jsonData?: J; // LLMに見えるデータ
|
|
183
|
+
data?: T; // UI専用データ(LLMには送信されない)
|
|
184
|
+
title?: string; // 結果のタイトル
|
|
185
|
+
instructions?: string; // LLMへのフォローアップ指示
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Viewコンポーネントのprops
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
// View.vueが受け取るprops
|
|
193
|
+
{
|
|
194
|
+
selectedResult: ToolResult; // 表示する現在の結果
|
|
195
|
+
sendTextMessage: (text: string) => void; // チャットにメッセージを送信
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// 発行するイベント
|
|
199
|
+
@updateResult="(updated: ToolResult) => void"
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### 重要なパターン: ref + watch
|
|
203
|
+
|
|
204
|
+
View.vueでは、`computed`の代わりに`ref + watch`パターンを使用:
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
// ✅ 正しい
|
|
208
|
+
const data = ref<MyData | null>(null);
|
|
209
|
+
watch(
|
|
210
|
+
() => props.selectedResult,
|
|
211
|
+
(newResult) => {
|
|
212
|
+
if (newResult?.jsonData) {
|
|
213
|
+
data.value = newResult.jsonData;
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
{ immediate: true }
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
// ❌ 間違い - リアクティビティの問題が発生
|
|
220
|
+
const data = computed(() => props.selectedResult?.jsonData);
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## コマンド
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
yarn dev # Vueデモを起動
|
|
227
|
+
yarn dev:react # Reactデモを起動
|
|
228
|
+
yarn build # 本番用ビルド
|
|
229
|
+
yarn typecheck # 型チェック
|
|
230
|
+
yarn lint # コードのLint
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## MulmoChatとの統合
|
|
234
|
+
|
|
235
|
+
プラグイン開発後:
|
|
236
|
+
|
|
237
|
+
1. npmに公開またはローカルパスを使用
|
|
238
|
+
2. MulmoChatにインストール:
|
|
239
|
+
```bash
|
|
240
|
+
yarn add guichat-plugin-my-plugin
|
|
241
|
+
```
|
|
242
|
+
3. MulmoChatの`src/tools/index.ts`でインポート:
|
|
243
|
+
```typescript
|
|
244
|
+
import MyPlugin from "guichat-plugin-my-plugin/vue";
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## ドキュメント
|
|
248
|
+
|
|
249
|
+
詳細なドキュメントは[docs/](./docs/README.ja.md)を参照:
|
|
250
|
+
|
|
251
|
+
- [はじめに](./docs/getting-started.ja.md) - 初心者向けチュートリアル
|
|
252
|
+
- [プラグイン開発ガイド](./docs/plugin-development-guide.md) - 詳細リファレンス
|
|
253
|
+
- [AI開発ガイド](./docs/ai-development-guide.md) - AI向け最適化ガイド
|
|
254
|
+
- [npm公開ガイド](./docs/npm-publishing-guide.md) - 公開と統合
|
|
255
|
+
|
|
256
|
+
## ライセンス
|
|
257
|
+
|
|
258
|
+
MIT
|
package/README.md
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# GUIChat Plugin Template
|
|
2
|
+
|
|
3
|
+
A plugin template for GUIChat/MulmoChat with **integrated chat demo environment**.
|
|
4
|
+
|
|
5
|
+
This template is designed for junior engineers to learn plugin development with a working chat interface that demonstrates how plugins interact with LLMs.
|
|
6
|
+
|
|
7
|
+
> **Note**: This template includes a **Quiz plugin as a working sample**. The Quiz plugin demonstrates how to create interactive plugins with user input. Replace it with your own plugin implementation.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- **Chat-Integrated Demo**: Test your plugin with a real chat interface
|
|
12
|
+
- **Mock Mode**: Develop without needing an API key
|
|
13
|
+
- **Real API Mode**: Test with OpenAI API for production-like behavior
|
|
14
|
+
- **Framework-agnostic Core**: Plugin logic separated from UI framework
|
|
15
|
+
- **Vue + React Support**: Both frameworks supported out of the box
|
|
16
|
+
- **TypeScript**: Full type safety
|
|
17
|
+
- **Tailwind CSS 4**: Modern styling
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# Install dependencies
|
|
23
|
+
yarn install
|
|
24
|
+
|
|
25
|
+
# Start development server
|
|
26
|
+
yarn dev
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Open http://localhost:5173 to see the demo.
|
|
30
|
+
|
|
31
|
+
### Demo Features
|
|
32
|
+
|
|
33
|
+
1. **Chat Panel**: Send messages and see LLM responses
|
|
34
|
+
2. **Mock Mode**: Toggle to test without API key (recognizes "quiz" and "hello" keywords)
|
|
35
|
+
3. **Real API Mode**: Enter your OpenAI API key for actual LLM integration
|
|
36
|
+
4. **View Component**: See how your plugin renders results
|
|
37
|
+
5. **Preview Component**: See the sidebar thumbnail
|
|
38
|
+
6. **Quick Samples**: Execute plugin samples directly
|
|
39
|
+
|
|
40
|
+
## Creating Your Own Plugin
|
|
41
|
+
|
|
42
|
+
### Step 1: Copy this template
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
cp -r GUIChatPluginTemplate GUIChatPluginMyPlugin
|
|
46
|
+
cd GUIChatPluginMyPlugin
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Step 2: Update package.json
|
|
50
|
+
|
|
51
|
+
Change the package name:
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"name": "guichat-plugin-my-plugin",
|
|
55
|
+
"description": "Your plugin description"
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Step 3: Implement your plugin
|
|
60
|
+
|
|
61
|
+
Edit the files in `src/core/` (shared by Vue/React):
|
|
62
|
+
|
|
63
|
+
1. **types.ts** - Define your data types
|
|
64
|
+
2. **definition.ts** - Define tool name and JSON schema
|
|
65
|
+
3. **samples.ts** - Add test data
|
|
66
|
+
4. **plugin.ts** - Implement execute function
|
|
67
|
+
|
|
68
|
+
#### For Vue
|
|
69
|
+
|
|
70
|
+
Edit the files in `src/vue/`:
|
|
71
|
+
|
|
72
|
+
1. **View.vue** - Main UI component
|
|
73
|
+
2. **Preview.vue** - Sidebar thumbnail
|
|
74
|
+
|
|
75
|
+
Start dev server: `yarn dev`
|
|
76
|
+
|
|
77
|
+
#### For React
|
|
78
|
+
|
|
79
|
+
Edit the files in `src/react/`:
|
|
80
|
+
|
|
81
|
+
1. **View.tsx** - Main UI component
|
|
82
|
+
2. **Preview.tsx** - Sidebar thumbnail
|
|
83
|
+
|
|
84
|
+
Start dev server: `yarn dev:react`
|
|
85
|
+
|
|
86
|
+
### Step 4: Update mock responses (optional)
|
|
87
|
+
|
|
88
|
+
Edit `demo/shared/chat-utils.ts` to add mock responses for your plugin:
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
export const DEFAULT_MOCK_RESPONSES: Record<string, MockResponse> = {
|
|
92
|
+
// Add your plugin's mock response
|
|
93
|
+
myKeyword: {
|
|
94
|
+
toolCall: {
|
|
95
|
+
name: "myToolName",
|
|
96
|
+
args: { /* your args */ },
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
// ...
|
|
100
|
+
};
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Plugin Structure
|
|
104
|
+
|
|
105
|
+
✏️ = Edit this file 🚫 = Don't edit (use as-is)
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
GUIChatPluginTemplate/
|
|
109
|
+
│
|
|
110
|
+
├── src/ # 📦 Distributed as npm package
|
|
111
|
+
│ │ # Used by apps like MulmoChat
|
|
112
|
+
│ ├── index.ts # 🚫 Default export (core)
|
|
113
|
+
│ ├── style.css # 🚫 Tailwind CSS entry
|
|
114
|
+
│ ├── core/ # Framework-agnostic (no Vue/React dependencies)
|
|
115
|
+
│ │ ├── index.ts # 🚫 Core exports
|
|
116
|
+
│ │ ├── types.ts # ✏️ Plugin-specific types
|
|
117
|
+
│ │ ├── definition.ts # ✏️ Tool definition (schema for LLM)
|
|
118
|
+
│ │ ├── samples.ts # ✏️ Sample data for testing
|
|
119
|
+
│ │ └── plugin.ts # ✏️ Execute function
|
|
120
|
+
│ ├── vue/ # Vue-specific implementation
|
|
121
|
+
│ │ ├── index.ts # 🚫 Vue plugin (combines core + components)
|
|
122
|
+
│ │ ├── View.vue # ✏️ Main view component
|
|
123
|
+
│ │ └── Preview.vue # ✏️ Sidebar preview component
|
|
124
|
+
│ └── react/ # React-specific implementation
|
|
125
|
+
│ ├── index.ts # 🚫 React plugin (combines core + components)
|
|
126
|
+
│ ├── View.tsx # ✏️ Main view component
|
|
127
|
+
│ └── Preview.tsx # ✏️ Sidebar preview component
|
|
128
|
+
│
|
|
129
|
+
└── demo/ # 🔧 For development/testing only (NOT distributed)
|
|
130
|
+
│ # Chat demo to test your plugin
|
|
131
|
+
│ # 🚫 Generally no edits needed
|
|
132
|
+
├── vue/ # Vue demo
|
|
133
|
+
├── react/ # React demo
|
|
134
|
+
└── shared/
|
|
135
|
+
└── chat-utils.ts # ✏️ Edit only to add mock responses
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
> **For Beginners**:
|
|
139
|
+
> - `src/` = Your plugin code. After npm publish, other apps import and use this
|
|
140
|
+
> - `demo/` = Development environment to test your plugin. Not included in npm package
|
|
141
|
+
> - Just edit the ✏️ files to create your plugin
|
|
142
|
+
|
|
143
|
+
## Understanding the Chat Flow
|
|
144
|
+
|
|
145
|
+
Normally, the chat communicates with the LLM via OpenAI API. Mock Mode is **for development testing only**, allowing you to test plugin behavior without an API key.
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
User Input
|
|
149
|
+
↓
|
|
150
|
+
useChat.sendMessage()
|
|
151
|
+
↓
|
|
152
|
+
┌─────────────────────────────────────┐
|
|
153
|
+
│ Mock Mode? (for testing) │
|
|
154
|
+
│ ├─ Yes → Return mock response │
|
|
155
|
+
│ └─ No → Call OpenAI API ← normal │
|
|
156
|
+
└─────────────────────────────────────┘
|
|
157
|
+
↓
|
|
158
|
+
LLM Response (may include tool_calls)
|
|
159
|
+
↓
|
|
160
|
+
┌─────────────────────────────────────┐
|
|
161
|
+
│ Has tool_calls? │
|
|
162
|
+
│ ├─ Yes → plugin.execute(args) │
|
|
163
|
+
│ │ → Update result │
|
|
164
|
+
│ │ → Show in View component │
|
|
165
|
+
│ │ → Call API again │
|
|
166
|
+
│ │ → Get LLM response │
|
|
167
|
+
│ └─ No → Show text response │
|
|
168
|
+
└─────────────────────────────────────┘
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Key Concepts
|
|
172
|
+
|
|
173
|
+
### ToolResult
|
|
174
|
+
|
|
175
|
+
The execute function returns a `ToolResult`:
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
interface ToolResult<T, J> {
|
|
179
|
+
toolName: string; // Must match TOOL_NAME (required)
|
|
180
|
+
message: string; // Brief status for LLM
|
|
181
|
+
jsonData?: J; // Data visible to LLM
|
|
182
|
+
data?: T; // Data for UI only (not sent to LLM)
|
|
183
|
+
title?: string; // Result title
|
|
184
|
+
instructions?: string; // Follow-up instructions for LLM
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### View Component Props
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
// Props received by View.vue
|
|
192
|
+
{
|
|
193
|
+
selectedResult: ToolResult; // Current result to display
|
|
194
|
+
sendTextMessage: (text: string) => void; // Send message back to chat
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Event emitted
|
|
198
|
+
@updateResult="(updated: ToolResult) => void"
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Important Pattern: ref + watch
|
|
202
|
+
|
|
203
|
+
In View.vue, always use `ref + watch` pattern instead of `computed`:
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
// ✅ Correct
|
|
207
|
+
const data = ref<MyData | null>(null);
|
|
208
|
+
watch(
|
|
209
|
+
() => props.selectedResult,
|
|
210
|
+
(newResult) => {
|
|
211
|
+
if (newResult?.jsonData) {
|
|
212
|
+
data.value = newResult.jsonData;
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
{ immediate: true }
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
// ❌ Wrong - causes reactivity issues
|
|
219
|
+
const data = computed(() => props.selectedResult?.jsonData);
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Commands
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
yarn dev # Start Vue demo
|
|
226
|
+
yarn dev:react # Start React demo
|
|
227
|
+
yarn build # Build for production
|
|
228
|
+
yarn typecheck # Type check
|
|
229
|
+
yarn lint # Lint code
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Integration with MulmoChat
|
|
233
|
+
|
|
234
|
+
After developing your plugin:
|
|
235
|
+
|
|
236
|
+
1. Publish to npm or use local path
|
|
237
|
+
2. Install in MulmoChat:
|
|
238
|
+
```bash
|
|
239
|
+
yarn add guichat-plugin-my-plugin
|
|
240
|
+
```
|
|
241
|
+
3. Import in MulmoChat's `src/tools/index.ts`:
|
|
242
|
+
```typescript
|
|
243
|
+
import MyPlugin from "guichat-plugin-my-plugin/vue";
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## License
|
|
247
|
+
|
|
248
|
+
MIT
|
package/README.npm.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# guichat-plugin-{plugin-name}
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/guichat-plugin-{plugin-name})
|
|
4
|
+
|
|
5
|
+
A plugin for [MulmoChat](https://github.com/receptron/MulmoChat) - a multi-modal voice chat application with OpenAI's GPT-4 Realtime API.
|
|
6
|
+
|
|
7
|
+
## What this plugin does
|
|
8
|
+
|
|
9
|
+
{plugin-description}
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
yarn add guichat-plugin-{plugin-name}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
### Vue Implementation (for MulmoChat)
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
// In src/tools/index.ts
|
|
23
|
+
import Plugin from "guichat-plugin-{plugin-name}/vue";
|
|
24
|
+
|
|
25
|
+
const pluginList = [
|
|
26
|
+
// ... other plugins
|
|
27
|
+
Plugin,
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
// In src/main.ts
|
|
31
|
+
import "guichat-plugin-{plugin-name}/style.css";
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### React Implementation
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import Plugin from "guichat-plugin-{plugin-name}/react";
|
|
38
|
+
import "guichat-plugin-{plugin-name}/style.css";
|
|
39
|
+
|
|
40
|
+
// Named exports
|
|
41
|
+
import { plugin, View, Preview } from "guichat-plugin-{plugin-name}/react";
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Core Only (Framework-agnostic)
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
import { pluginCore, TOOL_NAME } from "guichat-plugin-{plugin-name}";
|
|
48
|
+
// or
|
|
49
|
+
import pluginCore from "guichat-plugin-{plugin-name}";
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Package Exports
|
|
53
|
+
|
|
54
|
+
| Export | Description |
|
|
55
|
+
|--------|-------------|
|
|
56
|
+
| `guichat-plugin-{plugin-name}` | Core (framework-agnostic) |
|
|
57
|
+
| `guichat-plugin-{plugin-name}/vue` | Vue implementation with UI components |
|
|
58
|
+
| `guichat-plugin-{plugin-name}/react` | React implementation with UI components |
|
|
59
|
+
| `guichat-plugin-{plugin-name}/style.css` | Tailwind CSS styles |
|
|
60
|
+
|
|
61
|
+
## Development
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Install dependencies
|
|
65
|
+
yarn install
|
|
66
|
+
|
|
67
|
+
# Start dev server - Vue (http://localhost:5173/)
|
|
68
|
+
yarn dev
|
|
69
|
+
|
|
70
|
+
# Start dev server - React (http://localhost:5173/)
|
|
71
|
+
yarn dev:react
|
|
72
|
+
|
|
73
|
+
# Build
|
|
74
|
+
yarn build
|
|
75
|
+
|
|
76
|
+
# Type check
|
|
77
|
+
yarn typecheck
|
|
78
|
+
|
|
79
|
+
# Lint
|
|
80
|
+
yarn lint
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Test Prompts
|
|
84
|
+
|
|
85
|
+
Try these prompts to test the plugin:
|
|
86
|
+
|
|
87
|
+
1. "{test-prompt-1}"
|
|
88
|
+
2. "{test-prompt-2}"
|
|
89
|
+
3. "{test-prompt-3}"
|
|
90
|
+
|
|
91
|
+
## License
|
|
92
|
+
|
|
93
|
+
MIT
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MulmoChat Plugin Core Exports
|
|
3
|
+
*
|
|
4
|
+
* Framework-agnostic types and plugin logic.
|
|
5
|
+
* Import from "@mulmochat-plugin/quiz/core"
|
|
6
|
+
*/
|
|
7
|
+
export type { QuizQuestion, QuizData, QuizArgs } from "./types";
|
|
8
|
+
export { pluginCore, executeQuiz } from "./plugin";
|
|
9
|
+
export { TOOL_NAME, TOOL_DEFINITION } from "./definition";
|
|
10
|
+
export { SAMPLES } from "./samples";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MulmoChat Quiz Plugin Core (Framework-agnostic)
|
|
3
|
+
*
|
|
4
|
+
* Contains the plugin logic without UI components.
|
|
5
|
+
* Can be used by any framework (Vue, React, etc.)
|
|
6
|
+
*/
|
|
7
|
+
import type { ToolPluginCore, ToolContext, ToolResult } from "gui-chat-protocol";
|
|
8
|
+
import type { QuizData, QuizArgs } from "./types";
|
|
9
|
+
export declare const executeQuiz: (_context: ToolContext, args: QuizArgs) => Promise<ToolResult<never, QuizData>>;
|
|
10
|
+
export declare const pluginCore: ToolPluginCore<never, QuizData, QuizArgs>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quiz Plugin Types
|
|
3
|
+
*
|
|
4
|
+
* Quiz-specific type definitions only.
|
|
5
|
+
* Common types should be imported directly from gui-chat-protocol.
|
|
6
|
+
*/
|
|
7
|
+
/** Single quiz question */
|
|
8
|
+
export interface QuizQuestion {
|
|
9
|
+
question: string;
|
|
10
|
+
choices: string[];
|
|
11
|
+
correctAnswer?: number;
|
|
12
|
+
}
|
|
13
|
+
/** Quiz data stored in result.jsonData */
|
|
14
|
+
export interface QuizData {
|
|
15
|
+
title?: string;
|
|
16
|
+
questions: QuizQuestion[];
|
|
17
|
+
userAnswers?: number[];
|
|
18
|
+
}
|
|
19
|
+
/** Arguments passed to the quiz tool */
|
|
20
|
+
export interface QuizArgs {
|
|
21
|
+
title?: string;
|
|
22
|
+
questions: QuizQuestion[];
|
|
23
|
+
}
|
package/dist/core.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i="putQuestions",o={type:"function",name:i,description:"Present a set of multiple choice questions to test the user's knowledge or abilities. Each question should have 2-6 answer choices.",parameters:{type:"object",properties:{title:{type:"string",description:"Optional title for the quiz (e.g., 'JavaScript Basics Quiz')"},questions:{type:"array",description:"Array of multiple choice questions",items:{type:"object",properties:{question:{type:"string",description:"The question text"},choices:{type:"array",description:"Array of answer choices (2-6 choices)",items:{type:"string"},minItems:2,maxItems:6},correctAnswer:{type:"number",description:"Optional: The index of the correct answer (0-based). Include this if you want to track correct answers."}},required:["question","choices"]},minItems:1}},required:["questions"]}},n=[{name:"JavaScript Quiz",args:{title:"JavaScript Basics",questions:[{question:"What does 'const' do in JavaScript?",choices:["Declares a constant variable","Declares a mutable variable","Creates a function","Imports a module"],correctAnswer:0},{question:"Which method adds an element to the end of an array?",choices:["pop()","shift()","push()","unshift()"],correctAnswer:2},{question:"What is the output of: typeof null?",choices:['"null"','"undefined"','"object"','"boolean"'],correctAnswer:2}]}},{name:"World Capitals",args:{title:"World Capitals Quiz",questions:[{question:"What is the capital of Japan?",choices:["Osaka","Kyoto","Tokyo","Hiroshima"],correctAnswer:2},{question:"What is the capital of Australia?",choices:["Sydney","Melbourne","Canberra","Brisbane"],correctAnswer:2}]}},{name:"Simple Yes/No",args:{questions:[{question:"Is the Earth round?",choices:["Yes","No"],correctAnswer:0}]}}],a=async(l,c)=>{try{const{title:s,questions:e}=c;if(!e||!Array.isArray(e)||e.length===0)throw new Error("At least one question is required");for(let t=0;t<e.length;t++){const r=e[t];if(!r.question||typeof r.question!="string")throw new Error(`Question ${t+1} must have a question text`);if(!Array.isArray(r.choices)||r.choices.length<2)throw new Error(`Question ${t+1} must have at least 2 choices`);if(r.choices.length>6)throw new Error(`Question ${t+1} cannot have more than 6 choices`)}const u={title:s,questions:e};return{toolName:o.name,message:`Quiz presented with ${e.length} question${e.length>1?"s":""}`,jsonData:u,instructions:"The quiz has been presented to the user. Wait for the user to submit their answers. They will tell you their answers in text format."}}catch(s){return console.error("Quiz creation error",s),{toolName:o.name,message:`Quiz error: ${s instanceof Error?s.message:"Unknown error"}`,instructions:"Acknowledge that there was an error creating the quiz and suggest trying again."}}},h={toolDefinition:o,execute:a,generatingMessage:"Preparing quiz...",isEnabled:()=>!0,samples:n};exports.SAMPLES=n;exports.TOOL_DEFINITION=o;exports.TOOL_NAME=i;exports.executeQuiz=a;exports.pluginCore=h;
|