@gui-chat-plugin/tictactoe 0.1.0
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.md +100 -0
- package/dist/core/definition.d.ts +7 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/logic.d.ts +5 -0
- package/dist/core/plugin.d.ts +9 -0
- package/dist/core/samples.d.ts +5 -0
- package/dist/core/types.d.ts +77 -0
- package/dist/core.cjs +9 -0
- package/dist/core.js +281 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +10 -0
- package/dist/style.css +1 -0
- package/dist/vue/Preview.vue.d.ts +8 -0
- package/dist/vue/View.vue.d.ts +9 -0
- package/dist/vue/index.d.ts +17 -0
- package/dist/vue.cjs +1 -0
- package/dist/vue.js +278 -0
- package/package.json +63 -0
package/README.md
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# GUIChatPluginTicTacToe
|
|
2
|
+
|
|
3
|
+
Tic-Tac-Toe game plugin for GUI Chat.
|
|
4
|
+
|
|
5
|
+
## Development
|
|
6
|
+
|
|
7
|
+
### 1. Plugin単体でデバッグ
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
yarn install
|
|
11
|
+
yarn run dev
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
ブラウザで http://localhost:5173/ を開く
|
|
15
|
+
|
|
16
|
+
### 2. MulmoChatでデバッグ
|
|
17
|
+
|
|
18
|
+
**初回セットアップ(MulmoChat側):**
|
|
19
|
+
|
|
20
|
+
1. `MulmoChat/package.json` に依存関係を追加:
|
|
21
|
+
```json
|
|
22
|
+
"@gui-chat-plugin/tictactoe": "file:../GUIChatPluginTicTacToe",
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
2. `MulmoChat/src/main.ts` にCSS importを追加:
|
|
26
|
+
```typescript
|
|
27
|
+
import "@gui-chat-plugin/tictactoe/style.css";
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
3. `MulmoChat/src/tools/index.ts` にプラグインを登録:
|
|
31
|
+
```typescript
|
|
32
|
+
import TicTacToePlugin from "@gui-chat-plugin/tictactoe/vue";
|
|
33
|
+
// pluginList に TicTacToePlugin を追加
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**デバッグ実行:**
|
|
37
|
+
```bash
|
|
38
|
+
# プラグインをビルドしてMulmoChatに反映
|
|
39
|
+
./refresh-in-mulmochat.sh
|
|
40
|
+
|
|
41
|
+
# MulmoChatを起動
|
|
42
|
+
cd ../MulmoChat
|
|
43
|
+
yarn run dev
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 3. チェックスクリプト
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# プラグインファイル構成チェック
|
|
50
|
+
./check-plugin-structure.sh
|
|
51
|
+
|
|
52
|
+
# MulmoChat統合チェック(CSS, 依存関係, 登録)
|
|
53
|
+
./check-mulmochat-integration.sh
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Required Files (24 files)
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
【ルート設定ファイル (7)】
|
|
60
|
+
.gitignore
|
|
61
|
+
package.json
|
|
62
|
+
tsconfig.json
|
|
63
|
+
tsconfig.build.json
|
|
64
|
+
vite.config.ts
|
|
65
|
+
eslint.config.js
|
|
66
|
+
index.html
|
|
67
|
+
|
|
68
|
+
【ソースエントリ (2)】
|
|
69
|
+
src/index.ts
|
|
70
|
+
src/style.css
|
|
71
|
+
|
|
72
|
+
【Coreモジュール (6)】
|
|
73
|
+
src/core/index.ts
|
|
74
|
+
src/core/types.ts
|
|
75
|
+
src/core/definition.ts
|
|
76
|
+
src/core/logic.ts
|
|
77
|
+
src/core/plugin.ts
|
|
78
|
+
src/core/samples.ts
|
|
79
|
+
|
|
80
|
+
【Vueモジュール (3)】
|
|
81
|
+
src/vue/index.ts
|
|
82
|
+
src/vue/View.vue
|
|
83
|
+
src/vue/Preview.vue
|
|
84
|
+
|
|
85
|
+
【デモファイル (2)】
|
|
86
|
+
demo/main.ts
|
|
87
|
+
demo/App.vue
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Scripts
|
|
91
|
+
|
|
92
|
+
| Command | Description |
|
|
93
|
+
|---------|-------------|
|
|
94
|
+
| `yarn dev` | 開発サーバー起動 |
|
|
95
|
+
| `yarn build` | プロダクションビルド |
|
|
96
|
+
| `yarn typecheck` | TypeScriptチェック |
|
|
97
|
+
| `yarn lint` | ESLintチェック |
|
|
98
|
+
| `./check-plugin-structure.sh` | ファイル構成チェック |
|
|
99
|
+
| `./check-mulmochat-integration.sh` | MulmoChat統合チェック |
|
|
100
|
+
| `./refresh-in-mulmochat.sh` | MulmoChatに反映 |
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TicTacToe Plugin - Tool Definition
|
|
3
|
+
*/
|
|
4
|
+
import type { ToolDefinition } from "gui-chat-protocol";
|
|
5
|
+
export declare const TOOL_NAME = "playTicTacToe";
|
|
6
|
+
export declare const TOOL_DEFINITION: ToolDefinition;
|
|
7
|
+
export declare const SYSTEM_PROMPT = "You can play Tic-Tac-Toe with users using the playTicTacToe tool.\n\nIMPORTANT: When the user specifies a move (e.g., \"I want to play at top-left, which is row=0, col=0\"), you MUST call the playTicTacToe tool with action=\"move\", NOT respond with text.\n\nGame rules:\n1. Start a new game with action=\"new_game\"\n2. For moves, use action=\"move\" with row (0-2) and col (0-2), plus the current board state\n3. X always goes first. Win by getting 3 in a row (horizontal, vertical, or diagonal)\n4. Positions: row=0 is top, row=2 is bottom; col=0 is left, col=2 is right";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TicTacToe Plugin - Core (Framework-agnostic)
|
|
3
|
+
*/
|
|
4
|
+
export type { Cell, Side, TicTacToeBoard, PlayerType, TicTacToeArgs, NewGameCommand, MoveCommand, Command, TicTacToeState, TicTacToeClickData, } from "./types";
|
|
5
|
+
export { TOOL_NAME, TOOL_DEFINITION, SYSTEM_PROMPT, playTicTacToe, executeTicTacToe, pluginCore, } from "./plugin";
|
|
6
|
+
export { samples } from "./samples";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TicTacToe Plugin Core
|
|
3
|
+
*/
|
|
4
|
+
import type { ToolPluginCore, ToolContext, ToolResult } from "gui-chat-protocol";
|
|
5
|
+
import type { TicTacToeArgs, TicTacToeState } from "./types";
|
|
6
|
+
export { TOOL_NAME, TOOL_DEFINITION, SYSTEM_PROMPT } from "./definition";
|
|
7
|
+
export { playTicTacToe } from "./logic";
|
|
8
|
+
export declare const executeTicTacToe: (_context: ToolContext, args: TicTacToeArgs) => Promise<ToolResult<never, TicTacToeState>>;
|
|
9
|
+
export declare const pluginCore: ToolPluginCore<never, TicTacToeState, TicTacToeArgs>;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TicTacToe Plugin - Type Definitions
|
|
3
|
+
*/
|
|
4
|
+
export type Cell = "." | "X" | "O";
|
|
5
|
+
export type Side = "X" | "O";
|
|
6
|
+
export type TicTacToeBoard = Cell[][];
|
|
7
|
+
export type PlayerType = "user" | "computer";
|
|
8
|
+
export interface TicTacToeArgs {
|
|
9
|
+
action: "new_game" | "move";
|
|
10
|
+
col?: number;
|
|
11
|
+
row?: number;
|
|
12
|
+
board?: Cell[][];
|
|
13
|
+
currentSide?: Side;
|
|
14
|
+
playerNames?: {
|
|
15
|
+
X: PlayerType;
|
|
16
|
+
O: PlayerType;
|
|
17
|
+
};
|
|
18
|
+
firstPlayer?: PlayerType;
|
|
19
|
+
}
|
|
20
|
+
export type NewGameCommand = {
|
|
21
|
+
action: "new_game";
|
|
22
|
+
playerNames: {
|
|
23
|
+
X: string;
|
|
24
|
+
O: string;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
export type MoveCommand = {
|
|
28
|
+
action: "move";
|
|
29
|
+
row: number;
|
|
30
|
+
col: number;
|
|
31
|
+
board: TicTacToeBoard;
|
|
32
|
+
currentSide: Side;
|
|
33
|
+
playerNames: {
|
|
34
|
+
X: string;
|
|
35
|
+
O: string;
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
export type Command = NewGameCommand | MoveCommand;
|
|
39
|
+
export interface TicTacToeState {
|
|
40
|
+
board: TicTacToeBoard;
|
|
41
|
+
currentSide: Side;
|
|
42
|
+
playerNames: {
|
|
43
|
+
X: string;
|
|
44
|
+
O: string;
|
|
45
|
+
};
|
|
46
|
+
legalMoves: {
|
|
47
|
+
row: number;
|
|
48
|
+
col: number;
|
|
49
|
+
}[];
|
|
50
|
+
counts: {
|
|
51
|
+
X: number;
|
|
52
|
+
O: number;
|
|
53
|
+
empty: number;
|
|
54
|
+
};
|
|
55
|
+
isTerminal: boolean;
|
|
56
|
+
winner: Side | "draw" | null;
|
|
57
|
+
winningLine: {
|
|
58
|
+
row: number;
|
|
59
|
+
col: number;
|
|
60
|
+
}[] | null;
|
|
61
|
+
lastAction: {
|
|
62
|
+
type: "new_game";
|
|
63
|
+
} | {
|
|
64
|
+
type: "move";
|
|
65
|
+
row: number;
|
|
66
|
+
col: number;
|
|
67
|
+
};
|
|
68
|
+
error?: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Data passed from handleCellClick for demo testing
|
|
72
|
+
*/
|
|
73
|
+
export interface TicTacToeClickData {
|
|
74
|
+
row: number;
|
|
75
|
+
col: number;
|
|
76
|
+
currentState: TicTacToeState;
|
|
77
|
+
}
|
package/dist/core.cjs
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y="playTicTacToe",T={type:"function",name:y,description:"Play Tic-Tac-Toe (Noughts and Crosses) game with the user. You can start a new game or make moves on the 3x3 board.",parameters:{type:"object",properties:{action:{type:"string",enum:["new_game","move"],description:"The action to perform: start a new game or make a move"},col:{type:"number",description:"Column position for the move (0-2, required for 'move' action). Left=0, Center=1, Right=2",minimum:0,maximum:2},row:{type:"number",description:"Row position for the move (0-2, required for 'move' action). Top=0, Middle=1, Bottom=2",minimum:0,maximum:2},board:{type:"array",description:"Current 3x3 board state BEFORE the move (required for 'move' action). Pass the current board state as-is.",items:{type:"array",items:{type:"string",enum:[".","X","O"]}}},currentSide:{type:"string",enum:["X","O"],description:"Current player's side (required for 'move' action). X always goes first."},playerNames:{type:"object",description:"Player assignments (required for 'move' action)",properties:{X:{type:"string",enum:["user","computer"]},O:{type:"string",enum:["user","computer"]}},required:["X","O"]},firstPlayer:{type:"string",enum:["user","computer"],description:"Optional: Which player should play as X (goes first) for 'new_game' action. If not specified, will be chosen randomly."}},required:["action"],additionalProperties:!1}},f=`You can play Tic-Tac-Toe with users using the playTicTacToe tool.
|
|
2
|
+
|
|
3
|
+
IMPORTANT: When the user specifies a move (e.g., "I want to play at top-left, which is row=0, col=0"), you MUST call the playTicTacToe tool with action="move", NOT respond with text.
|
|
4
|
+
|
|
5
|
+
Game rules:
|
|
6
|
+
1. Start a new game with action="new_game"
|
|
7
|
+
2. For moves, use action="move" with row (0-2) and col (0-2), plus the current board state
|
|
8
|
+
3. X always goes first. Win by getting 3 in a row (horizontal, vertical, or diagonal)
|
|
9
|
+
4. Positions: row=0 is top, row=2 is bottom; col=0 is left, col=2 is right`,M=[[{row:0,col:0},{row:0,col:1},{row:0,col:2}],[{row:1,col:0},{row:1,col:1},{row:1,col:2}],[{row:2,col:0},{row:2,col:1},{row:2,col:2}],[{row:0,col:0},{row:1,col:0},{row:2,col:0}],[{row:0,col:1},{row:1,col:1},{row:2,col:1}],[{row:0,col:2},{row:1,col:2},{row:2,col:2}],[{row:0,col:0},{row:1,col:1},{row:2,col:2}],[{row:0,col:2},{row:1,col:1},{row:2,col:0}]];function P(){const r=[];for(let o=0;o<3;o++)r[o]=new Array(3).fill(".");return r}function S(r){return r.map(o=>[...o])}function I(r){return r==="X"?"O":"X"}function p(r){const o=[];for(let t=0;t<3;t++)for(let e=0;e<3;e++)r[t][e]==="."&&o.push({row:t,col:e});return o}function L(r,o,t,e){const n=S(r);return n[o][t]=e,n}function u(r){let o=0,t=0,e=0;for(let n=0;n<3;n++)for(let i=0;i<3;i++){const s=r[n][i];s==="X"?o++:s==="O"?t++:e++}return{X:o,O:t,empty:e}}function _(r){for(const o of M){const t=o.map(e=>r[e.row][e.col]);if(t[0]!=="."&&t[0]===t[1]&&t[1]===t[2])return{winner:t[0],winningLine:o}}return{winner:null,winningLine:null}}function X(r){const{winner:o,winningLine:t}=_(r);return o?{isTerminal:!0,winner:o,winningLine:t}:u(r).empty===0?{isTerminal:!0,winner:"draw",winningLine:null}:{isTerminal:!1,winner:null,winningLine:null}}function g(r){if(r.action==="new_game"){const{playerNames:m}=r,c=P(),N=p(c),O=u(c);return{board:c,currentSide:"X",playerNames:m,legalMoves:N,counts:O,isTerminal:!1,winner:null,winningLine:null,lastAction:{type:"new_game"}}}const{row:o,col:t,board:e,currentSide:n,playerNames:i}=r;if(o<0||o>2||t<0||t>2){const m=p(e),c=u(e);return{board:e,currentSide:n,playerNames:i,legalMoves:m,counts:c,isTerminal:!1,winner:null,winningLine:null,lastAction:{type:"move",row:o,col:t},error:`Invalid move: (${o}, ${t}) is out of bounds. Row and column must be 0-2.`}}if(e[o][t]!=="."){const m=p(e),c=u(e);return{board:e,currentSide:n,playerNames:i,legalMoves:m,counts:c,isTerminal:!1,winner:null,winningLine:null,lastAction:{type:"move",row:o,col:t},error:`Invalid move: (${o}, ${t}) is already occupied by ${e[o][t]}.`}}const s=L(e,o,t,n),a=I(n),l=p(s),d=u(s),{isTerminal:w,winner:h,winningLine:b}=X(s);return{board:s,currentSide:a,playerNames:i,legalMoves:l,counts:d,isTerminal:w,winner:h,winningLine:b,lastAction:{type:"move",row:o,col:t}}}const v=async(r,o)=>{try{let t;if(o.action==="new_game"){let a;o.firstPlayer?a=o.firstPlayer:a=Math.random()<.5?"computer":"user",t={action:"new_game",playerNames:{X:a,O:a==="user"?"computer":"user"}}}else if(o.action==="move"){if(typeof o.row!="number"||typeof o.col!="number"||!o.board||!o.currentSide||!o.playerNames)throw new Error("Move action requires row, col, board, currentSide, and playerNames parameters");t={action:"move",row:o.row,col:o.col,board:o.board,currentSide:o.currentSide,playerNames:o.playerNames}}else throw new Error(`Unknown action: ${o.action}`);const e=g(t);if(e.error){const a=e.playerNames[e.currentSide]==="computer",l=e.legalMoves.map(w=>`(row=${w.row}, col=${w.col})`).join(", "),d=a?`Invalid move attempted. You must make a valid move. Legal moves are: ${l}. Choose one of these moves.`:`Invalid move attempted. Tell the user they must make a valid move. Legal moves are: ${l}.`;return{message:e.error,jsonData:e,instructions:d,updating:!0}}let n="";if(e.lastAction.type==="new_game")n="Started a new Tic-Tac-Toe game! X goes first.";else if(e.lastAction.type==="move"){const a=$(e.lastAction.row,e.lastAction.col);n=`Played ${e.board[e.lastAction.row][e.lastAction.col]==="X"?"O":"X"} at ${a} (row=${e.lastAction.row}, col=${e.lastAction.col}).`}e.isTerminal&&(e.winner==="draw"?n+=" Game over - it's a draw!":e.winner&&(n+=` Game over - ${e.winner} wins!`));const i=e.playerNames[e.currentSide]==="computer",s=e.isTerminal?"The game is over. Briefly announce the result. Do NOT draw the board - the user can see it in the GUI.":i?"It is your turn. You MUST call playTicTacToe with action='move' immediately. Do NOT describe the board or explain - just make your move.":"It is the user's turn. Do NOT draw or describe the board - the user can see it in the GUI. Just say it's their turn briefly. When they specify a move, call playTicTacToe with action='move'.";return{message:n,jsonData:e,instructions:s,instructionsRequired:e.isTerminal||i,updating:o.action!=="new_game"}}catch(t){return console.error("ERR: TicTacToe game error",t),{message:`TicTacToe game error: ${t instanceof Error?t.message:"Unknown error"}`,instructions:"Acknowledge that there was an error with the TicTacToe game and suggest trying again."}}};function $(r,o){const t=["Top","Middle","Bottom"],e=["Left","Center","Right"];return`${t[r]}-${e[o]}`}const A={toolDefinition:T,execute:v,generatingMessage:"Processing TicTacToe move...",isEnabled:()=>!0,systemPrompt:f},E=[{name:"New Game (User plays X)",args:{action:"new_game",firstPlayer:"user"}},{name:"New Game (Computer plays X)",args:{action:"new_game",firstPlayer:"computer"}}];exports.SYSTEM_PROMPT=f;exports.TOOL_DEFINITION=T;exports.TOOL_NAME=y;exports.executeTicTacToe=v;exports.playTicTacToe=g;exports.pluginCore=A;exports.samples=E;
|
package/dist/core.js
ADDED
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
const h = "playTicTacToe", v = {
|
|
2
|
+
type: "function",
|
|
3
|
+
name: h,
|
|
4
|
+
description: "Play Tic-Tac-Toe (Noughts and Crosses) game with the user. You can start a new game or make moves on the 3x3 board.",
|
|
5
|
+
parameters: {
|
|
6
|
+
type: "object",
|
|
7
|
+
properties: {
|
|
8
|
+
action: {
|
|
9
|
+
type: "string",
|
|
10
|
+
enum: ["new_game", "move"],
|
|
11
|
+
description: "The action to perform: start a new game or make a move"
|
|
12
|
+
},
|
|
13
|
+
col: {
|
|
14
|
+
type: "number",
|
|
15
|
+
description: "Column position for the move (0-2, required for 'move' action). Left=0, Center=1, Right=2",
|
|
16
|
+
minimum: 0,
|
|
17
|
+
maximum: 2
|
|
18
|
+
},
|
|
19
|
+
row: {
|
|
20
|
+
type: "number",
|
|
21
|
+
description: "Row position for the move (0-2, required for 'move' action). Top=0, Middle=1, Bottom=2",
|
|
22
|
+
minimum: 0,
|
|
23
|
+
maximum: 2
|
|
24
|
+
},
|
|
25
|
+
board: {
|
|
26
|
+
type: "array",
|
|
27
|
+
description: "Current 3x3 board state BEFORE the move (required for 'move' action). Pass the current board state as-is.",
|
|
28
|
+
items: {
|
|
29
|
+
type: "array",
|
|
30
|
+
items: {
|
|
31
|
+
type: "string",
|
|
32
|
+
enum: [".", "X", "O"]
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
currentSide: {
|
|
37
|
+
type: "string",
|
|
38
|
+
enum: ["X", "O"],
|
|
39
|
+
description: "Current player's side (required for 'move' action). X always goes first."
|
|
40
|
+
},
|
|
41
|
+
playerNames: {
|
|
42
|
+
type: "object",
|
|
43
|
+
description: "Player assignments (required for 'move' action)",
|
|
44
|
+
properties: {
|
|
45
|
+
X: {
|
|
46
|
+
type: "string",
|
|
47
|
+
enum: ["user", "computer"]
|
|
48
|
+
},
|
|
49
|
+
O: {
|
|
50
|
+
type: "string",
|
|
51
|
+
enum: ["user", "computer"]
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
required: ["X", "O"]
|
|
55
|
+
},
|
|
56
|
+
firstPlayer: {
|
|
57
|
+
type: "string",
|
|
58
|
+
enum: ["user", "computer"],
|
|
59
|
+
description: "Optional: Which player should play as X (goes first) for 'new_game' action. If not specified, will be chosen randomly."
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
required: ["action"],
|
|
63
|
+
additionalProperties: !1
|
|
64
|
+
}
|
|
65
|
+
}, b = `You can play Tic-Tac-Toe with users using the playTicTacToe tool.
|
|
66
|
+
|
|
67
|
+
IMPORTANT: When the user specifies a move (e.g., "I want to play at top-left, which is row=0, col=0"), you MUST call the playTicTacToe tool with action="move", NOT respond with text.
|
|
68
|
+
|
|
69
|
+
Game rules:
|
|
70
|
+
1. Start a new game with action="new_game"
|
|
71
|
+
2. For moves, use action="move" with row (0-2) and col (0-2), plus the current board state
|
|
72
|
+
3. X always goes first. Win by getting 3 in a row (horizontal, vertical, or diagonal)
|
|
73
|
+
4. Positions: row=0 is top, row=2 is bottom; col=0 is left, col=2 is right`, N = [
|
|
74
|
+
// Rows
|
|
75
|
+
[{ row: 0, col: 0 }, { row: 0, col: 1 }, { row: 0, col: 2 }],
|
|
76
|
+
[{ row: 1, col: 0 }, { row: 1, col: 1 }, { row: 1, col: 2 }],
|
|
77
|
+
[{ row: 2, col: 0 }, { row: 2, col: 1 }, { row: 2, col: 2 }],
|
|
78
|
+
// Columns
|
|
79
|
+
[{ row: 0, col: 0 }, { row: 1, col: 0 }, { row: 2, col: 0 }],
|
|
80
|
+
[{ row: 0, col: 1 }, { row: 1, col: 1 }, { row: 2, col: 1 }],
|
|
81
|
+
[{ row: 0, col: 2 }, { row: 1, col: 2 }, { row: 2, col: 2 }],
|
|
82
|
+
// Diagonals
|
|
83
|
+
[{ row: 0, col: 0 }, { row: 1, col: 1 }, { row: 2, col: 2 }],
|
|
84
|
+
[{ row: 0, col: 2 }, { row: 1, col: 1 }, { row: 2, col: 0 }]
|
|
85
|
+
];
|
|
86
|
+
function O() {
|
|
87
|
+
const n = [];
|
|
88
|
+
for (let o = 0; o < 3; o++)
|
|
89
|
+
n[o] = new Array(3).fill(".");
|
|
90
|
+
return n;
|
|
91
|
+
}
|
|
92
|
+
function M(n) {
|
|
93
|
+
return n.map((o) => [...o]);
|
|
94
|
+
}
|
|
95
|
+
function P(n) {
|
|
96
|
+
return n === "X" ? "O" : "X";
|
|
97
|
+
}
|
|
98
|
+
function p(n) {
|
|
99
|
+
const o = [];
|
|
100
|
+
for (let t = 0; t < 3; t++)
|
|
101
|
+
for (let e = 0; e < 3; e++)
|
|
102
|
+
n[t][e] === "." && o.push({ row: t, col: e });
|
|
103
|
+
return o;
|
|
104
|
+
}
|
|
105
|
+
function S(n, o, t, e) {
|
|
106
|
+
const r = M(n);
|
|
107
|
+
return r[o][t] = e, r;
|
|
108
|
+
}
|
|
109
|
+
function u(n) {
|
|
110
|
+
let o = 0, t = 0, e = 0;
|
|
111
|
+
for (let r = 0; r < 3; r++)
|
|
112
|
+
for (let i = 0; i < 3; i++) {
|
|
113
|
+
const s = n[r][i];
|
|
114
|
+
s === "X" ? o++ : s === "O" ? t++ : e++;
|
|
115
|
+
}
|
|
116
|
+
return { X: o, O: t, empty: e };
|
|
117
|
+
}
|
|
118
|
+
function X(n) {
|
|
119
|
+
for (const o of N) {
|
|
120
|
+
const t = o.map((e) => n[e.row][e.col]);
|
|
121
|
+
if (t[0] !== "." && t[0] === t[1] && t[1] === t[2])
|
|
122
|
+
return { winner: t[0], winningLine: o };
|
|
123
|
+
}
|
|
124
|
+
return { winner: null, winningLine: null };
|
|
125
|
+
}
|
|
126
|
+
function $(n) {
|
|
127
|
+
const { winner: o, winningLine: t } = X(n);
|
|
128
|
+
return o ? { isTerminal: !0, winner: o, winningLine: t } : u(n).empty === 0 ? { isTerminal: !0, winner: "draw", winningLine: null } : { isTerminal: !1, winner: null, winningLine: null };
|
|
129
|
+
}
|
|
130
|
+
function I(n) {
|
|
131
|
+
if (n.action === "new_game") {
|
|
132
|
+
const { playerNames: m } = n, c = O(), T = p(c), g = u(c);
|
|
133
|
+
return {
|
|
134
|
+
board: c,
|
|
135
|
+
currentSide: "X",
|
|
136
|
+
// X always goes first
|
|
137
|
+
playerNames: m,
|
|
138
|
+
legalMoves: T,
|
|
139
|
+
counts: g,
|
|
140
|
+
isTerminal: !1,
|
|
141
|
+
winner: null,
|
|
142
|
+
winningLine: null,
|
|
143
|
+
lastAction: { type: "new_game" }
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
const { row: o, col: t, board: e, currentSide: r, playerNames: i } = n;
|
|
147
|
+
if (o < 0 || o > 2 || t < 0 || t > 2) {
|
|
148
|
+
const m = p(e), c = u(e);
|
|
149
|
+
return {
|
|
150
|
+
board: e,
|
|
151
|
+
currentSide: r,
|
|
152
|
+
playerNames: i,
|
|
153
|
+
legalMoves: m,
|
|
154
|
+
counts: c,
|
|
155
|
+
isTerminal: !1,
|
|
156
|
+
winner: null,
|
|
157
|
+
winningLine: null,
|
|
158
|
+
lastAction: { type: "move", row: o, col: t },
|
|
159
|
+
error: `Invalid move: (${o}, ${t}) is out of bounds. Row and column must be 0-2.`
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
if (e[o][t] !== ".") {
|
|
163
|
+
const m = p(e), c = u(e);
|
|
164
|
+
return {
|
|
165
|
+
board: e,
|
|
166
|
+
currentSide: r,
|
|
167
|
+
playerNames: i,
|
|
168
|
+
legalMoves: m,
|
|
169
|
+
counts: c,
|
|
170
|
+
isTerminal: !1,
|
|
171
|
+
winner: null,
|
|
172
|
+
winningLine: null,
|
|
173
|
+
lastAction: { type: "move", row: o, col: t },
|
|
174
|
+
error: `Invalid move: (${o}, ${t}) is already occupied by ${e[o][t]}.`
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
const s = S(e, o, t, r), a = P(r), l = p(s), d = u(s), { isTerminal: w, winner: y, winningLine: f } = $(s);
|
|
178
|
+
return {
|
|
179
|
+
board: s,
|
|
180
|
+
currentSide: a,
|
|
181
|
+
playerNames: i,
|
|
182
|
+
legalMoves: l,
|
|
183
|
+
counts: d,
|
|
184
|
+
isTerminal: w,
|
|
185
|
+
winner: y,
|
|
186
|
+
winningLine: f,
|
|
187
|
+
lastAction: { type: "move", row: o, col: t }
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
const L = async (n, o) => {
|
|
191
|
+
try {
|
|
192
|
+
let t;
|
|
193
|
+
if (o.action === "new_game") {
|
|
194
|
+
let a;
|
|
195
|
+
o.firstPlayer ? a = o.firstPlayer : a = Math.random() < 0.5 ? "computer" : "user", t = {
|
|
196
|
+
action: "new_game",
|
|
197
|
+
playerNames: { X: a, O: a === "user" ? "computer" : "user" }
|
|
198
|
+
};
|
|
199
|
+
} else if (o.action === "move") {
|
|
200
|
+
if (typeof o.row != "number" || typeof o.col != "number" || !o.board || !o.currentSide || !o.playerNames)
|
|
201
|
+
throw new Error(
|
|
202
|
+
"Move action requires row, col, board, currentSide, and playerNames parameters"
|
|
203
|
+
);
|
|
204
|
+
t = {
|
|
205
|
+
action: "move",
|
|
206
|
+
row: o.row,
|
|
207
|
+
col: o.col,
|
|
208
|
+
board: o.board,
|
|
209
|
+
currentSide: o.currentSide,
|
|
210
|
+
playerNames: o.playerNames
|
|
211
|
+
};
|
|
212
|
+
} else
|
|
213
|
+
throw new Error(`Unknown action: ${o.action}`);
|
|
214
|
+
const e = I(t);
|
|
215
|
+
if (e.error) {
|
|
216
|
+
const a = e.playerNames[e.currentSide] === "computer", l = e.legalMoves.map((w) => `(row=${w.row}, col=${w.col})`).join(", "), d = a ? `Invalid move attempted. You must make a valid move. Legal moves are: ${l}. Choose one of these moves.` : `Invalid move attempted. Tell the user they must make a valid move. Legal moves are: ${l}.`;
|
|
217
|
+
return {
|
|
218
|
+
message: e.error,
|
|
219
|
+
jsonData: e,
|
|
220
|
+
instructions: d,
|
|
221
|
+
updating: !0
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
let r = "";
|
|
225
|
+
if (e.lastAction.type === "new_game")
|
|
226
|
+
r = "Started a new Tic-Tac-Toe game! X goes first.";
|
|
227
|
+
else if (e.lastAction.type === "move") {
|
|
228
|
+
const a = A(e.lastAction.row, e.lastAction.col);
|
|
229
|
+
r = `Played ${e.board[e.lastAction.row][e.lastAction.col] === "X" ? "O" : "X"} at ${a} (row=${e.lastAction.row}, col=${e.lastAction.col}).`;
|
|
230
|
+
}
|
|
231
|
+
e.isTerminal && (e.winner === "draw" ? r += " Game over - it's a draw!" : e.winner && (r += ` Game over - ${e.winner} wins!`));
|
|
232
|
+
const i = e.playerNames[e.currentSide] === "computer", s = e.isTerminal ? "The game is over. Briefly announce the result. Do NOT draw the board - the user can see it in the GUI." : i ? "It is your turn. You MUST call playTicTacToe with action='move' immediately. Do NOT describe the board or explain - just make your move." : "It is the user's turn. Do NOT draw or describe the board - the user can see it in the GUI. Just say it's their turn briefly. When they specify a move, call playTicTacToe with action='move'.";
|
|
233
|
+
return {
|
|
234
|
+
message: r,
|
|
235
|
+
jsonData: e,
|
|
236
|
+
instructions: s,
|
|
237
|
+
instructionsRequired: e.isTerminal || i,
|
|
238
|
+
updating: o.action !== "new_game"
|
|
239
|
+
};
|
|
240
|
+
} catch (t) {
|
|
241
|
+
return console.error("ERR: TicTacToe game error", t), {
|
|
242
|
+
message: `TicTacToe game error: ${t instanceof Error ? t.message : "Unknown error"}`,
|
|
243
|
+
instructions: "Acknowledge that there was an error with the TicTacToe game and suggest trying again."
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
function A(n, o) {
|
|
248
|
+
const t = ["Top", "Middle", "Bottom"], e = ["Left", "Center", "Right"];
|
|
249
|
+
return `${t[n]}-${e[o]}`;
|
|
250
|
+
}
|
|
251
|
+
const _ = {
|
|
252
|
+
toolDefinition: v,
|
|
253
|
+
execute: L,
|
|
254
|
+
generatingMessage: "Processing TicTacToe move...",
|
|
255
|
+
isEnabled: () => !0,
|
|
256
|
+
systemPrompt: b
|
|
257
|
+
}, E = [
|
|
258
|
+
{
|
|
259
|
+
name: "New Game (User plays X)",
|
|
260
|
+
args: {
|
|
261
|
+
action: "new_game",
|
|
262
|
+
firstPlayer: "user"
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
name: "New Game (Computer plays X)",
|
|
267
|
+
args: {
|
|
268
|
+
action: "new_game",
|
|
269
|
+
firstPlayer: "computer"
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
];
|
|
273
|
+
export {
|
|
274
|
+
b as SYSTEM_PROMPT,
|
|
275
|
+
v as TOOL_DEFINITION,
|
|
276
|
+
h as TOOL_NAME,
|
|
277
|
+
L as executeTicTacToe,
|
|
278
|
+
I as playTicTacToe,
|
|
279
|
+
_ as pluginCore,
|
|
280
|
+
E as samples
|
|
281
|
+
};
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./core.cjs");exports.SYSTEM_PROMPT=e.SYSTEM_PROMPT;exports.TOOL_DEFINITION=e.TOOL_DEFINITION;exports.TOOL_NAME=e.TOOL_NAME;exports.executeTicTacToe=e.executeTicTacToe;exports.playTicTacToe=e.playTicTacToe;exports.pluginCore=e.pluginCore;exports.samples=e.samples;
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { SYSTEM_PROMPT as O, TOOL_DEFINITION as c, TOOL_NAME as o, executeTicTacToe as a, playTicTacToe as p, pluginCore as i, samples as l } from "./core.js";
|
|
2
|
+
export {
|
|
3
|
+
O as SYSTEM_PROMPT,
|
|
4
|
+
c as TOOL_DEFINITION,
|
|
5
|
+
o as TOOL_NAME,
|
|
6
|
+
a as executeTicTacToe,
|
|
7
|
+
p as playTicTacToe,
|
|
8
|
+
i as pluginCore,
|
|
9
|
+
l as samples
|
|
10
|
+
};
|
package/dist/style.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-space-y-reverse:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-400:oklch(70.4% .191 22.216);--color-red-600:oklch(57.7% .245 27.325);--color-yellow-200:oklch(94.5% .129 101.54);--color-yellow-400:oklch(85.2% .199 91.936);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-600:oklch(54.6% .245 262.881);--color-indigo-100:oklch(93% .034 272.788);--color-indigo-200:oklch(87% .065 274.039);--color-indigo-700:oklch(45.7% .24 277.023);--color-gray-50:oklch(98.5% .002 247.839);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-800:oklch(27.8% .033 256.848);--color-white:#fff;--spacing:.25rem;--container-3xl:48rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75/1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.mx-auto{margin-inline:auto}.mt-4{margin-top:calc(var(--spacing)*4)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.mb-5{margin-bottom:calc(var(--spacing)*5)}.mb-8{margin-bottom:calc(var(--spacing)*8)}.flex{display:flex}.grid{display:grid}.inline-block{display:inline-block}.h-4{height:calc(var(--spacing)*4)}.h-6{height:calc(var(--spacing)*6)}.h-16{height:calc(var(--spacing)*16)}.h-24{height:calc(var(--spacing)*24)}.h-\[500px\]{height:500px}.h-full{height:100%}.w-4{width:calc(var(--spacing)*4)}.w-6{width:calc(var(--spacing)*6)}.w-16{width:calc(var(--spacing)*16)}.w-24{width:calc(var(--spacing)*24)}.w-full{width:100%}.max-w-3xl{max-width:var(--container-3xl)}.max-w-\[200px\]{max-width:200px}.cursor-pointer{cursor:pointer}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-center{justify-content:center}.gap-0\.5{gap:calc(var(--spacing)*.5)}.gap-1{gap:calc(var(--spacing)*1)}.gap-2{gap:calc(var(--spacing)*2)}.gap-8{gap:calc(var(--spacing)*8)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*1)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*1)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}.rounded{border-radius:.25rem}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.border{border-style:var(--tw-border-style);border-width:1px}.border-gray-600{border-color:var(--color-gray-600)}.border-indigo-200{border-color:var(--color-indigo-200)}.bg-gray-50{background-color:var(--color-gray-50)}.bg-gray-100{background-color:var(--color-gray-100)}.bg-gray-200{background-color:var(--color-gray-200)}.bg-gray-600{background-color:var(--color-gray-600)}.bg-gray-700{background-color:var(--color-gray-700)}.bg-gray-800{background-color:var(--color-gray-800)}.bg-indigo-100{background-color:var(--color-indigo-100)}.bg-white{background-color:var(--color-white)}.bg-yellow-200{background-color:var(--color-yellow-200)}.p-0\.5{padding:calc(var(--spacing)*.5)}.p-2{padding:calc(var(--spacing)*2)}.p-3{padding:calc(var(--spacing)*3)}.p-4{padding:calc(var(--spacing)*4)}.p-5{padding:calc(var(--spacing)*5)}.p-8{padding:calc(var(--spacing)*8)}.px-4{padding-inline:calc(var(--spacing)*4)}.py-2{padding-block:calc(var(--spacing)*2)}.text-center{text-align:center}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.text-blue-400{color:var(--color-blue-400)}.text-blue-600{color:var(--color-blue-600)}.text-gray-200{color:var(--color-gray-200)}.text-gray-500{color:var(--color-gray-500)}.text-gray-600{color:var(--color-gray-600)}.text-gray-700{color:var(--color-gray-700)}.text-gray-800{color:var(--color-gray-800)}.text-indigo-700{color:var(--color-indigo-700)}.text-red-400{color:var(--color-red-400)}.text-red-600{color:var(--color-red-600)}.opacity-30{opacity:.3}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-2{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-yellow-400{--tw-ring-color:var(--color-yellow-400)}@media(hover:hover){.hover\:bg-gray-100:hover{background-color:var(--color-gray-100)}.hover\:bg-indigo-200:hover{background-color:var(--color-indigo-200)}}}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ToolResult } from "gui-chat-protocol/vue";
|
|
2
|
+
import type { TicTacToeState } from "../core/types";
|
|
3
|
+
type __VLS_Props = {
|
|
4
|
+
result: ToolResult<never, TicTacToeState>;
|
|
5
|
+
};
|
|
6
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
7
|
+
declare const _default: typeof __VLS_export;
|
|
8
|
+
export default _default;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ToolResult, SendTextMessageOptions } from "gui-chat-protocol/vue";
|
|
2
|
+
import type { TicTacToeState } from "../core/types";
|
|
3
|
+
type __VLS_Props = {
|
|
4
|
+
selectedResult: ToolResult<never, TicTacToeState> | null;
|
|
5
|
+
sendTextMessage?: (text: string, options?: SendTextMessageOptions) => void;
|
|
6
|
+
};
|
|
7
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
8
|
+
declare const _default: typeof __VLS_export;
|
|
9
|
+
export default _default;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TicTacToe Plugin - Vue Implementation
|
|
3
|
+
*/
|
|
4
|
+
import "../style.css";
|
|
5
|
+
import type { ToolPlugin } from "gui-chat-protocol/vue";
|
|
6
|
+
import type { TicTacToeArgs, TicTacToeState } from "../core/types";
|
|
7
|
+
import View from "./View.vue";
|
|
8
|
+
import Preview from "./Preview.vue";
|
|
9
|
+
export declare const plugin: ToolPlugin<never, TicTacToeState, TicTacToeArgs>;
|
|
10
|
+
export type { Cell, Side, TicTacToeBoard, PlayerType, TicTacToeArgs, NewGameCommand, MoveCommand, Command, TicTacToeState, TicTacToeClickData, } from "../core/types";
|
|
11
|
+
export { TOOL_NAME, TOOL_DEFINITION, SYSTEM_PROMPT, playTicTacToe, executeTicTacToe, pluginCore, } from "../core/plugin";
|
|
12
|
+
export { samples } from "../core/samples";
|
|
13
|
+
export { View, Preview };
|
|
14
|
+
declare const _default: {
|
|
15
|
+
plugin: ToolPlugin<never, TicTacToeState, TicTacToeArgs, import("gui-chat-protocol/vue").InputHandler, Record<string, unknown>>;
|
|
16
|
+
};
|
|
17
|
+
export default _default;
|
package/dist/vue.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const i=require("./core.cjs"),e=require("vue"),N={class:"w-full h-full flex flex-col items-center justify-center p-4 bg-gray-100"},T={key:0,class:"flex flex-col items-center"},C={key:0},h={key:1},V={class:"grid grid-cols-3 gap-1 p-2 bg-gray-700 rounded-lg shadow-lg"},b=["onClick","onMouseenter","onMouseleave"],_={key:0,class:"w-16 h-16 text-blue-600",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"3","stroke-linecap":"round"},D={key:1,class:"w-16 h-16 text-red-600",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"3"},S={key:1,cx:"12",cy:"12",r:"8"},O={class:"mt-4 flex gap-8 text-lg"},$={class:"flex items-center gap-2"},M={class:"text-gray-500 text-sm"},j={class:"flex items-center gap-2"},L={class:"text-gray-500 text-sm"},w=e.defineComponent({__name:"View",props:{selectedResult:{},sendTextMessage:{type:Function}},setup(a){const u=a,t=e.ref(null),v=e.ref(null);e.watch(()=>u.selectedResult,n=>{n?.toolName==="playTicTacToe"&&n.jsonData&&(t.value=n.jsonData)},{immediate:!0});const f=e.computed(()=>{if(!t.value?.playerNames)return"";const n=t.value.playerNames[t.value.currentSide];return n.charAt(0).toUpperCase()+n.slice(1)}),d=e.computed(()=>t.value?.playerNames&&t.value.playerNames[t.value.currentSide]==="computer"),s=e.computed(()=>t.value?t.value.isTerminal?t.value.winner==="draw"?"text-gray-600":t.value.winner==="X"?"text-blue-600":"text-red-600":t.value.currentSide==="X"?"text-blue-600":"text-red-600":""),c=e.computed(()=>{if(!t.value?.board)return[];const n=[];for(let l=0;l<3;l++)for(let o=0;o<3;o++){const r=t.value.board[l][o],p=t.value.legalMoves?.some(y=>y.row===l&&y.col===o),x=t.value.winningLine?.some(y=>y.row===l&&y.col===o);n.push({row:l,col:o,piece:r!=="."?r:null,isLegalMove:p??!1,isWinningCell:x??!1})}return n});function m(n,l){const o="w-24 h-24 flex items-center justify-center bg-white rounded";let r="";return n.isWinningCell?r="bg-yellow-200 ring-2 ring-yellow-400":n.isLegalMove&&!d.value&&!t.value?.isTerminal&&(r=v.value===l?"bg-gray-200 cursor-pointer":"hover:bg-gray-100 cursor-pointer"),`${o} ${r}`}function g(n){if(!t.value||t.value.isTerminal||d.value)return;const l=c.value[n];if(!l.isLegalMove)return;const o=["top","middle","bottom"],r=["left","center","right"],p=`${o[l.row]}-${r[l.col]}`,x={row:l.row,col:l.col,currentState:t.value};u.sendTextMessage?.(`I want to play at ${p}, which is row=${l.row}, col=${l.col}`,{data:x})}function k(n,l){!t.value||t.value.isTerminal||d.value||!c.value[n].isLegalMove||(v.value=l?n:null)}return(n,l)=>(e.openBlock(),e.createElementBlock("div",N,[t.value?(e.openBlock(),e.createElementBlock("div",T,[l[6]||(l[6]=e.createElementVNode("h1",{class:"text-2xl font-bold text-gray-800 mb-2"},"Tic-Tac-Toe",-1)),e.createElementVNode("div",{class:e.normalizeClass(["text-lg font-semibold mb-4 text-center",s.value])},[t.value.isTerminal?(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[t.value.winner==="draw"?(e.openBlock(),e.createElementBlock("span",C,"It's a Draw!")):(e.openBlock(),e.createElementBlock("span",h,e.toDisplayString(t.value.winner)+" Wins!",1))],64)):(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[e.createTextVNode(e.toDisplayString(f.value)+"'s Turn ("+e.toDisplayString(t.value.currentSide)+") ",1)],64))],2),e.createElementVNode("div",V,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(c.value,(o,r)=>(e.openBlock(),e.createElementBlock("div",{key:r,class:e.normalizeClass(m(o,r)),onClick:p=>g(r),onMouseenter:p=>k(r,!0),onMouseleave:p=>k(r,!1)},[o.piece==="X"?(e.openBlock(),e.createElementBlock("svg",_,[...l[0]||(l[0]=[e.createElementVNode("line",{x1:"4",y1:"4",x2:"20",y2:"20"},null,-1),e.createElementVNode("line",{x1:"20",y1:"4",x2:"4",y2:"20"},null,-1)])])):o.piece==="O"?(e.openBlock(),e.createElementBlock("svg",D,[...l[1]||(l[1]=[e.createElementVNode("circle",{cx:"12",cy:"12",r:"8"},null,-1)])])):o.isLegalMove&&!d.value&&v.value===r?(e.openBlock(),e.createElementBlock("svg",{key:2,class:e.normalizeClass(["w-16 h-16 opacity-30",t.value.currentSide==="X"?"text-blue-400":"text-red-400"]),viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"3","stroke-linecap":"round"},[t.value.currentSide==="X"?(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[l[2]||(l[2]=e.createElementVNode("line",{x1:"4",y1:"4",x2:"20",y2:"20"},null,-1)),l[3]||(l[3]=e.createElementVNode("line",{x1:"20",y1:"4",x2:"4",y2:"20"},null,-1))],64)):(e.openBlock(),e.createElementBlock("circle",S))],2)):e.createCommentVNode("",!0)],42,b))),128))]),e.createElementVNode("div",O,[e.createElementVNode("div",$,[l[4]||(l[4]=e.createElementVNode("span",{class:"text-blue-600 font-bold"},"X:",-1)),e.createElementVNode("span",null,e.toDisplayString(t.value.counts.X),1),e.createElementVNode("span",M,"("+e.toDisplayString(t.value.playerNames.X)+")",1)]),e.createElementVNode("div",j,[l[5]||(l[5]=e.createElementVNode("span",{class:"text-red-600 font-bold"},"O:",-1)),e.createElementVNode("span",null,e.toDisplayString(t.value.counts.O),1),e.createElementVNode("span",L,"("+e.toDisplayString(t.value.playerNames.O)+")",1)])])])):e.createCommentVNode("",!0)]))}}),X={class:"p-3 bg-gray-50 rounded"},F={key:0,class:"space-y-2"},P={class:"flex justify-center"},z={class:"inline-block bg-gray-600 p-0.5 rounded"},W={class:"grid grid-cols-3 gap-0.5"},I={key:0,class:"w-4 h-4 text-blue-600",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"3","stroke-linecap":"round"},A={key:1,class:"w-4 h-4 text-red-600",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"3"},R={class:"text-xs text-center space-y-1"},q={key:0,class:"text-gray-600"},E=e.defineComponent({__name:"Preview",props:{result:{}},setup(a){const u=a;function t(s,c){return u.result.jsonData?.winningLine?.some(m=>m.row===s&&m.col===c)??!1}function v(s){return s.isTerminal?s.winner==="draw"?"Draw!":s.winner==="X"?"X Wins!":s.winner==="O"?"O Wins!":"Game Over":""}function f(){return u.result.jsonData?.isTerminal?u.result.jsonData.winner==="draw"?"text-gray-600":u.result.jsonData.winner==="X"?"text-blue-600":u.result.jsonData.winner==="O"?"text-red-600":"":""}function d(s){return s.charAt(0).toUpperCase()+s.slice(1)}return(s,c)=>(e.openBlock(),e.createElementBlock("div",X,[a.result.jsonData?(e.openBlock(),e.createElementBlock("div",F,[e.createElementVNode("div",P,[e.createElementVNode("div",z,[e.createElementVNode("div",W,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(a.result.jsonData.board,(m,g)=>(e.openBlock(),e.createElementBlock(e.Fragment,{key:g},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(m,(k,n)=>(e.openBlock(),e.createElementBlock("div",{key:`${g}-${n}`,class:e.normalizeClass(["w-6 h-6 flex items-center justify-center bg-white rounded-sm",t(g,n)?"bg-yellow-200":""])},[k==="X"?(e.openBlock(),e.createElementBlock("svg",I,[...c[0]||(c[0]=[e.createElementVNode("line",{x1:"4",y1:"4",x2:"20",y2:"20"},null,-1),e.createElementVNode("line",{x1:"20",y1:"4",x2:"4",y2:"20"},null,-1)])])):k==="O"?(e.openBlock(),e.createElementBlock("svg",A,[...c[1]||(c[1]=[e.createElementVNode("circle",{cx:"12",cy:"12",r:"8"},null,-1)])])):e.createCommentVNode("",!0)],2))),128))],64))),128))])])]),e.createElementVNode("div",R,[a.result.jsonData.isTerminal?(e.openBlock(),e.createElementBlock("div",{key:1,class:e.normalizeClass(["font-medium",f()])},e.toDisplayString(v(a.result.jsonData)),3)):(e.openBlock(),e.createElementBlock("div",q,[e.createElementVNode("span",{class:e.normalizeClass(a.result.jsonData.currentSide==="X"?"text-blue-600":"text-red-600")},e.toDisplayString(a.result.jsonData.currentSide),3),e.createTextVNode(" "+e.toDisplayString(d(a.result.jsonData.playerNames[a.result.jsonData.currentSide]))+" to play ",1)]))])])):e.createCommentVNode("",!0)]))}}),B={...i.pluginCore,viewComponent:w,previewComponent:E,samples:i.samples},G={plugin:B};exports.SYSTEM_PROMPT=i.SYSTEM_PROMPT;exports.TOOL_DEFINITION=i.TOOL_DEFINITION;exports.TOOL_NAME=i.TOOL_NAME;exports.executeTicTacToe=i.executeTicTacToe;exports.playTicTacToe=i.playTicTacToe;exports.pluginCore=i.pluginCore;exports.samples=i.samples;exports.Preview=E;exports.View=w;exports.default=G;exports.plugin=B;
|
package/dist/vue.js
ADDED
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import { samples as M, pluginCore as O } from "./core.js";
|
|
2
|
+
import { SYSTEM_PROMPT as ce, TOOL_DEFINITION as de, TOOL_NAME as ve, executeTicTacToe as ye, playTicTacToe as fe } from "./core.js";
|
|
3
|
+
import { defineComponent as j, ref as D, watch as X, computed as b, createElementBlock as n, openBlock as l, createCommentVNode as C, createElementVNode as s, normalizeClass as x, Fragment as y, toDisplayString as d, createTextVNode as N, renderList as $ } from "vue";
|
|
4
|
+
const L = { class: "w-full h-full flex flex-col items-center justify-center p-4 bg-gray-100" }, S = {
|
|
5
|
+
key: 0,
|
|
6
|
+
class: "flex flex-col items-center"
|
|
7
|
+
}, B = { key: 0 }, W = { key: 1 }, V = { class: "grid grid-cols-3 gap-1 p-2 bg-gray-700 rounded-lg shadow-lg" }, E = ["onClick", "onMouseenter", "onMouseleave"], P = {
|
|
8
|
+
key: 0,
|
|
9
|
+
class: "w-16 h-16 text-blue-600",
|
|
10
|
+
viewBox: "0 0 24 24",
|
|
11
|
+
fill: "none",
|
|
12
|
+
stroke: "currentColor",
|
|
13
|
+
"stroke-width": "3",
|
|
14
|
+
"stroke-linecap": "round"
|
|
15
|
+
}, F = {
|
|
16
|
+
key: 1,
|
|
17
|
+
class: "w-16 h-16 text-red-600",
|
|
18
|
+
viewBox: "0 0 24 24",
|
|
19
|
+
fill: "none",
|
|
20
|
+
stroke: "currentColor",
|
|
21
|
+
"stroke-width": "3"
|
|
22
|
+
}, A = {
|
|
23
|
+
key: 1,
|
|
24
|
+
cx: "12",
|
|
25
|
+
cy: "12",
|
|
26
|
+
r: "8"
|
|
27
|
+
}, I = { class: "mt-4 flex gap-8 text-lg" }, R = { class: "flex items-center gap-2" }, z = { class: "text-gray-500 text-sm" }, G = { class: "flex items-center gap-2" }, U = { class: "text-gray-500 text-sm" }, H = /* @__PURE__ */ j({
|
|
28
|
+
__name: "View",
|
|
29
|
+
props: {
|
|
30
|
+
selectedResult: {},
|
|
31
|
+
sendTextMessage: { type: Function }
|
|
32
|
+
},
|
|
33
|
+
setup(u) {
|
|
34
|
+
const v = u, e = D(null), p = D(null);
|
|
35
|
+
X(
|
|
36
|
+
() => v.selectedResult,
|
|
37
|
+
(r) => {
|
|
38
|
+
r?.toolName === "playTicTacToe" && r.jsonData && (e.value = r.jsonData);
|
|
39
|
+
},
|
|
40
|
+
{ immediate: !0 }
|
|
41
|
+
);
|
|
42
|
+
const T = b(() => {
|
|
43
|
+
if (!e.value?.playerNames) return "";
|
|
44
|
+
const r = e.value.playerNames[e.value.currentSide];
|
|
45
|
+
return r.charAt(0).toUpperCase() + r.slice(1);
|
|
46
|
+
}), f = b(() => e.value?.playerNames && e.value.playerNames[e.value.currentSide] === "computer"), i = b(() => e.value ? e.value.isTerminal ? e.value.winner === "draw" ? "text-gray-600" : e.value.winner === "X" ? "text-blue-600" : "text-red-600" : e.value.currentSide === "X" ? "text-blue-600" : "text-red-600" : ""), c = b(() => {
|
|
47
|
+
if (!e.value?.board) return [];
|
|
48
|
+
const r = [];
|
|
49
|
+
for (let t = 0; t < 3; t++)
|
|
50
|
+
for (let o = 0; o < 3; o++) {
|
|
51
|
+
const a = e.value.board[t][o], m = e.value.legalMoves?.some(
|
|
52
|
+
(h) => h.row === t && h.col === o
|
|
53
|
+
), _ = e.value.winningLine?.some(
|
|
54
|
+
(h) => h.row === t && h.col === o
|
|
55
|
+
);
|
|
56
|
+
r.push({
|
|
57
|
+
row: t,
|
|
58
|
+
col: o,
|
|
59
|
+
piece: a !== "." ? a : null,
|
|
60
|
+
isLegalMove: m ?? !1,
|
|
61
|
+
isWinningCell: _ ?? !1
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
return r;
|
|
65
|
+
});
|
|
66
|
+
function g(r, t) {
|
|
67
|
+
const o = "w-24 h-24 flex items-center justify-center bg-white rounded";
|
|
68
|
+
let a = "";
|
|
69
|
+
return r.isWinningCell ? a = "bg-yellow-200 ring-2 ring-yellow-400" : r.isLegalMove && !f.value && !e.value?.isTerminal && (a = p.value === t ? "bg-gray-200 cursor-pointer" : "hover:bg-gray-100 cursor-pointer"), `${o} ${a}`;
|
|
70
|
+
}
|
|
71
|
+
function w(r) {
|
|
72
|
+
if (!e.value || e.value.isTerminal || f.value)
|
|
73
|
+
return;
|
|
74
|
+
const t = c.value[r];
|
|
75
|
+
if (!t.isLegalMove) return;
|
|
76
|
+
const o = ["top", "middle", "bottom"], a = ["left", "center", "right"], m = `${o[t.row]}-${a[t.col]}`, _ = {
|
|
77
|
+
row: t.row,
|
|
78
|
+
col: t.col,
|
|
79
|
+
currentState: e.value
|
|
80
|
+
};
|
|
81
|
+
v.sendTextMessage?.(
|
|
82
|
+
`I want to play at ${m}, which is row=${t.row}, col=${t.col}`,
|
|
83
|
+
{ data: _ }
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
function k(r, t) {
|
|
87
|
+
!e.value || e.value.isTerminal || f.value || !c.value[r].isLegalMove || (p.value = t ? r : null);
|
|
88
|
+
}
|
|
89
|
+
return (r, t) => (l(), n("div", L, [
|
|
90
|
+
e.value ? (l(), n("div", S, [
|
|
91
|
+
t[6] || (t[6] = s("h1", { class: "text-2xl font-bold text-gray-800 mb-2" }, "Tic-Tac-Toe", -1)),
|
|
92
|
+
s("div", {
|
|
93
|
+
class: x(["text-lg font-semibold mb-4 text-center", i.value])
|
|
94
|
+
}, [
|
|
95
|
+
e.value.isTerminal ? (l(), n(y, { key: 0 }, [
|
|
96
|
+
e.value.winner === "draw" ? (l(), n("span", B, "It's a Draw!")) : (l(), n("span", W, d(e.value.winner) + " Wins!", 1))
|
|
97
|
+
], 64)) : (l(), n(y, { key: 1 }, [
|
|
98
|
+
N(d(T.value) + "'s Turn (" + d(e.value.currentSide) + ") ", 1)
|
|
99
|
+
], 64))
|
|
100
|
+
], 2),
|
|
101
|
+
s("div", V, [
|
|
102
|
+
(l(!0), n(y, null, $(c.value, (o, a) => (l(), n("div", {
|
|
103
|
+
key: a,
|
|
104
|
+
class: x(g(o, a)),
|
|
105
|
+
onClick: (m) => w(a),
|
|
106
|
+
onMouseenter: (m) => k(a, !0),
|
|
107
|
+
onMouseleave: (m) => k(a, !1)
|
|
108
|
+
}, [
|
|
109
|
+
o.piece === "X" ? (l(), n("svg", P, [...t[0] || (t[0] = [
|
|
110
|
+
s("line", {
|
|
111
|
+
x1: "4",
|
|
112
|
+
y1: "4",
|
|
113
|
+
x2: "20",
|
|
114
|
+
y2: "20"
|
|
115
|
+
}, null, -1),
|
|
116
|
+
s("line", {
|
|
117
|
+
x1: "20",
|
|
118
|
+
y1: "4",
|
|
119
|
+
x2: "4",
|
|
120
|
+
y2: "20"
|
|
121
|
+
}, null, -1)
|
|
122
|
+
])])) : o.piece === "O" ? (l(), n("svg", F, [...t[1] || (t[1] = [
|
|
123
|
+
s("circle", {
|
|
124
|
+
cx: "12",
|
|
125
|
+
cy: "12",
|
|
126
|
+
r: "8"
|
|
127
|
+
}, null, -1)
|
|
128
|
+
])])) : o.isLegalMove && !f.value && p.value === a ? (l(), n("svg", {
|
|
129
|
+
key: 2,
|
|
130
|
+
class: x(["w-16 h-16 opacity-30", e.value.currentSide === "X" ? "text-blue-400" : "text-red-400"]),
|
|
131
|
+
viewBox: "0 0 24 24",
|
|
132
|
+
fill: "none",
|
|
133
|
+
stroke: "currentColor",
|
|
134
|
+
"stroke-width": "3",
|
|
135
|
+
"stroke-linecap": "round"
|
|
136
|
+
}, [
|
|
137
|
+
e.value.currentSide === "X" ? (l(), n(y, { key: 0 }, [
|
|
138
|
+
t[2] || (t[2] = s("line", {
|
|
139
|
+
x1: "4",
|
|
140
|
+
y1: "4",
|
|
141
|
+
x2: "20",
|
|
142
|
+
y2: "20"
|
|
143
|
+
}, null, -1)),
|
|
144
|
+
t[3] || (t[3] = s("line", {
|
|
145
|
+
x1: "20",
|
|
146
|
+
y1: "4",
|
|
147
|
+
x2: "4",
|
|
148
|
+
y2: "20"
|
|
149
|
+
}, null, -1))
|
|
150
|
+
], 64)) : (l(), n("circle", A))
|
|
151
|
+
], 2)) : C("", !0)
|
|
152
|
+
], 42, E))), 128))
|
|
153
|
+
]),
|
|
154
|
+
s("div", I, [
|
|
155
|
+
s("div", R, [
|
|
156
|
+
t[4] || (t[4] = s("span", { class: "text-blue-600 font-bold" }, "X:", -1)),
|
|
157
|
+
s("span", null, d(e.value.counts.X), 1),
|
|
158
|
+
s("span", z, "(" + d(e.value.playerNames.X) + ")", 1)
|
|
159
|
+
]),
|
|
160
|
+
s("div", G, [
|
|
161
|
+
t[5] || (t[5] = s("span", { class: "text-red-600 font-bold" }, "O:", -1)),
|
|
162
|
+
s("span", null, d(e.value.counts.O), 1),
|
|
163
|
+
s("span", U, "(" + d(e.value.playerNames.O) + ")", 1)
|
|
164
|
+
])
|
|
165
|
+
])
|
|
166
|
+
])) : C("", !0)
|
|
167
|
+
]));
|
|
168
|
+
}
|
|
169
|
+
}), Y = { class: "p-3 bg-gray-50 rounded" }, q = {
|
|
170
|
+
key: 0,
|
|
171
|
+
class: "space-y-2"
|
|
172
|
+
}, J = { class: "flex justify-center" }, K = { class: "inline-block bg-gray-600 p-0.5 rounded" }, Q = { class: "grid grid-cols-3 gap-0.5" }, Z = {
|
|
173
|
+
key: 0,
|
|
174
|
+
class: "w-4 h-4 text-blue-600",
|
|
175
|
+
viewBox: "0 0 24 24",
|
|
176
|
+
fill: "none",
|
|
177
|
+
stroke: "currentColor",
|
|
178
|
+
"stroke-width": "3",
|
|
179
|
+
"stroke-linecap": "round"
|
|
180
|
+
}, ee = {
|
|
181
|
+
key: 1,
|
|
182
|
+
class: "w-4 h-4 text-red-600",
|
|
183
|
+
viewBox: "0 0 24 24",
|
|
184
|
+
fill: "none",
|
|
185
|
+
stroke: "currentColor",
|
|
186
|
+
"stroke-width": "3"
|
|
187
|
+
}, te = { class: "text-xs text-center space-y-1" }, se = {
|
|
188
|
+
key: 0,
|
|
189
|
+
class: "text-gray-600"
|
|
190
|
+
}, ne = /* @__PURE__ */ j({
|
|
191
|
+
__name: "Preview",
|
|
192
|
+
props: {
|
|
193
|
+
result: {}
|
|
194
|
+
},
|
|
195
|
+
setup(u) {
|
|
196
|
+
const v = u;
|
|
197
|
+
function e(i, c) {
|
|
198
|
+
return v.result.jsonData?.winningLine?.some(
|
|
199
|
+
(g) => g.row === i && g.col === c
|
|
200
|
+
) ?? !1;
|
|
201
|
+
}
|
|
202
|
+
function p(i) {
|
|
203
|
+
return i.isTerminal ? i.winner === "draw" ? "Draw!" : i.winner === "X" ? "X Wins!" : i.winner === "O" ? "O Wins!" : "Game Over" : "";
|
|
204
|
+
}
|
|
205
|
+
function T() {
|
|
206
|
+
return v.result.jsonData?.isTerminal ? v.result.jsonData.winner === "draw" ? "text-gray-600" : v.result.jsonData.winner === "X" ? "text-blue-600" : v.result.jsonData.winner === "O" ? "text-red-600" : "" : "";
|
|
207
|
+
}
|
|
208
|
+
function f(i) {
|
|
209
|
+
return i.charAt(0).toUpperCase() + i.slice(1);
|
|
210
|
+
}
|
|
211
|
+
return (i, c) => (l(), n("div", Y, [
|
|
212
|
+
u.result.jsonData ? (l(), n("div", q, [
|
|
213
|
+
s("div", J, [
|
|
214
|
+
s("div", K, [
|
|
215
|
+
s("div", Q, [
|
|
216
|
+
(l(!0), n(y, null, $(u.result.jsonData.board, (g, w) => (l(), n(y, { key: w }, [
|
|
217
|
+
(l(!0), n(y, null, $(g, (k, r) => (l(), n("div", {
|
|
218
|
+
key: `${w}-${r}`,
|
|
219
|
+
class: x(["w-6 h-6 flex items-center justify-center bg-white rounded-sm", e(w, r) ? "bg-yellow-200" : ""])
|
|
220
|
+
}, [
|
|
221
|
+
k === "X" ? (l(), n("svg", Z, [...c[0] || (c[0] = [
|
|
222
|
+
s("line", {
|
|
223
|
+
x1: "4",
|
|
224
|
+
y1: "4",
|
|
225
|
+
x2: "20",
|
|
226
|
+
y2: "20"
|
|
227
|
+
}, null, -1),
|
|
228
|
+
s("line", {
|
|
229
|
+
x1: "20",
|
|
230
|
+
y1: "4",
|
|
231
|
+
x2: "4",
|
|
232
|
+
y2: "20"
|
|
233
|
+
}, null, -1)
|
|
234
|
+
])])) : k === "O" ? (l(), n("svg", ee, [...c[1] || (c[1] = [
|
|
235
|
+
s("circle", {
|
|
236
|
+
cx: "12",
|
|
237
|
+
cy: "12",
|
|
238
|
+
r: "8"
|
|
239
|
+
}, null, -1)
|
|
240
|
+
])])) : C("", !0)
|
|
241
|
+
], 2))), 128))
|
|
242
|
+
], 64))), 128))
|
|
243
|
+
])
|
|
244
|
+
])
|
|
245
|
+
]),
|
|
246
|
+
s("div", te, [
|
|
247
|
+
u.result.jsonData.isTerminal ? (l(), n("div", {
|
|
248
|
+
key: 1,
|
|
249
|
+
class: x(["font-medium", T()])
|
|
250
|
+
}, d(p(u.result.jsonData)), 3)) : (l(), n("div", se, [
|
|
251
|
+
s("span", {
|
|
252
|
+
class: x(u.result.jsonData.currentSide === "X" ? "text-blue-600" : "text-red-600")
|
|
253
|
+
}, d(u.result.jsonData.currentSide), 3),
|
|
254
|
+
N(" " + d(f(u.result.jsonData.playerNames[u.result.jsonData.currentSide])) + " to play ", 1)
|
|
255
|
+
]))
|
|
256
|
+
])
|
|
257
|
+
])) : C("", !0)
|
|
258
|
+
]));
|
|
259
|
+
}
|
|
260
|
+
}), le = {
|
|
261
|
+
...O,
|
|
262
|
+
viewComponent: H,
|
|
263
|
+
previewComponent: ne,
|
|
264
|
+
samples: M
|
|
265
|
+
}, ae = { plugin: le };
|
|
266
|
+
export {
|
|
267
|
+
ne as Preview,
|
|
268
|
+
ce as SYSTEM_PROMPT,
|
|
269
|
+
de as TOOL_DEFINITION,
|
|
270
|
+
ve as TOOL_NAME,
|
|
271
|
+
H as View,
|
|
272
|
+
ae as default,
|
|
273
|
+
ye as executeTicTacToe,
|
|
274
|
+
fe as playTicTacToe,
|
|
275
|
+
le as plugin,
|
|
276
|
+
O as pluginCore,
|
|
277
|
+
M as samples
|
|
278
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@gui-chat-plugin/tictactoe",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Tic-Tac-Toe game plugin for GUI Chat",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
},
|
|
15
|
+
"./core": {
|
|
16
|
+
"types": "./dist/core/index.d.ts",
|
|
17
|
+
"import": "./dist/core.js",
|
|
18
|
+
"require": "./dist/core.cjs"
|
|
19
|
+
},
|
|
20
|
+
"./vue": {
|
|
21
|
+
"types": "./dist/vue/index.d.ts",
|
|
22
|
+
"import": "./dist/vue.js",
|
|
23
|
+
"require": "./dist/vue.cjs"
|
|
24
|
+
},
|
|
25
|
+
"./style.css": "./dist/style.css"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"dist"
|
|
29
|
+
],
|
|
30
|
+
"scripts": {
|
|
31
|
+
"dev": "vite",
|
|
32
|
+
"build": "vite build && vue-tsc -p tsconfig.build.json --emitDeclarationOnly",
|
|
33
|
+
"typecheck": "vue-tsc --noEmit",
|
|
34
|
+
"lint": "eslint src demo"
|
|
35
|
+
},
|
|
36
|
+
"peerDependencies": {
|
|
37
|
+
"gui-chat-protocol": "^0.0.1",
|
|
38
|
+
"vue": "^3.5.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@tailwindcss/vite": "^4.1.18",
|
|
42
|
+
"@typescript-eslint/eslint-plugin": "^8.53.0",
|
|
43
|
+
"@typescript-eslint/parser": "^8.53.0",
|
|
44
|
+
"@vitejs/plugin-vue": "^6.0.3",
|
|
45
|
+
"eslint": "^9.39.2",
|
|
46
|
+
"eslint-plugin-vue": "^10.6.2",
|
|
47
|
+
"globals": "^17.0.0",
|
|
48
|
+
"gui-chat-protocol": "^0.0.2",
|
|
49
|
+
"tailwindcss": "^4.1.18",
|
|
50
|
+
"typescript": "~5.9.3",
|
|
51
|
+
"vite": "^7.3.1",
|
|
52
|
+
"vue": "^3.5.27",
|
|
53
|
+
"vue-eslint-parser": "^10.2.0",
|
|
54
|
+
"vue-tsc": "^3.2.2"
|
|
55
|
+
},
|
|
56
|
+
"keywords": [
|
|
57
|
+
"guichat",
|
|
58
|
+
"plugin",
|
|
59
|
+
"tictactoe",
|
|
60
|
+
"game"
|
|
61
|
+
],
|
|
62
|
+
"license": "MIT"
|
|
63
|
+
}
|