chesspal 0.4.1 → 0.5.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 +37 -8
- package/dist/cli/chat-hook.d.ts +4 -1
- package/dist/cli/chat-hook.js +12 -5
- package/dist/cli/cli.js +3 -3
- package/dist/cli/command-line.js +9 -9
- package/dist/commands/game/new.js +3 -5
- package/dist/commands/registry/context.d.ts +5 -0
- package/dist/commands/registry/context.js +2 -1
- package/dist/commands/setup/init.d.ts +4 -1
- package/dist/commands/setup/init.js +30 -10
- package/dist/core/review.d.ts +2 -2
- package/dist/core/review.js +7 -3
- package/dist/host-files/host-files.d.ts +10 -6
- package/dist/host-files/host-files.js +57 -9
- package/dist/host-files/index.d.ts +1 -1
- package/dist/host-files/index.js +1 -1
- package/dist/page/app/app.js +1 -1
- package/dist/page/guide/en.md +2 -2
- package/dist/page/guide/it.md +2 -2
- package/dist/page/profile/settings.js +2 -0
- package/dist/page/table/action.js +19 -7
- package/dist/page/table/window.js +7 -5
- package/dist/page/text.js +2 -2
- package/dist/server/bell/antigravity.d.ts +10 -0
- package/dist/server/bell/antigravity.js +75 -0
- package/dist/server/bell/bell.d.ts +10 -2
- package/dist/server/bell/bell.js +33 -10
- package/dist/server/bell/index.d.ts +1 -1
- package/dist/server/bell/index.js +2 -1
- package/dist/server/mcp/caller.js +26 -1
- package/dist/server/page/page.js +1 -0
- package/dist/server/page/table.d.ts +2 -0
- package/dist/server/page/table.js +1 -1
- package/dist/server/table/hosts/chats.d.ts +4 -2
- package/dist/server/table/hosts/chats.js +23 -10
- package/dist/server/table/hosts/find.d.ts +6 -0
- package/dist/server/table/hosts/find.js +19 -1
- package/dist/server/table/hosts/hooks.d.ts +5 -2
- package/dist/server/table/hosts/hooks.js +6 -3
- package/dist/server/table/hosts/hosts.d.ts +19 -10
- package/dist/server/table/hosts/hosts.js +34 -16
- package/dist/server/table/hosts/models.d.ts +19 -0
- package/dist/server/table/hosts/models.js +95 -0
- package/dist/server/table/hosts/play.d.ts +4 -1
- package/dist/server/table/hosts/play.js +17 -8
- package/dist/server/table/table.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,18 +6,32 @@ Play chess against an AI on a real board, or learn with one.
|
|
|
6
6
|
|
|
7
7
|
## Get started
|
|
8
8
|
|
|
9
|
-
Five steps, done once, in about 15 minutes. You need a paid Claude plan or a
|
|
9
|
+
Five steps, done once, in about 15 minutes. You need a paid Claude plan, a ChatGPT account or a Google account. After these steps you open the board with a double click.
|
|
10
10
|
|
|
11
|
-
**1. Install Node.js.**
|
|
11
|
+
**1. Install Node.js.** Chesspal needs **Node.js 22.13 or newer**, which comes with **npm 10.9.2 or newer**.
|
|
12
|
+
|
|
13
|
+
- **Windows and macOS:** download it from [nodejs.org](https://nodejs.org): take the version marked **LTS**, the steady one. Install it like any program, keeping every choice as it is; on Windows, leave the box "Automatically install the necessary tools" unticked.
|
|
14
|
+
- **Linux:** do not take the Node.js of your system's programs (`apt`): it is often older, and it asks for `sudo` to install Chesspal. Install it with nvm, which puts it in your home folder. Open a terminal (step 2) and run:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.41.0/install.sh | bash
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Close the terminal, open a new one, and run:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
nvm install 22
|
|
24
|
+
```
|
|
12
25
|
|
|
13
26
|
**2. Open a terminal**, the window where you type commands. Open it after installing Node.js: one opened before does not find it.
|
|
14
27
|
|
|
15
28
|
- **Windows:** press Start, type `cmd` and press Enter. This opens Command Prompt. Use it rather than PowerShell: on a new computer PowerShell refuses these commands with "running scripts is disabled on this system".
|
|
16
29
|
- **macOS:** press ⌘ and Space, type `Terminal` and press Enter.
|
|
30
|
+
- **Linux:** press Ctrl+Alt+T, or look for "Terminal" among your programs.
|
|
17
31
|
|
|
18
32
|
In the steps below, copy each command, paste it in the terminal (Ctrl+V or right-click; on macOS ⌘V) and press Enter. Wait for the terminal to finish before the next one. Lines with "WARN" are normal: go on.
|
|
19
33
|
|
|
20
|
-
**3. Install the AI and sign in.** Choose one of the
|
|
34
|
+
**3. Install the AI and sign in.** Choose one of the three. You need your own subscription: Chesspal never uses an API key, which is paid by the call.
|
|
21
35
|
|
|
22
36
|
- **Claude Code**, with a paid Claude plan (Pro or higher; the free plan does not include it):
|
|
23
37
|
|
|
@@ -35,6 +49,19 @@ In the steps below, copy each command, paste it in the terminal (Ctrl+V or right
|
|
|
35
49
|
```
|
|
36
50
|
|
|
37
51
|
Choose **Sign in with ChatGPT** and sign in in your browser.
|
|
52
|
+
- **Antigravity**, Google's, with a Google account (the free plan is enough: Chesspal plays with Gemini Flash). On Windows, in Command Prompt:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
curl -fsSL https://antigravity.google/cli/install.cmd -o install.cmd && install.cmd && del install.cmd
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
On macOS and Linux:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
curl -fsSL https://antigravity.google/cli/install.sh | bash
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Then close the terminal, open a new one, run `agy` and sign in with your Google account.
|
|
38
65
|
|
|
39
66
|
Once you are signed in, close that terminal window with its × and open a new one, as in step 2.
|
|
40
67
|
|
|
@@ -47,7 +74,7 @@ chesspal
|
|
|
47
74
|
|
|
48
75
|
The board page opens in your browser, and you can close this terminal. The first time, Chesspal offers an icon on your desktop and in your menu of programs: accept it, and from then on you open the board with a double click on it, with no terminal.
|
|
49
76
|
|
|
50
|
-
**5. Start the AI.** The first time, the board page asks who you are: fill it in and press **Start playing**. Then press **Claude Code** or **
|
|
77
|
+
**5. Start the AI.** The first time, the board page asks who you are: fill it in and press **Start playing**. Then press **Claude Code**, **Codex** or **Antigravity**: the AI opens in a terminal of its own. Keep that window open while you play. The first time it asks some questions:
|
|
51
78
|
|
|
52
79
|
- whether you trust the folder: choose **Yes** with the arrow keys and press Enter;
|
|
53
80
|
- with Codex, about Chesspal's two hooks, the small programs that tell the AI when you move on the board: choose **Trust all and continue**;
|
|
@@ -58,7 +85,9 @@ Now press **New game**: choose your colour, the clock and the AI's level, and pl
|
|
|
58
85
|
**If a command fails:**
|
|
59
86
|
|
|
60
87
|
- "npm is not recognized" or "command not found": close the terminal and open a new one; if it still fails, install Node.js again.
|
|
88
|
+
- "Unsupported engine", or `node --version` says less than 22.13: your Node.js is too old. Install it again as in step 1.
|
|
61
89
|
- On macOS, "EACCES" or "permission denied": npm cannot write where Node.js put it. Follow [npm's guide](https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally), not `sudo`: with `sudo`, Chesspal and Claude Code cannot update themselves.
|
|
90
|
+
- On Linux, "EACCES" or "permission denied": npm cannot write where your system's Node.js is. Do not use `sudo`: install Node.js with nvm, as in step 1, then run `npm install -g chesspal` again.
|
|
62
91
|
- Anything else in red, or with "ERR!": copy the last lines and [tell us](#try-it-and-tell-us).
|
|
63
92
|
|
|
64
93
|
## What it does
|
|
@@ -75,16 +104,16 @@ Coming later: an AI coach that helps you grow, exercises chosen on your weak poi
|
|
|
75
104
|
|
|
76
105
|
## What you need
|
|
77
106
|
|
|
78
|
-
- **Node.js 22.13** or newer.
|
|
79
|
-
- **An AI agent** with your own subscription: [Claude Code](https://code.claude.com/docs/en/setup), with a paid Claude plan,
|
|
107
|
+
- **Node.js 22.13** or newer, with **npm 10.9.2** or newer, which comes with it.
|
|
108
|
+
- **An AI agent** with your own subscription: [Claude Code](https://code.claude.com/docs/en/setup), with a paid Claude plan, [Codex](https://developers.openai.com/codex), with a ChatGPT account, or [Antigravity](https://antigravity.google/docs/getting-started), with a Google account.
|
|
80
109
|
- **A web browser**, for the board page.
|
|
81
110
|
|
|
82
|
-
Chesspal works with any agent that can use Chesspal's tools (MCP) and the files on your computer: we develop it with Claude Code, and Codex
|
|
111
|
+
Chesspal works with any agent that can use Chesspal's tools (MCP) and the files on your computer: we develop it with Claude Code, and Codex and Antigravity are connected too.
|
|
83
112
|
|
|
84
113
|
## Good to know
|
|
85
114
|
|
|
86
115
|
- **For the next game**, press New game: the AI the board page opened starts again with a clean chat by itself, once it has stopped working. In a chat you opened yourself, type `/clear` first: a long chat makes the AI slower and costs you more.
|
|
87
|
-
- **To play in a folder of your own**, as with the Claude desktop app, type `chesspal init chess`, then open your agent in the folder `chess` and say hello: the AI answers with the link to the board page. Any name will do; your games are kept [elsewhere](#where-your-games-are).
|
|
116
|
+
- **To play in a folder of your own**, as with the Claude desktop app, type `chesspal init chess`, then open your agent in the folder `chess` and say hello: the AI answers with the link to the board page. Any name will do; your games are kept [elsewhere](#where-your-games-are). Antigravity opened there asks about each of Chesspal's tools the first time: choose to always allow it (Persist to settings.json). Its very first chat in a new folder does not notice your moves on the board: type `/clear` once before you play.
|
|
88
117
|
- **A move written in the chat** counts too: `e4`, `Nf3`, in the international notation (K Q R B N in every language), or in words.
|
|
89
118
|
- **To update**, when a new version is out the table's page shows an arrow at the top: press it between games, and the table installs it and starts again, with its chat. By hand: close the AI's terminal, run `npm install -g chesspal` again, then `chesspal`. In a folder of your own, run `chesspal init` there too: it updates its own lines and keeps what you wrote there. In Codex, allow the hooks again when it says so.
|
|
90
119
|
- **To uninstall**, run `chesspal icon --remove` first, which takes the icon off your desktop and menu, then `npm uninstall -g chesspal`. Your games stay [where they are](#where-your-games-are).
|
package/dist/cli/chat-hook.d.ts
CHANGED
|
@@ -1,2 +1,5 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* Reads the hook's input and writes how the chat started; a failure is told on stderr and never stops the chat. Antigravity names its chat a conversation,
|
|
3
|
+
* new at every start, /clear too, and runs the hook in .agents: the chat's folder is the one its input names.
|
|
4
|
+
*/
|
|
2
5
|
export declare function recordChatStart(input?: NodeJS.ReadableStream, folder?: string, now?: Date): Promise<void>;
|
package/dist/cli/chat-hook.js
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
|
-
// `chesspal chat`, the SessionStart hook of Claude Code and
|
|
1
|
+
// `chesspal chat`, the SessionStart hook of Claude Code, Codex and Antigravity (D-57): it writes how the chat started, new, cleared, resumed or compacted,
|
|
2
|
+
// for new_game to read.
|
|
2
3
|
import { saveChatStart } from "../games/index.js";
|
|
3
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* Reads the hook's input and writes how the chat started; a failure is told on stderr and never stops the chat. Antigravity names its chat a conversation,
|
|
6
|
+
* new at every start, /clear too, and runs the hook in .agents: the chat's folder is the one its input names.
|
|
7
|
+
*/
|
|
4
8
|
export async function recordChatStart(input = process.stdin, folder = process.cwd(), now = new Date()) {
|
|
5
9
|
try {
|
|
6
10
|
const hook = parsed(await textOf(input));
|
|
7
|
-
|
|
11
|
+
const conversation = typeof hook.conversationId === "string" ? hook.conversationId : undefined;
|
|
12
|
+
const session = typeof hook.session_id === "string" ? hook.session_id : conversation;
|
|
13
|
+
const transcript = typeof hook.transcript_path === "string" ? hook.transcript_path : typeof hook.transcriptPath === "string" ? hook.transcriptPath : undefined;
|
|
14
|
+
saveChatStart(conversation !== undefined && typeof hook.cwd === "string" ? hook.cwd : folder, {
|
|
8
15
|
source: typeof hook.source === "string" ? hook.source : "startup",
|
|
9
16
|
at: now.toISOString(),
|
|
10
|
-
...(
|
|
11
|
-
...(
|
|
17
|
+
...(session === undefined ? {} : { session }),
|
|
18
|
+
...(transcript === undefined ? {} : { transcript }),
|
|
12
19
|
});
|
|
13
20
|
}
|
|
14
21
|
catch (error) {
|
package/dist/cli/cli.js
CHANGED
|
@@ -31,9 +31,9 @@ else if (args.length === 1 && args[0] === "mcp") {
|
|
|
31
31
|
const { startMcpServer } = await import("../server/mcp/index.js");
|
|
32
32
|
await startMcpServer();
|
|
33
33
|
}
|
|
34
|
-
else if (args[0] === "listen" && (args.length === 1 || (args.length === 2 && args[1] === "--codex"))) {
|
|
34
|
+
else if (args[0] === "listen" && (args.length === 1 || (args.length === 2 && (args[1] === "--codex" || args[1] === "--antigravity")))) {
|
|
35
35
|
const { listen } = await import("../server/bell/index.js");
|
|
36
|
-
await listen(args[1] === "--codex");
|
|
36
|
+
await listen(args[1] === "--codex" ? "codex" : args[1] === "--antigravity" ? "antigravity" : "claude");
|
|
37
37
|
}
|
|
38
38
|
else if (args.length === 1 && args[0] === "chat") {
|
|
39
39
|
const { recordChatStart } = await import("./chat-hook.js");
|
|
@@ -92,7 +92,7 @@ async function putIconHere() {
|
|
|
92
92
|
async function playHere(host) {
|
|
93
93
|
const [{ isHostName, playHost }, { defaultContext }] = await Promise.all([import("../server/table/index.js"), import("../commands/index.js")]);
|
|
94
94
|
if (!isHostName(host)) {
|
|
95
|
-
console.error(`chesspal play takes claude or
|
|
95
|
+
console.error(`chesspal play takes claude, codex or antigravity, not ${host}.`);
|
|
96
96
|
process.exitCode = 1;
|
|
97
97
|
return;
|
|
98
98
|
}
|
package/dist/cli/command-line.js
CHANGED
|
@@ -6,15 +6,15 @@ import { version } from "../version.js";
|
|
|
6
6
|
// The commands that exist only on the command line: cli.ts starts the table, opens its page, puts its icon, starts the server, the doorbell, the chat's
|
|
7
7
|
// note or the move written alone, when one comes alone.
|
|
8
8
|
const mcpDescription = "Start the MCP server for an AI host. Through it the host uses these commands as tools; the host starts it, with no options.";
|
|
9
|
-
const listenDescription = "Wait for the player's move on the board page and wake the chat. Claude Code starts it at the end of each turn, and
|
|
10
|
-
const chatDescription = "Note how the chat started: new, cleared, resumed or compacted. Claude Code and
|
|
9
|
+
const listenDescription = "Wait for the player's move on the board page and wake the chat. Claude Code starts it at the end of each turn, Codex with --codex and Antigravity with --antigravity, as init sets them up.";
|
|
10
|
+
const chatDescription = "Note how the chat started: new, cleared, resumed or compacted. Claude Code, Codex and Antigravity run it when a chat starts, as init sets them up.";
|
|
11
11
|
const promptDescription = "Play the move the player wrote alone in the chat, before the AI reads it, and tell the AI the position. Claude Code runs it on each message, as init sets it up.";
|
|
12
12
|
const tableDescription = "Serve the board page with no chat, until no browser has had it open for five minutes. `chesspal` alone starts it apart and opens the page.";
|
|
13
13
|
const openDescription = "Open the board page as `chesspal` alone does, without asking about the icon: what the icon runs.";
|
|
14
14
|
const iconDescription = "Put Chesspal's icon on the desktop and in the menu: it opens the board page as `chesspal` alone does, with no terminal. `chesspal icon --remove` takes it away.";
|
|
15
|
-
const playDescription = "Start the AI in this terminal, in Claude Code or
|
|
15
|
+
const playDescription = "Start the AI in this terminal, in Claude Code, Codex or Antigravity, as the page's buttons do. It plays with the model and effort chosen on the page; New game there starts the chat again, clean.";
|
|
16
16
|
// What init and the icon's removal are to a player, in the general help: the command's own help says the files.
|
|
17
|
-
const initForPlayer = "Set up a folder of your own to play in, from Claude Code, Codex or the Claude desktop app.";
|
|
17
|
+
const initForPlayer = "Set up a folder of your own to play in, from Claude Code, Codex, Antigravity or the Claude desktop app.";
|
|
18
18
|
const iconRemoveForPlayer = "Take Chesspal's icon away, before you uninstall it.";
|
|
19
19
|
// Those of them that take no options, by name.
|
|
20
20
|
const plainCommands = new Map([["mcp", mcpDescription], ["chat", chatDescription], ["prompt", promptDescription], ["table", tableDescription], ["open", openDescription], ["icon", iconDescription]]);
|
|
@@ -34,14 +34,14 @@ export async function runCommandLine(argv, context = defaultContext(), list = co
|
|
|
34
34
|
return args.length === 0 || args.includes("--help") || args.includes("-h") ? success(help) : failure(`chesspal ${commandName} takes no options: ${args.join(" ")}.\n\n${help}`);
|
|
35
35
|
}
|
|
36
36
|
if (commandName === "listen") {
|
|
37
|
-
const help = `chesspal listen [--codex]\n\n${listenDescription}`;
|
|
38
|
-
const known = args.every((arg) => ["--codex", "--help", "-h"].includes(arg));
|
|
39
|
-
return known ? success(help) : failure(`chesspal listen takes only --codex: ${args.join(" ")}.\n\n${help}`);
|
|
37
|
+
const help = `chesspal listen [--codex|--antigravity]\n\n${listenDescription}`;
|
|
38
|
+
const known = args.every((arg) => ["--codex", "--antigravity", "--help", "-h"].includes(arg));
|
|
39
|
+
return known ? success(help) : failure(`chesspal listen takes only --codex or --antigravity: ${args.join(" ")}.\n\n${help}`);
|
|
40
40
|
}
|
|
41
41
|
if (commandName === "play") {
|
|
42
42
|
// cli.ts runs `chesspal play <host>`; here come the help and what it refuses.
|
|
43
|
-
const help = `chesspal play <claude|codex>\n\n${playDescription}`;
|
|
44
|
-
return args.includes("--help") || args.includes("-h") ? success(help) : failure(`chesspal play takes one host, claude or
|
|
43
|
+
const help = `chesspal play <claude|codex|antigravity>\n\n${playDescription}`;
|
|
44
|
+
return args.includes("--help") || args.includes("-h") ? success(help) : failure(`chesspal play takes one host, claude, codex or antigravity: ${args.join(" ") || "none given"}.\n\n${help}`);
|
|
45
45
|
}
|
|
46
46
|
const command = list.find((candidate) => candidate.name === commandName);
|
|
47
47
|
if (!command) {
|
|
@@ -3,7 +3,7 @@ import { join } from "node:path";
|
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { aiLevels, Game, levelTag, pgnDate, readPgn, startClock, timeControlOf, timeControlTag, withoutMoods } from "../../core/index.js";
|
|
5
5
|
import { archivedName, archiveGame, archiveName, cleanSince, endAnalysis, endOf, endTableTalk, lastChatStart, loadGame, saveGame, startOfNewGame, withoutPlans } from "../../games/index.js";
|
|
6
|
-
import { hasDoorbell } from "../../host-files/index.js";
|
|
6
|
+
import { hasDoorbell, hookedHosts } from "../../host-files/index.js";
|
|
7
7
|
import { gameFolder, gameFolders } from "../../profiles/index.js";
|
|
8
8
|
import { coachRuns, gameAt, nextStep, openingTags, positionLines, refuseUnseenPosition, sidesLine, speechLine, speechOf, summaryOf, withThought } from "../answers/index.js";
|
|
9
9
|
import { pastGameLines, playerLine } from "../profiles/index.js";
|
|
@@ -159,18 +159,16 @@ export const pliesBeforeClearing = 20;
|
|
|
159
159
|
const fenPattern = /^[pnbrqkPNBRQK1-8]+(?:\/[pnbrqkPNBRQK1-8]+){7}(?:\s|$)/;
|
|
160
160
|
/**
|
|
161
161
|
* Whether the chat must be cleared first: the last game begun, in any profile, was played in it at some length, and the host says how chats start (the hook
|
|
162
|
-
* of Claude Code and
|
|
162
|
+
* of Claude Code, Codex and Antigravity). Another profile does not clear the chat (D-66), nor a game another chat played, which this one was never shown (D-71).
|
|
163
163
|
*/
|
|
164
164
|
function chatToClear(context) {
|
|
165
165
|
const start = lastChatStart(context.folder);
|
|
166
|
-
if (!
|
|
166
|
+
if (!hookedHosts.includes(context.host?.() ?? "") || start === undefined) {
|
|
167
167
|
return false;
|
|
168
168
|
}
|
|
169
169
|
const last = gameFolders(context.home()).flatMap((folder) => loadGame(folder) ?? []).sort((one, other) => Date.parse(other.started) - Date.parse(one.started))[0];
|
|
170
170
|
return last !== undefined && last.started === context.positionSeen?.started && last.game.record.moves.length >= pliesBeforeClearing && !cleanSince(start, last.started);
|
|
171
171
|
}
|
|
172
|
-
// The hosts whose SessionStart hook, written by init, notes how each chat starts: Claude Code and Codex, by the names they give the server.
|
|
173
|
-
const hostsNotingChats = new Set(["claude-code", "codex-mcp-client"]);
|
|
174
172
|
/**
|
|
175
173
|
* Writes the new game over the one before, archived first: both under game.json's lock, on the game before as read, so a game another process changed
|
|
176
174
|
* since is neither archived stale nor lost. When game.json cannot be written, an archive this call made goes: nothing changed.
|
|
@@ -12,6 +12,11 @@ export interface Context {
|
|
|
12
12
|
pause?: (milliseconds: number) => Promise<void>;
|
|
13
13
|
/** The operating system, as process.platform names it: how a host starts the server. */
|
|
14
14
|
platform: string;
|
|
15
|
+
/**
|
|
16
|
+
* The home folder of the computer's user, where a host keeps the settings of all its folders: init adds Chesspal's server to Antigravity's there
|
|
17
|
+
* (D-115). None in the tests, which never write there.
|
|
18
|
+
*/
|
|
19
|
+
userHome?: () => string;
|
|
15
20
|
/** The player's language, as the system names it (it-IT): the command line's words to the player, in English when none or another. */
|
|
16
21
|
language?: string;
|
|
17
22
|
/** The address of the board page, when the MCP server serves it (D-47). */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// What every command runs with besides its input, injected by the command line, the MCP server or the tests: the folders, the time, the randomness.
|
|
2
|
-
import { userInfo } from "node:os";
|
|
2
|
+
import { homedir, userInfo } from "node:os";
|
|
3
3
|
import { dataFolder, openFolder } from "../../home/index.js";
|
|
4
4
|
import { ensureProfile } from "../../profiles/index.js";
|
|
5
5
|
/** The context of a process started in the player's folder: the data folder is found at the first command that needs it, once. */
|
|
@@ -12,6 +12,7 @@ export function defaultContext() {
|
|
|
12
12
|
random: Math.random,
|
|
13
13
|
now: () => new Date(),
|
|
14
14
|
platform: process.platform,
|
|
15
|
+
userHome: homedir,
|
|
15
16
|
language: systemLanguage(),
|
|
16
17
|
given: new Set(),
|
|
17
18
|
openFolder: (folder) => openFolder(folder, process.platform),
|
|
@@ -8,7 +8,10 @@ interface FolderSetUp {
|
|
|
8
8
|
/** Codex's hooks changed in a folder that had them: Codex runs them only once the player trusts them again. */
|
|
9
9
|
hooksChanged?: true;
|
|
10
10
|
}
|
|
11
|
-
/**
|
|
11
|
+
/**
|
|
12
|
+
* Makes a folder the player's chess table: the files through which Claude Code, Codex and Antigravity find Chesspal and the opponent's instructions
|
|
13
|
+
* (D-31, D-115), and Antigravity's settings for every folder, where it is installed.
|
|
14
|
+
*/
|
|
12
15
|
export declare const init: import("../registry/registry.ts").Command<z.ZodObject<{
|
|
13
16
|
folder: z.ZodOptional<z.ZodString>;
|
|
14
17
|
}, z.core.$strip>, FolderSetUp>;
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
|
-
import { relative, resolve } from "node:path";
|
|
2
|
+
import { isAbsolute, relative, resolve } from "node:path";
|
|
3
3
|
// Colours only on a terminal that shows them: none in a file, a pipe or with NO_COLOR.
|
|
4
4
|
import { styleText } from "node:util";
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
import { codexHooksPath, setUpHosts } from "../../host-files/index.js";
|
|
7
7
|
import { defineCommand, speaksItalian } from "../registry/index.js";
|
|
8
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* Makes a folder the player's chess table: the files through which Claude Code, Codex and Antigravity find Chesspal and the opponent's instructions
|
|
10
|
+
* (D-31, D-115), and Antigravity's settings for every folder, where it is installed.
|
|
11
|
+
*/
|
|
9
12
|
export const init = defineCommand({
|
|
10
13
|
name: "init",
|
|
11
|
-
description: "Sets up a folder to play chess with an AI: the .mcp.json, AGENTS.md, CLAUDE.md and the settings through which Claude Code
|
|
12
|
-
+ "Chesspal. Run it again to update Chesspal's lines; what you wrote there stays. Example: chesspal init chess.",
|
|
14
|
+
description: "Sets up a folder to play chess with an AI: the .mcp.json, AGENTS.md, CLAUDE.md and the settings through which Claude Code, Codex and "
|
|
15
|
+
+ "Antigravity find Chesspal. Run it again to update Chesspal's lines; what you wrote there stays. Example: chesspal init chess.",
|
|
13
16
|
input: z.object({ folder: z.string().optional().describe("the folder to set up; the current folder if left out") }),
|
|
14
17
|
cliOnly: true,
|
|
15
18
|
idempotent: true,
|
|
@@ -18,11 +21,11 @@ export const init = defineCommand({
|
|
|
18
21
|
const root = resolve(context.folder, folder ?? ".");
|
|
19
22
|
const hooks = codexHooksPath(root);
|
|
20
23
|
const hadHooks = existsSync(hooks);
|
|
21
|
-
const written = setUpHosts(root, context.platform);
|
|
24
|
+
const written = setUpHosts(root, context.platform, context.userHome?.());
|
|
22
25
|
const enter = relative(context.folder, root);
|
|
23
26
|
return {
|
|
24
27
|
folder: root,
|
|
25
|
-
written: written.map((path) =>
|
|
28
|
+
written: written.map((path) => inFolder(root, path)),
|
|
26
29
|
...(enter === "" ? {} : { enter }),
|
|
27
30
|
...(hadHooks && written.includes(hooks) ? { hooksChanged: true } : {}),
|
|
28
31
|
};
|
|
@@ -44,9 +47,15 @@ const english = {
|
|
|
44
47
|
set: (folder) => `Chesspal is ready in ${folder}`,
|
|
45
48
|
ready: (folder) => `Chesspal is ready in ${folder}: nothing to change`,
|
|
46
49
|
toPlay: "To play:",
|
|
47
|
-
open: (enter) => enter === undefined ? ["Open Claude Code or
|
|
50
|
+
open: (enter) => enter === undefined ? ["Open Claude Code, Codex or Antigravity in this folder."] : [`Go into the folder: cd ${enter}`, "then open Claude Code (claude), Codex (codex) or Antigravity (agy)."],
|
|
48
51
|
steps: [
|
|
49
|
-
[
|
|
52
|
+
[
|
|
53
|
+
"The first time, it asks whether to trust the folder: say yes.",
|
|
54
|
+
"Codex also asks about Chesspal's two hooks: choose Trust all.",
|
|
55
|
+
"They are small helpers that let it notice your moves on the board.",
|
|
56
|
+
"Antigravity asks about each of Chesspal's tools the first time:",
|
|
57
|
+
"choose to always allow it (Persist to settings.json).",
|
|
58
|
+
],
|
|
50
59
|
["Say hello: the AI gives you the link to the board."],
|
|
51
60
|
],
|
|
52
61
|
hooksChanged: "Chesspal's hooks for Codex have changed: when Codex asks about them, choose Trust all again.",
|
|
@@ -56,14 +65,25 @@ const italian = {
|
|
|
56
65
|
set: (folder) => `Chesspal è pronto in ${folder}`,
|
|
57
66
|
ready: (folder) => `Chesspal è già pronto in ${folder}: niente da cambiare`,
|
|
58
67
|
toPlay: "Per giocare:",
|
|
59
|
-
open: (enter) => enter === undefined ? ["Apri Claude Code o
|
|
68
|
+
open: (enter) => enter === undefined ? ["Apri Claude Code, Codex o Antigravity in questa cartella."] : [`Entra nella cartella: cd ${enter}`, "poi apri Claude Code (claude), Codex (codex) o Antigravity (agy)."],
|
|
60
69
|
steps: [
|
|
61
|
-
[
|
|
70
|
+
[
|
|
71
|
+
"La prima volta ti chiede se fidarti della cartella: rispondi sì.",
|
|
72
|
+
"Codex chiede anche dei due «hook» di Chesspal: scegli Trust all.",
|
|
73
|
+
"Sono piccoli aiuti che gli fanno vedere le tue mosse sulla scacchiera.",
|
|
74
|
+
"Antigravity chiede di ogni strumento di Chesspal, la prima volta:",
|
|
75
|
+
"scegli di consentirlo sempre (Persist to settings.json).",
|
|
76
|
+
],
|
|
62
77
|
["Saluta: l'AI ti dà il link della scacchiera."],
|
|
63
78
|
],
|
|
64
79
|
hooksChanged: "Gli «hook» di Chesspal per Codex sono cambiati: quando Codex te lo chiede, scegli di nuovo Trust all.",
|
|
65
80
|
updated: (count) => count === 1 ? "Aggiornato 1 file." : `Aggiornati ${count} file.`,
|
|
66
81
|
};
|
|
82
|
+
/** A file init wrote, by its path in the player's folder; one outside it, as Antigravity's settings in the user's home, by its whole path. */
|
|
83
|
+
function inFolder(folder, path) {
|
|
84
|
+
const inside = relative(folder, path);
|
|
85
|
+
return inside.startsWith("..") || isAbsolute(inside) ? path : inside;
|
|
86
|
+
}
|
|
67
87
|
/** A path as a shell reads it as one word: in quotes when it has spaces. */
|
|
68
88
|
function quoted(path) {
|
|
69
89
|
return /\s/.test(path) ? `"${path}"` : path;
|
package/dist/core/review.d.ts
CHANGED
|
@@ -82,8 +82,8 @@ export declare function withAiHost(record: GameRecord, host: string | undefined)
|
|
|
82
82
|
/** The host the AI played the game in, as its tags say (D-97); undefined without one. */
|
|
83
83
|
export declare function aiHostIn(record: GameRecord): string | undefined;
|
|
84
84
|
/**
|
|
85
|
-
* The AI's name from its host: Claude Code and the desktop app are Claude, Codex is Codex
|
|
86
|
-
*
|
|
85
|
+
* The AI's name from its host: Claude Code and the desktop app are Claude, Codex is Codex, Antigravity is Gemini, unless its model is known to be another
|
|
86
|
+
* (D-97, D-115); without a host it names, from the model, a Claude model is Claude. Undefined otherwise.
|
|
87
87
|
*/
|
|
88
88
|
export declare function aiNameOf(host: string | undefined, model?: string): string | undefined;
|
|
89
89
|
/** The record with the AI's word on the whole game, or its last word on the ending, in place of the one it had: each only when given. */
|
package/dist/core/review.js
CHANGED
|
@@ -108,17 +108,21 @@ export function aiHostIn(record) {
|
|
|
108
108
|
return host === undefined || host === "" ? undefined : host;
|
|
109
109
|
}
|
|
110
110
|
/**
|
|
111
|
-
* The AI's name from its host: Claude Code and the desktop app are Claude, Codex is Codex
|
|
112
|
-
*
|
|
111
|
+
* The AI's name from its host: Claude Code and the desktop app are Claude, Codex is Codex, Antigravity is Gemini, unless its model is known to be another
|
|
112
|
+
* (D-97, D-115); without a host it names, from the model, a Claude model is Claude. Undefined otherwise.
|
|
113
113
|
*/
|
|
114
114
|
export function aiNameOf(host, model) {
|
|
115
|
+
const named = model?.trim() ?? "";
|
|
115
116
|
if (/claude/i.test(host ?? "")) {
|
|
116
117
|
return "Claude";
|
|
117
118
|
}
|
|
118
119
|
if (/codex/i.test(host ?? "")) {
|
|
119
120
|
return "Codex";
|
|
120
121
|
}
|
|
121
|
-
|
|
122
|
+
if (/antigravity/i.test(host ?? "")) {
|
|
123
|
+
return named === "" || /^gemini/i.test(named) ? "Gemini" : /^claude/i.test(named) ? "Claude" : "Antigravity";
|
|
124
|
+
}
|
|
125
|
+
return /^claude/i.test(named) ? "Claude" : undefined;
|
|
122
126
|
}
|
|
123
127
|
/** The record with the AI's word on the whole game, or its last word on the ending, in place of the one it had: each only when given. */
|
|
124
128
|
export function withGameReview(record, { summary, closing }) {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Sets up the player's folder for Claude Code and
|
|
3
|
-
* Chesspal's marks (D-102), CLAUDE.md importing it, the hosts' settings with the server approved, and their hooks.
|
|
4
|
-
* the
|
|
2
|
+
* Sets up the player's folder for Claude Code, Codex and Antigravity (D-31, D-115): .mcp.json with the chesspal server, AGENTS.md with the lines that start
|
|
3
|
+
* a chat between Chesspal's marks (D-102), CLAUDE.md importing it, the hosts' settings with the server approved, and their hooks. With the user's home
|
|
4
|
+
* given, where Antigravity is installed, the chesspal server in its settings for every folder too, which alone give the first chat its tools. What the
|
|
5
|
+
* player wrote there stays; it returns the files written.
|
|
5
6
|
*/
|
|
6
|
-
export declare function setUpHosts(folder: string, platform: string): string[];
|
|
7
|
+
export declare function setUpHosts(folder: string, platform: string, userHome?: string): string[];
|
|
7
8
|
/**
|
|
8
9
|
* The files an older init wrote in a folder, or left out, that this version would write otherwise, by their paths in it: the AI and the page then ask the
|
|
9
10
|
* player to run init again. None in a folder init never set up.
|
|
@@ -12,10 +13,13 @@ export declare function outdatedHostFiles(folder: string, platform: string): str
|
|
|
12
13
|
/** Where Codex reads a folder's hooks, which it runs only once the player trusts them. */
|
|
13
14
|
export declare function codexHooksPath(folder: string): string;
|
|
14
15
|
/**
|
|
15
|
-
* Whether the host runs the
|
|
16
|
-
* the chat; the command line, which names no host, is taken as one. Elsewhere the player tells the
|
|
16
|
+
* Whether the host runs the hooks init writes, the doorbell and the note of how each chat starts: Claude Code, Codex and Antigravity by the names they give
|
|
17
|
+
* the server, so the player's act on the page wakes the chat; the command line, which names no host, is taken as one. Elsewhere the player tells the
|
|
18
|
+
* chat in its window.
|
|
17
19
|
*/
|
|
18
20
|
export declare function hasDoorbell(host: string | undefined): boolean;
|
|
21
|
+
/** The hosts that run the hooks init writes, by the names they give the server: Antigravity's too (D-115). */
|
|
22
|
+
export declare const hookedHosts: readonly string[];
|
|
19
23
|
/** The instructions of the AI opponent, read from the package wherever it is installed: the MCP server's `instructions` tool gives them (D-102). */
|
|
20
24
|
export declare function opponentInstructions(): string;
|
|
21
25
|
/** The lines that start a chat, in the MCP server's instructions and in AGENTS.md: call `instructions`, then `status` (D-102). */
|
|
@@ -4,13 +4,14 @@ import { join, relative } from "node:path";
|
|
|
4
4
|
import { makeFolder, writeAtomically } from "../games/index.js";
|
|
5
5
|
import { agentFiles, agentHosts, instructionsFile } from "./agents.js";
|
|
6
6
|
/**
|
|
7
|
-
* Sets up the player's folder for Claude Code and
|
|
8
|
-
* Chesspal's marks (D-102), CLAUDE.md importing it, the hosts' settings with the server approved, and their hooks.
|
|
9
|
-
* the
|
|
7
|
+
* Sets up the player's folder for Claude Code, Codex and Antigravity (D-31, D-115): .mcp.json with the chesspal server, AGENTS.md with the lines that start
|
|
8
|
+
* a chat between Chesspal's marks (D-102), CLAUDE.md importing it, the hosts' settings with the server approved, and their hooks. With the user's home
|
|
9
|
+
* given, where Antigravity is installed, the chesspal server in its settings for every folder too, which alone give the first chat its tools. What the
|
|
10
|
+
* player wrote there stays; it returns the files written.
|
|
10
11
|
*/
|
|
11
|
-
export function setUpHosts(folder, platform) {
|
|
12
|
+
export function setUpHosts(folder, platform, userHome) {
|
|
12
13
|
makeFolder(folder);
|
|
13
|
-
const written = hostChanges(folder, platform);
|
|
14
|
+
const written = [...hostChanges(folder, platform), ...(userHome === undefined ? [] : globalChanges(userHome, platform))];
|
|
14
15
|
for (const { path, text } of written) {
|
|
15
16
|
makeFolder(join(path, ".."));
|
|
16
17
|
writeAtomically(path, text);
|
|
@@ -32,12 +33,15 @@ export function codexHooksPath(folder) {
|
|
|
32
33
|
return join(folder, ".codex", "hooks.json");
|
|
33
34
|
}
|
|
34
35
|
/**
|
|
35
|
-
* Whether the host runs the
|
|
36
|
-
* the chat; the command line, which names no host, is taken as one. Elsewhere the player tells the
|
|
36
|
+
* Whether the host runs the hooks init writes, the doorbell and the note of how each chat starts: Claude Code, Codex and Antigravity by the names they give
|
|
37
|
+
* the server, so the player's act on the page wakes the chat; the command line, which names no host, is taken as one. Elsewhere the player tells the
|
|
38
|
+
* chat in its window.
|
|
37
39
|
*/
|
|
38
40
|
export function hasDoorbell(host) {
|
|
39
|
-
return host === undefined ||
|
|
41
|
+
return host === undefined || hookedHosts.includes(host);
|
|
40
42
|
}
|
|
43
|
+
/** The hosts that run the hooks init writes, by the names they give the server: Antigravity's too (D-115). */
|
|
44
|
+
export const hookedHosts = [...agentHosts, "antigravity-client"];
|
|
41
45
|
/** The instructions of the AI opponent, read from the package wherever it is installed: the MCP server's `instructions` tool gives them (D-102). */
|
|
42
46
|
export function opponentInstructions() {
|
|
43
47
|
return instructionsFile("opponent");
|
|
@@ -52,9 +56,23 @@ const endMark = "<!-- chesspal: end -->";
|
|
|
52
56
|
const markedBlock = /<!-- chesspal: (?!end)[^\n]*\n[\s\S]*?<!-- chesspal: end -->/;
|
|
53
57
|
/** What init writes for each host, missing or changed: what the player wrote there stays. */
|
|
54
58
|
function hostChanges(folder, platform) {
|
|
55
|
-
const changes = [
|
|
59
|
+
const changes = [
|
|
60
|
+
mcpFile(folder, platform),
|
|
61
|
+
agentsFile(folder),
|
|
62
|
+
claudeFile(folder),
|
|
63
|
+
claudeSettingsFile(folder),
|
|
64
|
+
...agentChanges(folder),
|
|
65
|
+
codexConfigFile(folder, platform),
|
|
66
|
+
codexHooksFile(folder),
|
|
67
|
+
antigravityHooksFile(folder),
|
|
68
|
+
];
|
|
56
69
|
return changes.filter((change) => change !== undefined);
|
|
57
70
|
}
|
|
71
|
+
/** What init writes outside the player's folder, in the user's home: the chesspal server in Antigravity's settings for every folder, where it is installed. */
|
|
72
|
+
function globalChanges(userHome, platform) {
|
|
73
|
+
const change = antigravityInstalled(userHome, platform) ? antigravityServerFile(userHome, platform) : undefined;
|
|
74
|
+
return change === undefined ? [] : [change];
|
|
75
|
+
}
|
|
58
76
|
/** How a host starts the server: on Windows through cmd, which finds npm's shim. */
|
|
59
77
|
function chesspalServer(platform) {
|
|
60
78
|
return platform === "win32" ? { command: "cmd", args: ["/c", "chesspal", "mcp"] } : { command: "chesspal", args: ["mcp"] };
|
|
@@ -166,6 +184,36 @@ const codexBellHook = {
|
|
|
166
184
|
};
|
|
167
185
|
// Codex's SessionStart hook: it notes how each chat starts, as Claude Code's does (D-57).
|
|
168
186
|
const codexChatHook = { type: "command", command: "chesspal chat", commandWindows: "chesspal.cmd chat" };
|
|
187
|
+
/**
|
|
188
|
+
* Antigravity's hooks, which it runs in a folder the player trusts, under a name of Chesspal's beside the player's own (D-115): how each chat starts
|
|
189
|
+
* (D-57), and the doorbell, which holds the turn's end until the player acts on the page; a day at most. Both read the chat's folder from their input,
|
|
190
|
+
* since Antigravity runs them in .agents.
|
|
191
|
+
*/
|
|
192
|
+
function antigravityHooksFile(folder) {
|
|
193
|
+
const path = join(folder, ".agents", "hooks.json");
|
|
194
|
+
const hooks = {
|
|
195
|
+
SessionStart: [{ type: "command", command: "chesspal chat", timeout: 30 }],
|
|
196
|
+
Stop: [{ type: "command", command: "chesspal listen --antigravity", timeout: 86_400 }],
|
|
197
|
+
};
|
|
198
|
+
return changed(path, { ...jsonOf(path), chesspal: hooks });
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Antigravity's MCP servers for every folder, with the chesspal server beside the player's: its first chat gets the tools of these alone, not of the
|
|
202
|
+
* folder's (Priya). No environment of Chesspal's, since Antigravity hands its own to the server, CHESSPAL_HOME with it; one the player gave stays. Never
|
|
203
|
+
* a backslash, which Antigravity refuses; a file left empty is no server at all.
|
|
204
|
+
*/
|
|
205
|
+
function antigravityServerFile(userHome, platform) {
|
|
206
|
+
const path = join(userHome, ".gemini", "config", "mcp_config.json");
|
|
207
|
+
const config = textOf(path)?.trim() === "" ? {} : jsonOf(path);
|
|
208
|
+
const servers = isObject(config.mcpServers) ? config.mcpServers : {};
|
|
209
|
+
const before = isObject(servers.chesspal) ? servers.chesspal : {};
|
|
210
|
+
return changed(path, { ...config, mcpServers: { ...servers, chesspal: { ...chesspalServer(platform), ...(isObject(before.env) ? { env: before.env } : {}) } } });
|
|
211
|
+
}
|
|
212
|
+
/** Whether Antigravity's command line is on this computer: its own folder in the user's home, made at its first start, or its program where its installer puts it. */
|
|
213
|
+
function antigravityInstalled(userHome, platform) {
|
|
214
|
+
const program = platform === "win32" ? join(userHome, "AppData", "Local", "agy", "bin", "agy.exe") : join(userHome, ".local", "bin", "agy");
|
|
215
|
+
return existsSync(join(userHome, ".gemini", "antigravity-cli")) || existsSync(program);
|
|
216
|
+
}
|
|
169
217
|
/** A JSON file's new content, when it differs from what is there. */
|
|
170
218
|
function changed(path, value) {
|
|
171
219
|
const text = `${JSON.stringify(value, null, 2)}\n`;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { agentHosts, agentTools, analystAgent, coachAgent, hasAgent, instructionsFile, isCodex, onQuickModel, ponderAgentFor, ponderAgents } from "./agents.ts";
|
|
2
|
-
export { codexHooksPath, hasDoorbell, opponentInstructions, outdatedHostFiles, setUpHosts, startInstructions } from "./host-files.ts";
|
|
2
|
+
export { codexHooksPath, hasDoorbell, hookedHosts, opponentInstructions, outdatedHostFiles, setUpHosts, startInstructions } from "./host-files.ts";
|
package/dist/host-files/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// The files through which an AI host finds Chesspal in the player's folder: the server, the opponent's instructions, the hosts' settings.
|
|
2
2
|
export { agentHosts, agentTools, analystAgent, coachAgent, hasAgent, instructionsFile, isCodex, onQuickModel, ponderAgentFor, ponderAgents } from "./agents.js";
|
|
3
|
-
export { codexHooksPath, hasDoorbell, opponentInstructions, outdatedHostFiles, setUpHosts, startInstructions } from "./host-files.js";
|
|
3
|
+
export { codexHooksPath, hasDoorbell, hookedHosts, opponentInstructions, outdatedHostFiles, setUpHosts, startInstructions } from "./host-files.js";
|
package/dist/page/app/app.js
CHANGED
|
@@ -131,7 +131,7 @@ export function App({ start }) {
|
|
|
131
131
|
apply(settingsFrom(served.settings));
|
|
132
132
|
}
|
|
133
133
|
}, [profileId]);
|
|
134
|
-
// The AI as the host names it (Claude, Codex), also where the page sends the player to write; the last known while the page is offline.
|
|
134
|
+
// The AI as the host names it (Claude, Codex, Gemini), also where the page sends the player to write; the last known while the page is offline.
|
|
135
135
|
const name = served?.opponent ?? text.ai;
|
|
136
136
|
// Under it, the model and effort the AI played its last move with (D-82).
|
|
137
137
|
const signed = served?.aiModel === undefined ? undefined : signature(served.aiModel.model, served.aiModel.effort);
|
package/dist/page/guide/en.md
CHANGED
|
@@ -18,7 +18,7 @@ No chess engine plays for the AI: every move and every judgment is its own. Ches
|
|
|
18
18
|
|
|
19
19
|
### Getting started
|
|
20
20
|
|
|
21
|
-
1. Click the **AI's name**, at the top left, and choose its chat among those on your computer: **Claude Code** or **
|
|
21
|
+
1. Click the **AI's name**, at the top left, and choose its chat among those on your computer: **Claude Code**, **Codex** or **Antigravity**. It opens in a window of its own: keep it open while you play. The first time it asks some questions. Whether you trust the folder: **Yes** (in Claude Code No is chosen already: go down to Yes with the arrow keys, then Enter). With Codex, about the hooks, Chesspal's two helpers: **Trust all and continue**. On Windows Codex also asks whether to set up its sandbox, the protected space it works in: choose the first option, and yes when Windows asks for permission.
|
|
22
22
|
2. Press **New game**, choose your colour, the clock and the AI's level, and press **Start**.
|
|
23
23
|
3. Move: the AI answers on the board, and with a few words under its name.
|
|
24
24
|
|
|
@@ -37,7 +37,7 @@ No chess engine plays for the AI: every move and every judgment is its own. Ches
|
|
|
37
37
|
|
|
38
38
|
- You talk with the AI in the **box under its name**, a few words with each move: it reads them with your move. You can also write to it in its window. With Codex, if you write there while it waits for your move, press **Esc** after Enter: else it reads your message only after your move.
|
|
39
39
|
- A **move written** in the chat counts too: `e4`, `Nf3`, with the English letters of the pieces (K Q R B N), or in words.
|
|
40
|
-
- **The AI's name** opens the choice of its chat: Claude Code or
|
|
40
|
+
- **The AI's name** opens the choice of its chat: Claude Code, Codex or Antigravity, the model (which AI: some are faster, others stronger) and how much it reasons. The more it reasons, the slower it plays. If you change them, the chat starts afresh in the same window: the AI forgets what you talked about, and the game stays as it is. In analysis the name stands over the box where you write to it.
|
|
41
41
|
- At each **new game**, the chat the page opened starts afresh by itself, once the AI has stopped thinking: a long chat makes the AI slower.
|
|
42
42
|
|
|
43
43
|
## Helps and marks
|
package/dist/page/guide/it.md
CHANGED
|
@@ -18,7 +18,7 @@ Nessun motore di scacchi gioca al posto dell'AI: ogni mossa e ogni giudizio sono
|
|
|
18
18
|
|
|
19
19
|
### Per cominciare
|
|
20
20
|
|
|
21
|
-
1. Clicca il **nome dell'AI**, in alto a sinistra, e scegli la chat fra quelle che hai sul computer: **Claude Code** o **
|
|
21
|
+
1. Clicca il **nome dell'AI**, in alto a sinistra, e scegli la chat fra quelle che hai sul computer: **Claude Code**, **Codex** o **Antigravity**. Si apre in una finestra sua: tienila aperta mentre giochi. La prima volta fa qualche domanda. Se ti fidi della cartella: **Sì** (in Claude Code è già scelto No: scendi su Yes con le frecce, poi Invio). Con Codex, sugli hook, i due aiutanti di Chesspal: **Trust all and continue**. Su Windows Codex chiede anche se preparare la sua sandbox, lo spazio protetto dove lavora: scegli la prima opzione, e sì quando Windows chiede il permesso.
|
|
22
22
|
2. Premi **Nuova partita**, scegli il colore, l'orologio e il livello dell'AI, e premi **Inizia**.
|
|
23
23
|
3. Muovi: l'AI risponde sulla scacchiera, e con qualche parola sotto il suo nome.
|
|
24
24
|
|
|
@@ -37,7 +37,7 @@ Nessun motore di scacchi gioca al posto dell'AI: ogni mossa e ogni giudizio sono
|
|
|
37
37
|
|
|
38
38
|
- Parli con l'AI nella **casella sotto il suo nome**, qualche parola a ogni mossa: le legge con la tua mossa. Puoi scriverle anche nella sua finestra. Con Codex, se gli scrivi lì mentre aspetta la tua mossa, dopo Invio premi **Esc**: se no legge il messaggio solo dopo la tua mossa.
|
|
39
39
|
- Anche una **mossa scritta** nella chat vale: `e4`, `Nf3`, con le lettere inglesi dei pezzi (K Q R B N), o a parole.
|
|
40
|
-
- **Il nome dell'AI** apre la scelta della chat: Claude Code o
|
|
40
|
+
- **Il nome dell'AI** apre la scelta della chat: Claude Code, Codex o Antigravity, il modello (quale AI: alcune sono più veloci, altre più forti) e quanto ragiona. Più ragiona, più gioca lenta. Se cambi, la chat riparte da capo nella stessa finestra: l'AI dimentica la chiacchierata di prima, la partita resta com'è. Nell'analisi il nome sta sopra la casella dove le scrivi.
|
|
41
41
|
- A ogni **nuova partita** la chat aperta dalla pagina riparte da capo da sola, se l'AI ha finito di pensare: una chat lunga rende l'AI più lenta.
|
|
42
42
|
|
|
43
43
|
## Gli aiuti e i segni
|
|
@@ -36,6 +36,8 @@ export function settingsFrom(value, defaults = { theme: "system", sound: true })
|
|
|
36
36
|
claudeEffort: word(stored.claudeEffort),
|
|
37
37
|
codexModel: word(stored.codexModel),
|
|
38
38
|
codexEffort: word(stored.codexEffort),
|
|
39
|
+
antigravityModel: word(stored.antigravityModel),
|
|
40
|
+
antigravityEffort: word(stored.antigravityEffort),
|
|
39
41
|
};
|
|
40
42
|
}
|
|
41
43
|
/** Remembers the settings in this browser. */
|