@gui-chat-plugin/go 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 ADDED
@@ -0,0 +1,110 @@
1
+ # @gui-chat-plugin/go
2
+
3
+ Go (Baduk/Weiqi) game plugin for GUI Chat applications. Play Go on a 9x9 board against an AI assistant.
4
+
5
+ ## Features
6
+
7
+ - Full Go game implementation on 9x9 board
8
+ - Interactive board with clickable intersections
9
+ - Stone capture detection and counting
10
+ - Territory calculation for scoring
11
+ - Game end detection (two consecutive passes)
12
+ - Suicide rule enforcement
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ yarn add @gui-chat-plugin/go
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ ### Vue Integration
23
+
24
+ ```typescript
25
+ // In src/tools/index.ts
26
+ import GoPlugin from "@gui-chat-plugin/go/vue";
27
+
28
+ const pluginList = [
29
+ // ... other plugins
30
+ GoPlugin,
31
+ ];
32
+
33
+ // In src/main.ts
34
+ import "@gui-chat-plugin/go/style.css";
35
+ ```
36
+
37
+ ### Core-only Usage
38
+
39
+ ```typescript
40
+ import { executeGo, playGo, TOOL_DEFINITION } from "@gui-chat-plugin/go";
41
+
42
+ // Start a new game
43
+ const result = await executeGo(context, {
44
+ action: "new_game",
45
+ firstPlayer: "user",
46
+ });
47
+
48
+ // Use the game logic directly
49
+ import { playGo } from "@gui-chat-plugin/go";
50
+
51
+ const state = playGo({
52
+ action: "new_game",
53
+ playerNames: { B: "user", W: "computer" },
54
+ });
55
+ ```
56
+
57
+ ## API
58
+
59
+ ### GoArgs
60
+
61
+ ```typescript
62
+ interface GoArgs {
63
+ action: "new_game" | "move" | "pass";
64
+ col?: number; // 0-8 for move action
65
+ row?: number; // 0-8 for move action
66
+ board?: Cell[][]; // Current board state
67
+ currentSide?: Side; // "B" or "W"
68
+ playerNames?: { B: GoPlayerType; W: GoPlayerType };
69
+ capturedStones?: { B: number; W: number };
70
+ consecutivePasses?: number;
71
+ firstPlayer?: GoPlayerType; // "user" or "computer"
72
+ }
73
+ ```
74
+
75
+ ### GoState
76
+
77
+ ```typescript
78
+ interface GoState {
79
+ board: GoBoard; // 9x9 grid of ".", "B", or "W"
80
+ currentSide: Side; // Whose turn is next
81
+ playerNames: { B: string; W: string };
82
+ capturedStones: { B: number; W: number };
83
+ counts: { B: number; W: number; empty: number };
84
+ isTerminal: boolean;
85
+ winner: Side | "draw" | null;
86
+ consecutivePasses: number;
87
+ lastAction: { type: "new_game" | "move" | "pass"; ... };
88
+ error?: string;
89
+ }
90
+ ```
91
+
92
+ ## Development
93
+
94
+ ```bash
95
+ # Install dependencies
96
+ yarn install
97
+
98
+ # Run demo
99
+ yarn dev
100
+
101
+ # Build
102
+ yarn build
103
+
104
+ # Lint
105
+ yarn lint
106
+ ```
107
+
108
+ ## License
109
+
110
+ MIT
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Go Plugin - Tool Definition
3
+ */
4
+ import type { ToolDefinition } from "gui-chat-protocol";
5
+ export declare const TOOL_NAME = "playGo";
6
+ export declare const TOOL_DEFINITION: ToolDefinition;
7
+ export declare const SYSTEM_PROMPT = "You can play Go (Baduk/Weiqi) with users on a 9x9 board. When a user wants to play:\n1. Start a new game with the \"new_game\" action\n2. For moves, the user specifies column (A-J, skipping I) and row (1-9)\n3. Use the \"move\" action with the current board state\n4. The game ends after two consecutive passes";
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Go Plugin - Core Entry Point
3
+ */
4
+ export type { Cell, Side, GoBoard, GoCellValue, GoPlayerType, GoArgs, GoState, Command, NewGameCommand, MoveCommand, } from "./types";
5
+ export { TOOL_NAME, TOOL_DEFINITION, SYSTEM_PROMPT, executeGo, pluginCore, playGo, } from "./plugin";
6
+ export { samples } from "./samples";
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Go Plugin - Game Logic
3
+ */
4
+ import type { Command, GoState } from "./types";
5
+ export declare function playGo(cmd: Command): GoState;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Go Plugin Core
3
+ */
4
+ import type { ToolPluginCore, ToolContext, ToolResult } from "gui-chat-protocol";
5
+ import type { GoArgs, GoState } from "./types";
6
+ export { TOOL_NAME, TOOL_DEFINITION, SYSTEM_PROMPT } from "./definition";
7
+ export { playGo } from "./logic";
8
+ export declare const executeGo: (_context: ToolContext, args: GoArgs) => Promise<ToolResult<never, GoState>>;
9
+ export declare const pluginCore: ToolPluginCore<never, GoState, GoArgs>;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Go Plugin - Samples
3
+ */
4
+ import type { ToolSample } from "gui-chat-protocol";
5
+ export declare const samples: ToolSample[];
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Go Plugin - Type Definitions
3
+ */
4
+ export type Cell = "." | "B" | "W";
5
+ export type Side = "B" | "W";
6
+ export type GoBoard = Cell[][];
7
+ export type GoCellValue = Cell;
8
+ export type GoPlayerType = "user" | "computer";
9
+ export interface GoArgs {
10
+ action: "new_game" | "move" | "pass";
11
+ col?: number;
12
+ row?: number;
13
+ board?: GoCellValue[][];
14
+ currentSide?: Side;
15
+ playerNames?: {
16
+ B: GoPlayerType;
17
+ W: GoPlayerType;
18
+ };
19
+ capturedStones?: {
20
+ B: number;
21
+ W: number;
22
+ };
23
+ consecutivePasses?: number;
24
+ firstPlayer?: GoPlayerType;
25
+ }
26
+ export type NewGameCommand = {
27
+ action: "new_game";
28
+ playerNames: {
29
+ B: string;
30
+ W: string;
31
+ };
32
+ };
33
+ export type MoveCommand = {
34
+ action: "move";
35
+ row: number;
36
+ col: number;
37
+ board: GoBoard;
38
+ currentSide: Side;
39
+ playerNames: {
40
+ B: string;
41
+ W: string;
42
+ };
43
+ capturedStones: {
44
+ B: number;
45
+ W: number;
46
+ };
47
+ } | {
48
+ action: "pass";
49
+ board: GoBoard;
50
+ currentSide: Side;
51
+ playerNames: {
52
+ B: string;
53
+ W: string;
54
+ };
55
+ capturedStones: {
56
+ B: number;
57
+ W: number;
58
+ };
59
+ consecutivePasses: number;
60
+ };
61
+ export type Command = NewGameCommand | MoveCommand;
62
+ export interface GoState {
63
+ board: GoBoard;
64
+ currentSide: Side;
65
+ playerNames: {
66
+ B: string;
67
+ W: string;
68
+ };
69
+ capturedStones: {
70
+ B: number;
71
+ W: number;
72
+ };
73
+ counts: {
74
+ B: number;
75
+ W: number;
76
+ empty: number;
77
+ };
78
+ isTerminal: boolean;
79
+ winner: Side | "draw" | null;
80
+ consecutivePasses: number;
81
+ lastAction: {
82
+ type: "new_game";
83
+ } | {
84
+ type: "move";
85
+ row: number;
86
+ col: number;
87
+ captured: number;
88
+ } | {
89
+ type: "pass";
90
+ };
91
+ error?: string;
92
+ }
package/dist/core.cjs ADDED
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./index.cjs");exports.SYSTEM_PROMPT=e.SYSTEM_PROMPT;exports.TOOL_DEFINITION=e.TOOL_DEFINITION;exports.TOOL_NAME=e.TOOL_NAME;exports.executeGo=e.executeGo;exports.playGo=e.playGo;exports.pluginCore=e.pluginCore;exports.samples=e.samples;
package/dist/core.js ADDED
@@ -0,0 +1,10 @@
1
+ import { SYSTEM_PROMPT as o, TOOL_DEFINITION as T, TOOL_NAME as p, executeGo as l, playGo as r, pluginCore as E, samples as I } from "./index.js";
2
+ export {
3
+ o as SYSTEM_PROMPT,
4
+ T as TOOL_DEFINITION,
5
+ p as TOOL_NAME,
6
+ l as executeGo,
7
+ r as playGo,
8
+ E as pluginCore,
9
+ I as samples
10
+ };
package/dist/index.cjs ADDED
@@ -0,0 +1,6 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const P="playGo",A={type:"function",name:P,description:"Play the game of Go (Baduk/Weiqi) with the user on a 9x9 board. You can start a new game, make moves, or pass turns. The game ends after two consecutive passes.",parameters:{type:"object",properties:{action:{type:"string",enum:["new_game","move","pass"],description:"The action to perform: start a new game, make a move, or pass the turn"},col:{type:"number",description:"Column position for the move (0-8, required for 'move' action). The user will tell you the column by specifying A to J (skipping I)",minimum:0,maximum:8},row:{type:"number",description:"Row position for the move (0-8, required for 'move' action). The user will tell you the row by specifying 1 to 9",minimum:0,maximum:8},board:{type:"array",description:"Current 9x9 board state (required for 'move' and 'pass' actions)",items:{type:"array",items:{type:"string",enum:[".","B","W"]}}},currentSide:{type:"string",enum:["B","W"],description:"Current player's side (required for 'move' and 'pass' actions)"},playerNames:{type:"object",description:"Player assignments (required for 'move' and 'pass' actions)",properties:{B:{type:"string",enum:["user","computer"]},W:{type:"string",enum:["user","computer"]}},required:["B","W"]},capturedStones:{type:"object",description:"Count of captured stones for each player (required for 'move' and 'pass' actions)",properties:{B:{type:"number",description:"Number of stones captured by Black"},W:{type:"number",description:"Number of stones captured by White"}},required:["B","W"]},consecutivePasses:{type:"number",description:"Number of consecutive passes (required for 'pass' action, 0-2)",minimum:0,maximum:2},firstPlayer:{type:"string",enum:["user","computer"],description:"Optional: Which player should play as Black (goes first) for 'new_game' action. If not specified, will be chosen randomly."}},required:["action"],additionalProperties:!1}},N=`You can play Go (Baduk/Weiqi) with users on a 9x9 board. When a user wants to play:
2
+ 1. Start a new game with the "new_game" action
3
+ 2. For moves, the user specifies column (A-J, skipping I) and row (1-9)
4
+ 3. Use the "move" action with the current board state
5
+ 4. The game ends after two consecutive passes`,l=9,v=[[-1,0],[1,0],[0,-1],[0,1]];function x(){const n=[];for(let e=0;e<l;e++)n[e]=new Array(l).fill(".");return n}function b(n){return n.map(e=>[...e])}function g(n,e){return n>=0&&n<l&&e>=0&&e<l}function w(n){return n==="B"?"W":"B"}function W(n,e,r,t){const o=n[e][r];if(o===".")return[];const s=[],a=[{row:e,col:r}];for(;a.length>0;){const i=a.pop(),c=i.row,u=i.col;if(!(!g(c,u)||t[c][u]||n[c][u]!==o)){t[c][u]=!0,s.push({row:c,col:u});for(const[m,p]of v)a.push({row:c+m,col:u+p})}}return s}function k(n,e){for(const{row:r,col:t}of e)for(const[o,s]of v){const a=r+o,i=t+s;if(g(a,i)&&n[a][i]===".")return!0}return!1}function C(n,e){const r=b(n),t=Array(l).fill(null).map(()=>Array(l).fill(!1));let o=0;for(let s=0;s<l;s++)for(let a=0;a<l;a++)if(r[s][a]===e&&!t[s][a]){const i=W(r,s,a,t);if(!k(r,i))for(const{row:c,col:u}of i)r[c][u]=".",o++}return{board:r,capturedCount:o}}function M(n,e,r,t){if(n[e][r]!==".")return!1;const o=b(n);o[e][r]=t;const s=w(t),{board:a}=C(o,s),i=Array(l).fill(null).map(()=>Array(l).fill(!1)),c=W(a,e,r,i);return k(a,c)}function $(n,e,r,t){const o=b(n);o[e][r]=t;const s=w(t),{board:a,capturedCount:i}=C(o,s);return{newBoard:a,capturedCount:i}}function y(n){let e=0,r=0,t=0;for(let o=0;o<l;o++)for(let s=0;s<l;s++){const a=n[o][s];a==="B"?e++:a==="W"?r++:t++}return{B:e,W:r,empty:t}}function D(n){const e=Array(l).fill(null).map(()=>Array(l).fill(!1));let r=0,t=0;for(let o=0;o<l;o++)for(let s=0;s<l;s++)if(n[o][s]==="."&&!e[o][s]){const a=[],i=[{row:o,col:s}],c=new Set;for(;i.length>0;){const u=i.pop(),m=u.row,p=u.col;if(!(!g(m,p)||e[m][p]))if(n[m][p]==="."){e[m][p]=!0,a.push({row:m,col:p});for(const[d,f]of v)i.push({row:m+d,col:p+f})}else c.add(n[m][p])}if(c.size===1){const u=Array.from(c)[0];u==="B"?r+=a.length:u==="W"&&(t+=a.length)}}return{B:r,W:t}}function R(n,e){const r=y(n),t=D(n),o=r.B+t.B+e.W,s=r.W+t.W+e.B;return o>s?"B":s>o?"W":"draw"}function I(n){if(n.action==="new_game"){const{playerNames:d}=n,f=x(),h=y(f);return{board:f,currentSide:"B",playerNames:d,capturedStones:{B:0,W:0},counts:h,isTerminal:!1,winner:null,consecutivePasses:0,lastAction:{type:"new_game"}}}if(n.action==="pass"){const{board:d,currentSide:f,playerNames:h,capturedStones:S,consecutivePasses:G}=n,O=w(f),q=y(d),B=G+1,T=B>=2,E=T?R(d,S):null;return{board:d,currentSide:O,playerNames:h,capturedStones:S,counts:q,isTerminal:T,winner:E,consecutivePasses:B,lastAction:{type:"pass"}}}const{row:e,col:r,board:t,currentSide:o,playerNames:s,capturedStones:a}=n;if(!M(t,e,r,o)){const d=y(t);return{board:t,currentSide:o,playerNames:s,capturedStones:a,counts:d,isTerminal:!1,winner:null,consecutivePasses:0,lastAction:{type:"pass"},error:`Invalid move: (${e}, ${r}) is not a legal move for ${o}. The position must be empty and the move must not be suicide.`}}const{newBoard:i,capturedCount:c}=$(t,e,r,o),u=w(o),m=y(i),p={...a};return c>0&&(p[o]+=c),{board:i,currentSide:u,playerNames:s,capturedStones:p,counts:m,isTerminal:!1,winner:null,consecutivePasses:0,lastAction:{type:"move",row:e,col:r,captured:c}}}const _=async(n,e)=>{try{let r;if(e.action==="new_game"){let i;e.firstPlayer?i=e.firstPlayer:i=Math.random()<.5?"computer":"user",r={action:"new_game",playerNames:{B:i,W:i==="user"?"computer":"user"}}}else if(e.action==="move"){if(typeof e.row!="number"||typeof e.col!="number"||!e.board||!e.currentSide||!e.playerNames||!e.capturedStones)throw new Error("Move action requires row, col, board, currentSide, playerNames, and capturedStones parameters");r={action:"move",row:e.row,col:e.col,board:e.board,currentSide:e.currentSide,playerNames:e.playerNames,capturedStones:e.capturedStones}}else if(e.action==="pass"){if(!e.board||!e.currentSide||!e.playerNames||!e.capturedStones||typeof e.consecutivePasses!="number")throw new Error("Pass action requires board, currentSide, playerNames, capturedStones, and consecutivePasses parameters");r={action:"pass",board:e.board,currentSide:e.currentSide,playerNames:e.playerNames,capturedStones:e.capturedStones,consecutivePasses:e.consecutivePasses}}else throw new Error(`Unknown action: ${e.action}`);const t=I(r);if(t.error){const c=t.playerNames[t.currentSide]==="computer"?"Invalid move attempted. You must make a valid move. Choose an empty intersection where placing a stone would not result in immediate capture (suicide rule).":"Invalid move attempted. Tell the user they must make a valid move. The position must be empty and the move must not be suicide. The user will tell you the move by specifying column (A to J, skipping I) and row (1 to 9).";return{message:t.error,jsonData:t,instructions:c,updating:!0}}let o="";if(t.lastAction.type==="new_game")o="Started a new Go game on a 9x9 board! Black (●) goes first.";else if(t.lastAction.type==="move"){const i=t.lastAction.captured>0?` and captured ${t.lastAction.captured} stone${t.lastAction.captured>1?"s":""}`:"";o=`Played at (${t.lastAction.row}, ${t.lastAction.col})${i}.`}else t.lastAction.type==="pass"&&(o="Passed the turn.",t.consecutivePasses===1&&(o+=" One more pass will end the game."));t.isTerminal&&(t.winner==="draw"?o+=" Game over - it's a draw!":t.winner&&(o+=` Game over - ${t.winner==="B"?"Black":"White"} wins!`));const s=t.playerNames[t.currentSide]==="computer",a=t.isTerminal?"The game is over. Announce the game result with final scores.":s?"The game state has been updated. It is your turn (you = AI assistant, computer). Make your move or pass.":"The game state has been updated. Tell the user to make a move or pass. Do not describe the state of the game. The user is able to see it. The user will tell you the move by specifying column (A to J, skipping I) and row (1 to 9).";return{message:o,jsonData:t,instructions:a,instructionsRequired:t.isTerminal||s,updating:e.action!=="new_game"}}catch(r){return console.error(`ERR: exception
6
+ Go game error`,r),{message:`Go game error: ${r instanceof Error?r.message:"Unknown error"}`,instructions:"Acknowledge that there was an error with the Go game and suggest trying again."}}},j={toolDefinition:A,execute:_,generatingMessage:"Processing Go move...",isEnabled:()=>!0,systemPrompt:N},L=[{name:"New Game (User First)",args:{action:"new_game",firstPlayer:"user"}},{name:"New Game (Computer First)",args:{action:"new_game",firstPlayer:"computer"}}];exports.SYSTEM_PROMPT=N;exports.TOOL_DEFINITION=A;exports.TOOL_NAME=P;exports.executeGo=_;exports.playGo=I;exports.pluginCore=j;exports.samples=L;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Go Plugin - Main Entry Point
3
+ */
4
+ export type { Cell, Side, GoBoard, GoCellValue, GoPlayerType, GoArgs, GoState, Command, NewGameCommand, MoveCommand, } from "./core/types";
5
+ export { TOOL_NAME, TOOL_DEFINITION, SYSTEM_PROMPT, executeGo, pluginCore, playGo, } from "./core/plugin";
6
+ export { samples } from "./core/samples";
package/dist/index.js ADDED
@@ -0,0 +1,374 @@
1
+ const G = "playGo", _ = {
2
+ type: "function",
3
+ name: G,
4
+ description: "Play the game of Go (Baduk/Weiqi) with the user on a 9x9 board. You can start a new game, make moves, or pass turns. The game ends after two consecutive passes.",
5
+ parameters: {
6
+ type: "object",
7
+ properties: {
8
+ action: {
9
+ type: "string",
10
+ enum: ["new_game", "move", "pass"],
11
+ description: "The action to perform: start a new game, make a move, or pass the turn"
12
+ },
13
+ col: {
14
+ type: "number",
15
+ description: "Column position for the move (0-8, required for 'move' action). The user will tell you the column by specifying A to J (skipping I)",
16
+ minimum: 0,
17
+ maximum: 8
18
+ },
19
+ row: {
20
+ type: "number",
21
+ description: "Row position for the move (0-8, required for 'move' action). The user will tell you the row by specifying 1 to 9",
22
+ minimum: 0,
23
+ maximum: 8
24
+ },
25
+ board: {
26
+ type: "array",
27
+ description: "Current 9x9 board state (required for 'move' and 'pass' actions)",
28
+ items: {
29
+ type: "array",
30
+ items: {
31
+ type: "string",
32
+ enum: [".", "B", "W"]
33
+ }
34
+ }
35
+ },
36
+ currentSide: {
37
+ type: "string",
38
+ enum: ["B", "W"],
39
+ description: "Current player's side (required for 'move' and 'pass' actions)"
40
+ },
41
+ playerNames: {
42
+ type: "object",
43
+ description: "Player assignments (required for 'move' and 'pass' actions)",
44
+ properties: {
45
+ B: {
46
+ type: "string",
47
+ enum: ["user", "computer"]
48
+ },
49
+ W: {
50
+ type: "string",
51
+ enum: ["user", "computer"]
52
+ }
53
+ },
54
+ required: ["B", "W"]
55
+ },
56
+ capturedStones: {
57
+ type: "object",
58
+ description: "Count of captured stones for each player (required for 'move' and 'pass' actions)",
59
+ properties: {
60
+ B: {
61
+ type: "number",
62
+ description: "Number of stones captured by Black"
63
+ },
64
+ W: {
65
+ type: "number",
66
+ description: "Number of stones captured by White"
67
+ }
68
+ },
69
+ required: ["B", "W"]
70
+ },
71
+ consecutivePasses: {
72
+ type: "number",
73
+ description: "Number of consecutive passes (required for 'pass' action, 0-2)",
74
+ minimum: 0,
75
+ maximum: 2
76
+ },
77
+ firstPlayer: {
78
+ type: "string",
79
+ enum: ["user", "computer"],
80
+ description: "Optional: Which player should play as Black (goes first) for 'new_game' action. If not specified, will be chosen randomly."
81
+ }
82
+ },
83
+ required: ["action"],
84
+ additionalProperties: !1
85
+ }
86
+ }, q = `You can play Go (Baduk/Weiqi) with users on a 9x9 board. When a user wants to play:
87
+ 1. Start a new game with the "new_game" action
88
+ 2. For moves, the user specifies column (A-J, skipping I) and row (1-9)
89
+ 3. Use the "move" action with the current board state
90
+ 4. The game ends after two consecutive passes`, l = 9, v = [
91
+ [-1, 0],
92
+ // up
93
+ [1, 0],
94
+ // down
95
+ [0, -1],
96
+ // left
97
+ [0, 1]
98
+ // right
99
+ ];
100
+ function x() {
101
+ const n = [];
102
+ for (let e = 0; e < l; e++)
103
+ n[e] = new Array(l).fill(".");
104
+ return n;
105
+ }
106
+ function b(n) {
107
+ return n.map((e) => [...e]);
108
+ }
109
+ function g(n, e) {
110
+ return n >= 0 && n < l && e >= 0 && e < l;
111
+ }
112
+ function w(n) {
113
+ return n === "B" ? "W" : "B";
114
+ }
115
+ function A(n, e, r, t) {
116
+ const o = n[e][r];
117
+ if (o === ".") return [];
118
+ const s = [], a = [{ row: e, col: r }];
119
+ for (; a.length > 0; ) {
120
+ const i = a.pop(), c = i.row, u = i.col;
121
+ if (!(!g(c, u) || t[c][u] || n[c][u] !== o)) {
122
+ t[c][u] = !0, s.push({ row: c, col: u });
123
+ for (const [m, p] of v)
124
+ a.push({ row: c + m, col: u + p });
125
+ }
126
+ }
127
+ return s;
128
+ }
129
+ function P(n, e) {
130
+ for (const { row: r, col: t } of e)
131
+ for (const [o, s] of v) {
132
+ const a = r + o, i = t + s;
133
+ if (g(a, i) && n[a][i] === ".")
134
+ return !0;
135
+ }
136
+ return !1;
137
+ }
138
+ function N(n, e) {
139
+ const r = b(n), t = Array(l).fill(null).map(() => Array(l).fill(!1));
140
+ let o = 0;
141
+ for (let s = 0; s < l; s++)
142
+ for (let a = 0; a < l; a++)
143
+ if (r[s][a] === e && !t[s][a]) {
144
+ const i = A(r, s, a, t);
145
+ if (!P(r, i))
146
+ for (const { row: c, col: u } of i)
147
+ r[c][u] = ".", o++;
148
+ }
149
+ return { board: r, capturedCount: o };
150
+ }
151
+ function E(n, e, r, t) {
152
+ if (n[e][r] !== ".")
153
+ return !1;
154
+ const o = b(n);
155
+ o[e][r] = t;
156
+ const s = w(t), { board: a } = N(
157
+ o,
158
+ s
159
+ ), i = Array(l).fill(null).map(() => Array(l).fill(!1)), c = A(a, e, r, i);
160
+ return P(a, c);
161
+ }
162
+ function O(n, e, r, t) {
163
+ const o = b(n);
164
+ o[e][r] = t;
165
+ const s = w(t), { board: a, capturedCount: i } = N(
166
+ o,
167
+ s
168
+ );
169
+ return { newBoard: a, capturedCount: i };
170
+ }
171
+ function y(n) {
172
+ let e = 0, r = 0, t = 0;
173
+ for (let o = 0; o < l; o++)
174
+ for (let s = 0; s < l; s++) {
175
+ const a = n[o][s];
176
+ a === "B" ? e++ : a === "W" ? r++ : t++;
177
+ }
178
+ return { B: e, W: r, empty: t };
179
+ }
180
+ function $(n) {
181
+ const e = Array(l).fill(null).map(() => Array(l).fill(!1));
182
+ let r = 0, t = 0;
183
+ for (let o = 0; o < l; o++)
184
+ for (let s = 0; s < l; s++)
185
+ if (n[o][s] === "." && !e[o][s]) {
186
+ const a = [], i = [{ row: o, col: s }], c = /* @__PURE__ */ new Set();
187
+ for (; i.length > 0; ) {
188
+ const u = i.pop(), m = u.row, p = u.col;
189
+ if (!(!g(m, p) || e[m][p]))
190
+ if (n[m][p] === ".") {
191
+ e[m][p] = !0, a.push({ row: m, col: p });
192
+ for (const [d, f] of v)
193
+ i.push({ row: m + d, col: p + f });
194
+ } else
195
+ c.add(n[m][p]);
196
+ }
197
+ if (c.size === 1) {
198
+ const u = Array.from(c)[0];
199
+ u === "B" ? r += a.length : u === "W" && (t += a.length);
200
+ }
201
+ }
202
+ return { B: r, W: t };
203
+ }
204
+ function M(n, e) {
205
+ const r = y(n), t = $(n), o = r.B + t.B + e.W, s = r.W + t.W + e.B;
206
+ return o > s ? "B" : s > o ? "W" : "draw";
207
+ }
208
+ function D(n) {
209
+ if (n.action === "new_game") {
210
+ const { playerNames: d } = n, f = x(), h = y(f);
211
+ return {
212
+ board: f,
213
+ currentSide: "B",
214
+ playerNames: d,
215
+ capturedStones: { B: 0, W: 0 },
216
+ counts: h,
217
+ isTerminal: !1,
218
+ winner: null,
219
+ consecutivePasses: 0,
220
+ lastAction: { type: "new_game" }
221
+ };
222
+ }
223
+ if (n.action === "pass") {
224
+ const {
225
+ board: d,
226
+ currentSide: f,
227
+ playerNames: h,
228
+ capturedStones: S,
229
+ consecutivePasses: W
230
+ } = n, k = w(f), C = y(d), B = W + 1, T = B >= 2, I = T ? M(d, S) : null;
231
+ return {
232
+ board: d,
233
+ currentSide: k,
234
+ playerNames: h,
235
+ capturedStones: S,
236
+ counts: C,
237
+ isTerminal: T,
238
+ winner: I,
239
+ consecutivePasses: B,
240
+ lastAction: { type: "pass" }
241
+ };
242
+ }
243
+ const { row: e, col: r, board: t, currentSide: o, playerNames: s, capturedStones: a } = n;
244
+ if (!E(t, e, r, o)) {
245
+ const d = y(t);
246
+ return {
247
+ board: t,
248
+ currentSide: o,
249
+ playerNames: s,
250
+ capturedStones: a,
251
+ counts: d,
252
+ isTerminal: !1,
253
+ winner: null,
254
+ consecutivePasses: 0,
255
+ lastAction: { type: "pass" },
256
+ error: `Invalid move: (${e}, ${r}) is not a legal move for ${o}. The position must be empty and the move must not be suicide.`
257
+ };
258
+ }
259
+ const { newBoard: i, capturedCount: c } = O(t, e, r, o), u = w(o), m = y(i), p = { ...a };
260
+ return c > 0 && (p[o] += c), {
261
+ board: i,
262
+ currentSide: u,
263
+ playerNames: s,
264
+ capturedStones: p,
265
+ counts: m,
266
+ isTerminal: !1,
267
+ winner: null,
268
+ consecutivePasses: 0,
269
+ // Reset on actual move
270
+ lastAction: { type: "move", row: e, col: r, captured: c }
271
+ };
272
+ }
273
+ const R = async (n, e) => {
274
+ try {
275
+ let r;
276
+ if (e.action === "new_game") {
277
+ let i;
278
+ e.firstPlayer ? i = e.firstPlayer : i = Math.random() < 0.5 ? "computer" : "user", r = {
279
+ action: "new_game",
280
+ playerNames: { B: i, W: i === "user" ? "computer" : "user" }
281
+ };
282
+ } else if (e.action === "move") {
283
+ if (typeof e.row != "number" || typeof e.col != "number" || !e.board || !e.currentSide || !e.playerNames || !e.capturedStones)
284
+ throw new Error(
285
+ "Move action requires row, col, board, currentSide, playerNames, and capturedStones parameters"
286
+ );
287
+ r = {
288
+ action: "move",
289
+ row: e.row,
290
+ col: e.col,
291
+ board: e.board,
292
+ currentSide: e.currentSide,
293
+ playerNames: e.playerNames,
294
+ capturedStones: e.capturedStones
295
+ };
296
+ } else if (e.action === "pass") {
297
+ if (!e.board || !e.currentSide || !e.playerNames || !e.capturedStones || typeof e.consecutivePasses != "number")
298
+ throw new Error(
299
+ "Pass action requires board, currentSide, playerNames, capturedStones, and consecutivePasses parameters"
300
+ );
301
+ r = {
302
+ action: "pass",
303
+ board: e.board,
304
+ currentSide: e.currentSide,
305
+ playerNames: e.playerNames,
306
+ capturedStones: e.capturedStones,
307
+ consecutivePasses: e.consecutivePasses
308
+ };
309
+ } else
310
+ throw new Error(`Unknown action: ${e.action}`);
311
+ const t = D(r);
312
+ if (t.error) {
313
+ const c = t.playerNames[t.currentSide] === "computer" ? "Invalid move attempted. You must make a valid move. Choose an empty intersection where placing a stone would not result in immediate capture (suicide rule)." : "Invalid move attempted. Tell the user they must make a valid move. The position must be empty and the move must not be suicide. The user will tell you the move by specifying column (A to J, skipping I) and row (1 to 9).";
314
+ return {
315
+ message: t.error,
316
+ jsonData: t,
317
+ instructions: c,
318
+ updating: !0
319
+ };
320
+ }
321
+ let o = "";
322
+ if (t.lastAction.type === "new_game")
323
+ o = "Started a new Go game on a 9x9 board! Black (●) goes first.";
324
+ else if (t.lastAction.type === "move") {
325
+ const i = t.lastAction.captured > 0 ? ` and captured ${t.lastAction.captured} stone${t.lastAction.captured > 1 ? "s" : ""}` : "";
326
+ o = `Played at (${t.lastAction.row}, ${t.lastAction.col})${i}.`;
327
+ } else t.lastAction.type === "pass" && (o = "Passed the turn.", t.consecutivePasses === 1 && (o += " One more pass will end the game."));
328
+ t.isTerminal && (t.winner === "draw" ? o += " Game over - it's a draw!" : t.winner && (o += ` Game over - ${t.winner === "B" ? "Black" : "White"} wins!`));
329
+ const s = t.playerNames[t.currentSide] === "computer", a = t.isTerminal ? "The game is over. Announce the game result with final scores." : s ? "The game state has been updated. It is your turn (you = AI assistant, computer). Make your move or pass." : "The game state has been updated. Tell the user to make a move or pass. Do not describe the state of the game. The user is able to see it. The user will tell you the move by specifying column (A to J, skipping I) and row (1 to 9).";
330
+ return {
331
+ message: o,
332
+ jsonData: t,
333
+ instructions: a,
334
+ instructionsRequired: t.isTerminal || s,
335
+ updating: e.action !== "new_game"
336
+ };
337
+ } catch (r) {
338
+ return console.error(`ERR: exception
339
+ Go game error`, r), {
340
+ message: `Go game error: ${r instanceof Error ? r.message : "Unknown error"}`,
341
+ instructions: "Acknowledge that there was an error with the Go game and suggest trying again."
342
+ };
343
+ }
344
+ }, j = {
345
+ toolDefinition: _,
346
+ execute: R,
347
+ generatingMessage: "Processing Go move...",
348
+ isEnabled: () => !0,
349
+ systemPrompt: q
350
+ }, F = [
351
+ {
352
+ name: "New Game (User First)",
353
+ args: {
354
+ action: "new_game",
355
+ firstPlayer: "user"
356
+ }
357
+ },
358
+ {
359
+ name: "New Game (Computer First)",
360
+ args: {
361
+ action: "new_game",
362
+ firstPlayer: "computer"
363
+ }
364
+ }
365
+ ];
366
+ export {
367
+ q as SYSTEM_PROMPT,
368
+ _ as TOOL_DEFINITION,
369
+ G as TOOL_NAME,
370
+ R as executeGo,
371
+ D as playGo,
372
+ j as pluginCore,
373
+ F as samples
374
+ };
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-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--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-amber-50:oklch(98.7% .022 95.277);--color-amber-100:oklch(96.2% .059 95.617);--color-amber-900:oklch(41.4% .112 45.904);--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-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--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-black:#000;--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-bold:700;--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{.pointer-events-none{pointer-events:none}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:calc(var(--spacing)*0)}.top-1\/2{top:50%}.top-4{top:calc(var(--spacing)*4)}.right-4{right:calc(var(--spacing)*4)}.-bottom-6{bottom:calc(var(--spacing)*-6)}.bottom-4{bottom:calc(var(--spacing)*4)}.-left-6{left:calc(var(--spacing)*-6)}.left-1\/2{left:50%}.left-4{left:calc(var(--spacing)*4)}.mx-auto{margin-inline:auto}.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)}.contents{display:contents}.flex{display:flex}.grid{display:grid}.inline-block{display:inline-block}.h-0\.5{height:calc(var(--spacing)*.5)}.h-1{height:calc(var(--spacing)*1)}.h-2{height:calc(var(--spacing)*2)}.h-2\.5{height:calc(var(--spacing)*2.5)}.h-3{height:calc(var(--spacing)*3)}.h-10{height:calc(var(--spacing)*10)}.h-12{height:calc(var(--spacing)*12)}.h-\[600px\]{height:600px}.h-full{height:100%}.h-px{height:1px}.w-0\.5{width:calc(var(--spacing)*.5)}.w-1{width:calc(var(--spacing)*1)}.w-2{width:calc(var(--spacing)*2)}.w-2\.5{width:calc(var(--spacing)*2.5)}.w-3{width:calc(var(--spacing)*3)}.w-10{width:calc(var(--spacing)*10)}.w-12{width:calc(var(--spacing)*12)}.w-full{width:100%}.w-px{width:1px}.max-w-3xl{max-width:var(--container-3xl)}.max-w-\[200px\]{max-width:200px}.transform{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.grid-cols-9{grid-template-columns:repeat(9,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-around{justify-content:space-around}.justify-center{justify-content:center}.gap-0{gap:calc(var(--spacing)*0)}.gap-2{gap:calc(var(--spacing)*2)}: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)))}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-amber-900{border-color:var(--color-amber-900)}.border-gray-300{border-color:var(--color-gray-300)}.border-gray-600{border-color:var(--color-gray-600)}.border-gray-700{border-color:var(--color-gray-700)}.border-indigo-200{border-color:var(--color-indigo-200)}.bg-amber-50{background-color:var(--color-amber-50)}.bg-amber-100{background-color:var(--color-amber-100)}.bg-black{background-color:var(--color-black)}.bg-gray-100{background-color:var(--color-gray-100)}.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)}.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)}.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-white{color:var(--color-white)}.opacity-50{opacity:.5}.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)}@media(hover:hover){.hover\:bg-indigo-200:hover{background-color:var(--color-indigo-200)}}}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@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 { GoState } from "../core/types";
3
+ type __VLS_Props = {
4
+ result: ToolResult<never, GoState>;
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 } from "gui-chat-protocol/vue";
2
+ import type { GoState } from "../core/types";
3
+ type __VLS_Props = {
4
+ selectedResult: ToolResult<never, GoState> | null;
5
+ sendTextMessage: (text?: string) => 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
+ * Go Plugin - Vue Implementation
3
+ */
4
+ import "../style.css";
5
+ import type { ToolPlugin } from "gui-chat-protocol/vue";
6
+ import type { GoArgs, GoState } from "../core/types";
7
+ import View from "./View.vue";
8
+ import Preview from "./Preview.vue";
9
+ export declare const plugin: ToolPlugin<never, GoState, GoArgs>;
10
+ export type { Cell, Side, GoBoard, GoCellValue, GoPlayerType, GoArgs, GoState, } from "../core/types";
11
+ export { TOOL_NAME, TOOL_DEFINITION, SYSTEM_PROMPT, executeGo, pluginCore, playGo, } from "../core/plugin";
12
+ export { samples } from "../core/samples";
13
+ export { View, Preview };
14
+ declare const _default: {
15
+ plugin: ToolPlugin<never, GoState, GoArgs, 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("./index.cjs"),e=require("vue"),E={class:"w-full h-full flex flex-col items-center justify-center p-4"},N={key:0,class:"flex flex-col items-center"},x={class:"text-white text-lg font-bold mb-2 text-center"},C={class:"text-white text-sm mb-4 text-center"},w={class:"relative p-4 bg-amber-100 rounded-lg border-2 border-amber-900"},V={class:"grid gap-0",style:{gridTemplateColumns:"repeat(9, 1fr)",width:"432px",height:"432px"}},S=["onClick","onMouseenter","onMouseleave"],$={class:"absolute inset-0 pointer-events-none"},D={key:0,class:"absolute left-1/2 top-1/2 w-0.5 bg-black",style:{height:"48px",transform:"translateX(-50%)"}},j={key:1,class:"absolute left-1/2 top-1/2 h-0.5 bg-black",style:{width:"48px",transform:"translateY(-50%)"}},T={key:0,class:"absolute inset-0 flex items-center justify-center pointer-events-none"},M={key:1,class:"absolute inset-0 flex items-center justify-center pointer-events-none"},O={key:2,class:"absolute inset-0 flex items-center justify-center pointer-events-none"},P={class:"absolute -bottom-6 left-4 right-4 flex justify-around"},F={class:"absolute -left-6 top-4 bottom-4 flex flex-col justify-around"},h=e.defineComponent({__name:"View",props:{selectedResult:{},sendTextMessage:{type:Function}},setup(a){const m=a,o=e.ref(null),p=e.ref(null),r=["A","B","C","D","E","F","G","H","J"];e.watch(()=>m.selectedResult,l=>{l?.toolName==="playGo"&&l.jsonData&&(o.value=l.jsonData)},{immediate:!0});const v=e.computed(()=>{if(!o.value?.playerNames)return"";const l=o.value.playerNames[o.value.currentSide];return l.charAt(0).toUpperCase()+l.slice(1)}),k=e.computed(()=>o.value?o.value.currentSide==="B"?"Black":"White":""),c=e.computed(()=>o.value?.playerNames&&o.value.playerNames[o.value.currentSide]==="computer"),u=e.computed(()=>{if(!o.value?.board)return[];const l=[];for(let n=0;n<9;n++)for(let t=0;t<9;t++){const s=o.value.board[n][t];l.push({row:n,col:t,piece:s!=="."?s:null})}return l});function d(l,n){return[[2,2],[2,6],[4,4],[6,2],[6,6]].some(([s,f])=>s===l&&f===n)}function _(l){const n="relative w-12 h-12",t=!l.piece&&!c.value&&!o.value?.isTerminal?"cursor-pointer":"cursor-default";return`${n} ${t}`}function g(l){if(!o.value||o.value.isTerminal||c.value)return;const n=u.value[l];if(n.piece)return;const t=r[n.col],s=n.row+1;m.sendTextMessage(`I want to play at ${t}${s}, which is column=${n.col}, row=${n.row}`)}function y(l,n){!o.value||o.value.isTerminal||c.value||u.value[l].piece||(p.value=n?l:null)}return(l,n)=>(e.openBlock(),e.createElementBlock("div",E,[o.value?(e.openBlock(),e.createElementBlock("div",N,[e.createElementVNode("div",x," Current Turn: "+e.toDisplayString(v.value)+" ("+e.toDisplayString(k.value)+") ",1),e.createElementVNode("div",C," Captured - Black: "+e.toDisplayString(o.value.capturedStones.B)+", White: "+e.toDisplayString(o.value.capturedStones.W),1),e.createElementVNode("div",w,[e.createElementVNode("div",V,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(u.value,(t,s)=>(e.openBlock(),e.createElementBlock("div",{key:s,class:e.normalizeClass(_(t)),onClick:f=>g(s),onMouseenter:f=>y(s,!0),onMouseleave:f=>y(s,!1)},[e.createElementVNode("div",$,[t.row<8?(e.openBlock(),e.createElementBlock("div",D)):e.createCommentVNode("",!0),t.col<8?(e.openBlock(),e.createElementBlock("div",j)):e.createCommentVNode("",!0)]),d(t.row,t.col)?(e.openBlock(),e.createElementBlock("div",T,[...n[0]||(n[0]=[e.createElementVNode("div",{class:"w-2 h-2 bg-black rounded-full"},null,-1)])])):e.createCommentVNode("",!0),t.piece?(e.openBlock(),e.createElementBlock("div",M,[e.createElementVNode("div",{class:e.normalizeClass(["w-10 h-10 rounded-full border-2",t.piece==="B"?"bg-black border-gray-700":"bg-white border-gray-300"])},null,2)])):!c.value&&p.value===s?(e.openBlock(),e.createElementBlock("div",O,[e.createElementVNode("div",{class:e.normalizeClass(["w-10 h-10 rounded-full opacity-50",o.value.currentSide==="B"?"bg-black":"bg-white"])},null,2)])):e.createCommentVNode("",!0)],42,S))),128))]),e.createElementVNode("div",P,[(e.openBlock(),e.createElementBlock(e.Fragment,null,e.renderList(r,t=>e.createElementVNode("div",{key:t,class:"text-xs font-bold text-white w-12 text-center"},e.toDisplayString(t),1)),64))]),e.createElementVNode("div",F,[(e.openBlock(),e.createElementBlock(e.Fragment,null,e.renderList(9,t=>e.createElementVNode("div",{key:t,class:"text-xs font-bold text-white h-12 flex items-center justify-center"},e.toDisplayString(t),1)),64))])])])):e.createCommentVNode("",!0)]))}}),L={class:"p-3 bg-amber-50 rounded"},W={key:0,class:"space-y-1"},G={class:"flex justify-center"},z={class:"inline-block relative",style:{"background-color":"#d4a574",padding:"4px"}},A={class:"grid grid-cols-9",style:{gap:"0px"}},Y={key:0,class:"absolute left-1/2 top-1/2 w-px bg-black",style:{height:"12px",transform:"translateX(-50%)"}},R={key:1,class:"absolute left-1/2 top-1/2 h-px bg-black",style:{width:"12px",transform:"translateY(-50%)"}},q={key:2,class:"absolute w-1 h-1 bg-black rounded-full",style:{"z-index":"1"}},H={key:3,class:"w-2.5 h-2.5 bg-black rounded-full relative",style:{"z-index":"2"}},I={key:4,class:"w-2.5 h-2.5 bg-white rounded-full border border-gray-300 relative",style:{"z-index":"2"}},U={class:"text-xs text-center space-y-1"},X={key:0,class:"text-gray-600"},J={key:1,class:"font-medium"},K={class:"text-gray-500 text-xs"},b=e.defineComponent({__name:"Preview",props:{result:{}},setup(a){function m(r,v){return[[2,2],[2,6],[4,4],[6,2],[6,6]].some(([c,u])=>c===r&&u===v)}function o(r){return r.isTerminal?r.winner==="draw"?"Draw!":r.winner==="B"?"⚫ Black Wins!":r.winner==="W"?"⚪ White Wins!":"Game Over":""}function p(r){return r.charAt(0).toUpperCase()+r.slice(1)}return(r,v)=>(e.openBlock(),e.createElementBlock("div",L,[a.result.jsonData?(e.openBlock(),e.createElementBlock("div",W,[e.createElementVNode("div",G,[e.createElementVNode("div",z,[e.createElementVNode("div",A,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(a.result.jsonData.board,(k,c)=>(e.openBlock(),e.createElementBlock(e.Fragment,{key:c},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(k,(u,d)=>(e.openBlock(),e.createElementBlock("div",{key:`${c}-${d}`,class:"w-3 h-3 flex items-center justify-center relative"},[Number(c)<8?(e.openBlock(),e.createElementBlock("div",Y)):e.createCommentVNode("",!0),Number(d)<8?(e.openBlock(),e.createElementBlock("div",R)):e.createCommentVNode("",!0),m(Number(c),Number(d))?(e.openBlock(),e.createElementBlock("div",q)):e.createCommentVNode("",!0),u==="B"?(e.openBlock(),e.createElementBlock("div",H)):u==="W"?(e.openBlock(),e.createElementBlock("div",I)):e.createCommentVNode("",!0)]))),128))],64))),128))])])]),e.createElementVNode("div",U,[a.result.jsonData.isTerminal?(e.openBlock(),e.createElementBlock("div",J,e.toDisplayString(o(a.result.jsonData)),1)):(e.openBlock(),e.createElementBlock("div",X,e.toDisplayString(a.result.jsonData.currentSide==="B"?"⚫":"⚪")+" "+e.toDisplayString(p(a.result.jsonData.playerNames[a.result.jsonData.currentSide]))+" to play ",1)),e.createElementVNode("div",K," Captured: ⚫"+e.toDisplayString(a.result.jsonData.capturedStones.B)+" ⚪"+e.toDisplayString(a.result.jsonData.capturedStones.W),1)])])):e.createCommentVNode("",!0)]))}}),B={...i.pluginCore,viewComponent:h,previewComponent:b,samples:i.samples},Q={plugin:B};exports.SYSTEM_PROMPT=i.SYSTEM_PROMPT;exports.TOOL_DEFINITION=i.TOOL_DEFINITION;exports.TOOL_NAME=i.TOOL_NAME;exports.executeGo=i.executeGo;exports.playGo=i.playGo;exports.pluginCore=i.pluginCore;exports.samples=i.samples;exports.Preview=b;exports.View=h;exports.default=Q;exports.plugin=B;
package/dist/vue.js ADDED
@@ -0,0 +1,242 @@
1
+ import { samples as D, pluginCore as T } from "./index.js";
2
+ import { SYSTEM_PROMPT as me, TOOL_DEFINITION as pe, TOOL_NAME as be, executeGo as ye, playGo as _e } from "./index.js";
3
+ import { defineComponent as j, ref as C, watch as S, computed as k, createElementBlock as t, openBlock as s, createCommentVNode as v, createElementVNode as o, toDisplayString as d, Fragment as h, renderList as p, normalizeClass as w } from "vue";
4
+ const P = { class: "w-full h-full flex flex-col items-center justify-center p-4" }, M = {
5
+ key: 0,
6
+ class: "flex flex-col items-center"
7
+ }, W = { class: "text-white text-lg font-bold mb-2 text-center" }, O = { class: "text-white text-sm mb-4 text-center" }, E = { class: "relative p-4 bg-amber-100 rounded-lg border-2 border-amber-900" }, G = {
8
+ class: "grid gap-0",
9
+ style: {
10
+ gridTemplateColumns: "repeat(9, 1fr)",
11
+ width: "432px",
12
+ height: "432px"
13
+ }
14
+ }, z = ["onClick", "onMouseenter", "onMouseleave"], F = { class: "absolute inset-0 pointer-events-none" }, L = {
15
+ key: 0,
16
+ class: "absolute left-1/2 top-1/2 w-0.5 bg-black",
17
+ style: { height: "48px", transform: "translateX(-50%)" }
18
+ }, V = {
19
+ key: 1,
20
+ class: "absolute left-1/2 top-1/2 h-0.5 bg-black",
21
+ style: { width: "48px", transform: "translateY(-50%)" }
22
+ }, A = {
23
+ key: 0,
24
+ class: "absolute inset-0 flex items-center justify-center pointer-events-none"
25
+ }, Y = {
26
+ key: 1,
27
+ class: "absolute inset-0 flex items-center justify-center pointer-events-none"
28
+ }, H = {
29
+ key: 2,
30
+ class: "absolute inset-0 flex items-center justify-center pointer-events-none"
31
+ }, R = { class: "absolute -bottom-6 left-4 right-4 flex justify-around" }, U = { class: "absolute -left-6 top-4 bottom-4 flex flex-col justify-around" }, X = /* @__PURE__ */ j({
32
+ __name: "View",
33
+ props: {
34
+ selectedResult: {},
35
+ sendTextMessage: { type: Function }
36
+ },
37
+ setup(u) {
38
+ const b = u, r = C(null), y = C(null), a = ["A", "B", "C", "D", "E", "F", "G", "H", "J"];
39
+ S(
40
+ () => b.selectedResult,
41
+ (n) => {
42
+ n?.toolName === "playGo" && n.jsonData && (r.value = n.jsonData);
43
+ },
44
+ { immediate: !0 }
45
+ );
46
+ const _ = k(() => {
47
+ if (!r.value?.playerNames) return "";
48
+ const n = r.value.playerNames[r.value.currentSide];
49
+ return n.charAt(0).toUpperCase() + n.slice(1);
50
+ }), x = k(() => r.value ? r.value.currentSide === "B" ? "Black" : "White" : ""), c = k(() => r.value?.playerNames && r.value.playerNames[r.value.currentSide] === "computer"), f = k(() => {
51
+ if (!r.value?.board) return [];
52
+ const n = [];
53
+ for (let l = 0; l < 9; l++)
54
+ for (let e = 0; e < 9; e++) {
55
+ const i = r.value.board[l][e];
56
+ n.push({
57
+ row: l,
58
+ col: e,
59
+ piece: i !== "." ? i : null
60
+ });
61
+ }
62
+ return n;
63
+ });
64
+ function m(n, l) {
65
+ return [
66
+ [2, 2],
67
+ [2, 6],
68
+ [4, 4],
69
+ [6, 2],
70
+ [6, 6]
71
+ ].some(([i, g]) => i === n && g === l);
72
+ }
73
+ function N(n) {
74
+ const l = "relative w-12 h-12", e = !n.piece && !c.value && !r.value?.isTerminal ? "cursor-pointer" : "cursor-default";
75
+ return `${l} ${e}`;
76
+ }
77
+ function B(n) {
78
+ if (!r.value || r.value.isTerminal || c.value)
79
+ return;
80
+ const l = f.value[n];
81
+ if (l.piece) return;
82
+ const e = a[l.col], i = l.row + 1;
83
+ b.sendTextMessage(
84
+ `I want to play at ${e}${i}, which is column=${l.col}, row=${l.row}`
85
+ );
86
+ }
87
+ function $(n, l) {
88
+ !r.value || r.value.isTerminal || c.value || f.value[n].piece || (y.value = l ? n : null);
89
+ }
90
+ return (n, l) => (s(), t("div", P, [
91
+ r.value ? (s(), t("div", M, [
92
+ o("div", W, " Current Turn: " + d(_.value) + " (" + d(x.value) + ") ", 1),
93
+ o("div", O, " Captured - Black: " + d(r.value.capturedStones.B) + ", White: " + d(r.value.capturedStones.W), 1),
94
+ o("div", E, [
95
+ o("div", G, [
96
+ (s(!0), t(h, null, p(f.value, (e, i) => (s(), t("div", {
97
+ key: i,
98
+ class: w(N(e)),
99
+ onClick: (g) => B(i),
100
+ onMouseenter: (g) => $(i, !0),
101
+ onMouseleave: (g) => $(i, !1)
102
+ }, [
103
+ o("div", F, [
104
+ e.row < 8 ? (s(), t("div", L)) : v("", !0),
105
+ e.col < 8 ? (s(), t("div", V)) : v("", !0)
106
+ ]),
107
+ m(e.row, e.col) ? (s(), t("div", A, [...l[0] || (l[0] = [
108
+ o("div", { class: "w-2 h-2 bg-black rounded-full" }, null, -1)
109
+ ])])) : v("", !0),
110
+ e.piece ? (s(), t("div", Y, [
111
+ o("div", {
112
+ class: w([
113
+ "w-10 h-10 rounded-full border-2",
114
+ e.piece === "B" ? "bg-black border-gray-700" : "bg-white border-gray-300"
115
+ ])
116
+ }, null, 2)
117
+ ])) : !c.value && y.value === i ? (s(), t("div", H, [
118
+ o("div", {
119
+ class: w(["w-10 h-10 rounded-full opacity-50", r.value.currentSide === "B" ? "bg-black" : "bg-white"])
120
+ }, null, 2)
121
+ ])) : v("", !0)
122
+ ], 42, z))), 128))
123
+ ]),
124
+ o("div", R, [
125
+ (s(), t(h, null, p(a, (e) => o("div", {
126
+ key: e,
127
+ class: "text-xs font-bold text-white w-12 text-center"
128
+ }, d(e), 1)), 64))
129
+ ]),
130
+ o("div", U, [
131
+ (s(), t(h, null, p(9, (e) => o("div", {
132
+ key: e,
133
+ class: "text-xs font-bold text-white h-12 flex items-center justify-center"
134
+ }, d(e), 1)), 64))
135
+ ])
136
+ ])
137
+ ])) : v("", !0)
138
+ ]));
139
+ }
140
+ }), J = { class: "p-3 bg-amber-50 rounded" }, q = {
141
+ key: 0,
142
+ class: "space-y-1"
143
+ }, K = { class: "flex justify-center" }, Q = {
144
+ class: "inline-block relative",
145
+ style: { "background-color": "#d4a574", padding: "4px" }
146
+ }, Z = {
147
+ class: "grid grid-cols-9",
148
+ style: { gap: "0px" }
149
+ }, I = {
150
+ key: 0,
151
+ class: "absolute left-1/2 top-1/2 w-px bg-black",
152
+ style: { height: "12px", transform: "translateX(-50%)" }
153
+ }, ee = {
154
+ key: 1,
155
+ class: "absolute left-1/2 top-1/2 h-px bg-black",
156
+ style: { width: "12px", transform: "translateY(-50%)" }
157
+ }, te = {
158
+ key: 2,
159
+ class: "absolute w-1 h-1 bg-black rounded-full",
160
+ style: { "z-index": "1" }
161
+ }, se = {
162
+ key: 3,
163
+ class: "w-2.5 h-2.5 bg-black rounded-full relative",
164
+ style: { "z-index": "2" }
165
+ }, re = {
166
+ key: 4,
167
+ class: "w-2.5 h-2.5 bg-white rounded-full border border-gray-300 relative",
168
+ style: { "z-index": "2" }
169
+ }, ne = { class: "text-xs text-center space-y-1" }, le = {
170
+ key: 0,
171
+ class: "text-gray-600"
172
+ }, oe = {
173
+ key: 1,
174
+ class: "font-medium"
175
+ }, ae = { class: "text-gray-500 text-xs" }, ie = /* @__PURE__ */ j({
176
+ __name: "Preview",
177
+ props: {
178
+ result: {}
179
+ },
180
+ setup(u) {
181
+ function b(a, _) {
182
+ return [
183
+ [2, 2],
184
+ [2, 6],
185
+ [4, 4],
186
+ [6, 2],
187
+ [6, 6]
188
+ ].some(([c, f]) => c === a && f === _);
189
+ }
190
+ function r(a) {
191
+ return a.isTerminal ? a.winner === "draw" ? "Draw!" : a.winner === "B" ? "⚫ Black Wins!" : a.winner === "W" ? "⚪ White Wins!" : "Game Over" : "";
192
+ }
193
+ function y(a) {
194
+ return a.charAt(0).toUpperCase() + a.slice(1);
195
+ }
196
+ return (a, _) => (s(), t("div", J, [
197
+ u.result.jsonData ? (s(), t("div", q, [
198
+ o("div", K, [
199
+ o("div", Q, [
200
+ o("div", Z, [
201
+ (s(!0), t(h, null, p(u.result.jsonData.board, (x, c) => (s(), t(h, { key: c }, [
202
+ (s(!0), t(h, null, p(x, (f, m) => (s(), t("div", {
203
+ key: `${c}-${m}`,
204
+ class: "w-3 h-3 flex items-center justify-center relative"
205
+ }, [
206
+ Number(c) < 8 ? (s(), t("div", I)) : v("", !0),
207
+ Number(m) < 8 ? (s(), t("div", ee)) : v("", !0),
208
+ b(Number(c), Number(m)) ? (s(), t("div", te)) : v("", !0),
209
+ f === "B" ? (s(), t("div", se)) : f === "W" ? (s(), t("div", re)) : v("", !0)
210
+ ]))), 128))
211
+ ], 64))), 128))
212
+ ])
213
+ ])
214
+ ]),
215
+ o("div", ne, [
216
+ u.result.jsonData.isTerminal ? (s(), t("div", oe, d(r(u.result.jsonData)), 1)) : (s(), t("div", le, d(u.result.jsonData.currentSide === "B" ? "⚫" : "⚪") + " " + d(y(
217
+ u.result.jsonData.playerNames[u.result.jsonData.currentSide]
218
+ )) + " to play ", 1)),
219
+ o("div", ae, " Captured: ⚫" + d(u.result.jsonData.capturedStones.B) + " ⚪" + d(u.result.jsonData.capturedStones.W), 1)
220
+ ])
221
+ ])) : v("", !0)
222
+ ]));
223
+ }
224
+ }), ue = {
225
+ ...T,
226
+ viewComponent: X,
227
+ previewComponent: ie,
228
+ samples: D
229
+ }, ve = { plugin: ue };
230
+ export {
231
+ ie as Preview,
232
+ me as SYSTEM_PROMPT,
233
+ pe as TOOL_DEFINITION,
234
+ be as TOOL_NAME,
235
+ X as View,
236
+ ve as default,
237
+ ye as executeGo,
238
+ _e as playGo,
239
+ ue as plugin,
240
+ T as pluginCore,
241
+ D as samples
242
+ };
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@gui-chat-plugin/go",
3
+ "version": "0.1.0",
4
+ "description": "Go (Baduk/Weiqi) 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": ["dist"],
28
+ "scripts": {
29
+ "dev": "vite",
30
+ "build": "vite build && vue-tsc -p tsconfig.build.json --emitDeclarationOnly",
31
+ "typecheck": "vue-tsc --noEmit",
32
+ "lint": "eslint src demo"
33
+ },
34
+ "peerDependencies": {
35
+ "vue": "^3.5.0"
36
+ },
37
+ "dependencies": {
38
+ "gui-chat-protocol": "^0.0.1"
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
+ "tailwindcss": "^4.1.18",
49
+ "typescript": "~5.9.3",
50
+ "vite": "^7.3.1",
51
+ "vue": "^3.5.26",
52
+ "vue-eslint-parser": "^10.2.0",
53
+ "vue-tsc": "^3.2.2"
54
+ },
55
+ "keywords": ["guichat", "plugin", "go", "baduk", "weiqi", "game"],
56
+ "license": "MIT"
57
+ }