castle-web-cli 0.4.77 → 0.4.79
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/dist/agent-prompts.d.ts +4 -1
- package/dist/agent-prompts.js +28 -7
- package/dist/agent.d.ts +7 -2
- package/dist/agent.js +655 -51
- package/dist/ide.js +2 -0
- package/dist/native/loop.d.ts +2 -0
- package/dist/native/loop.js +698 -0
- package/dist/native/openrouter.d.ts +55 -0
- package/dist/native/openrouter.js +354 -0
- package/dist/native/playtest-browser.d.ts +34 -0
- package/dist/native/playtest-browser.js +354 -0
- package/dist/native/playtest-executor.d.ts +3 -0
- package/dist/native/playtest-executor.js +156 -0
- package/dist/native/playtest.d.ts +131 -0
- package/dist/native/playtest.js +314 -0
- package/dist/native/tools.d.ts +38 -0
- package/dist/native/tools.js +630 -0
- package/dist/native/types.d.ts +40 -0
- package/dist/native/types.js +41 -0
- package/dist/serve.js +12 -0
- package/dist/shell/assets/{index-CvHiGhAV.js → index-CNT3KxJb.js} +37 -37
- package/dist/shell/assets/{index-QteLRDnK.css → index-RZrw5gQ2.css} +1 -1
- package/dist/shell/index.html +2 -2
- package/kits/basic-2d/CLAUDE.md +29 -3
- package/kits/basic-2d/behaviors/Layout.jsx +10 -0
- package/kits/basic-2d/behaviors/Sprite.jsx +16 -4
- package/kits/basic-2d/blueprints/cauldron.scene +22 -0
- package/kits/basic-2d/castle.json +5 -7
- package/kits/basic-2d/docs/pxart-format.md +83 -4
- package/kits/basic-2d/drawings/cauldron.pxart +113 -0
- package/kits/basic-2d/editors/BlueprintLibrary.jsx +247 -0
- package/kits/basic-2d/editors/PlayOnly.jsx +1 -0
- package/kits/basic-2d/editors/PxArtEditor.jsx +68 -9
- package/kits/basic-2d/editors/SceneEditor.jsx +424 -418
- package/kits/basic-2d/editors/SelectionOverlay.jsx +125 -63
- package/kits/basic-2d/editors/SingleEditor.jsx +11 -2
- package/kits/basic-2d/editors/editorHistory.js +95 -17
- package/kits/basic-2d/editors/inspectorSheet.js +5 -19
- package/kits/basic-2d/editors/pixelEditorChrome.jsx +21 -8
- package/kits/basic-2d/editors/pixelInspector.jsx +39 -0
- package/kits/basic-2d/editors/pxArtEditorModel.js +15 -1
- package/kits/basic-2d/engine/ScenePlayer.jsx +2 -2
- package/kits/basic-2d/engine/blueprint.js +423 -0
- package/kits/basic-2d/engine/files.js +1 -1
- package/kits/basic-2d/engine/pxart.js +49 -2
- package/kits/basic-2d/engine/pxartSmooth.js +222 -0
- package/kits/basic-2d/engine/scene.js +29 -29
- package/kits/basic-2d/engine/ui.jsx +160 -21
- package/kits/basic-2d/engine/ui.module.css +263 -27
- package/kits/basic-2d/pnpm-workspace.yaml +3 -0
- package/kits/basic-2d/scenes/main.scene +3 -13
- package/package.json +2 -1
- package/kits/basic-2d/drawings/pig.pxart +0 -26
package/dist/agent-prompts.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export interface PromptTask {
|
|
|
12
12
|
files?: string[];
|
|
13
13
|
error?: string;
|
|
14
14
|
blockedBy?: string[];
|
|
15
|
+
suspectNoChanges?: boolean;
|
|
15
16
|
}
|
|
16
17
|
export interface PromptSibling {
|
|
17
18
|
title: string;
|
|
@@ -22,6 +23,7 @@ export declare function buildRouterPrompt(opts: {
|
|
|
22
23
|
deckLabel: string;
|
|
23
24
|
quickReference?: string;
|
|
24
25
|
deckTree?: string;
|
|
26
|
+
deckContents?: string;
|
|
25
27
|
messages: PromptMessage[];
|
|
26
28
|
tasks: PromptTask[];
|
|
27
29
|
instruction: string;
|
|
@@ -39,8 +41,9 @@ export declare function buildTaskPrompt(opts: {
|
|
|
39
41
|
progressPath: string;
|
|
40
42
|
notesPath: string;
|
|
41
43
|
depsSummary?: string;
|
|
42
|
-
backend?: "cursor" | "claude";
|
|
44
|
+
backend?: "cursor" | "claude" | "smith";
|
|
43
45
|
deckTree?: string;
|
|
46
|
+
deckContents?: string;
|
|
44
47
|
quickReference?: string;
|
|
45
48
|
siblings?: PromptSibling[];
|
|
46
49
|
}): string;
|
package/dist/agent-prompts.js
CHANGED
|
@@ -93,17 +93,29 @@ function renderTasks(tasks) {
|
|
|
93
93
|
const blockedBy = t.blockedBy && t.blockedBy.length > 0
|
|
94
94
|
? ` -- blocked by: ${t.blockedBy.join(", ")}`
|
|
95
95
|
: "";
|
|
96
|
-
|
|
96
|
+
const suspect = t.suspectNoChanges
|
|
97
|
+
? " -- caution: done but touched no tracked files (bash side effects aren't tracked); verify the work actually landed"
|
|
98
|
+
: "";
|
|
99
|
+
return `- [${t.status} ${t.progress}%] ${t.title} (${t.id})${notes}${files}${error}${blockedBy}${suspect}`;
|
|
97
100
|
})
|
|
98
101
|
.join("\n");
|
|
99
102
|
}
|
|
100
103
|
export function buildRouterPrompt(opts) {
|
|
104
|
+
// Making the ABSENCE explicit, not just omitting the section, matters: a
|
|
105
|
+
// router on a bare/greenfield deck otherwise has no way to tell "no docs
|
|
106
|
+
// exist" from "the docs section just wasn't included in this prompt", and
|
|
107
|
+
// burns its first tool-call turns hunting for CLAUDE.md / **/*.md that
|
|
108
|
+
// isn't there (real incident: 2 of a router turn's 9 iterations, on an
|
|
109
|
+
// 8-file deck with zero markdown files).
|
|
101
110
|
const quickReference = opts.quickReference?.trim()
|
|
102
111
|
? `\n\n== how this deck works ==\n${opts.quickReference.trim()}`
|
|
103
|
-
: "";
|
|
112
|
+
: "\n\n== how this deck works ==\nThis deck has no CLAUDE.md / AGENTS.md quick reference. There is no documentation to read -- do not search for one (CLAUDE.md, README, **/*.md, etc.).";
|
|
104
113
|
const deckFiles = opts.deckTree?.trim()
|
|
105
114
|
? `\n\n== deck files ==\n${opts.deckTree.trim()}`
|
|
106
115
|
: "";
|
|
116
|
+
const deckSource = opts.deckContents?.trim()
|
|
117
|
+
? `\n\n== deck source (current contents -- no need to read_file these to see what's already there) ==\n${opts.deckContents.trim()}`
|
|
118
|
+
: "";
|
|
107
119
|
// Section order is stable-to-volatile for prompt caching: rules + deck
|
|
108
120
|
// identity never change within a serve, the transcript is append-only, and
|
|
109
121
|
// the churning state (file tree, task board, instruction) rides at the tail
|
|
@@ -114,7 +126,7 @@ export function buildRouterPrompt(opts) {
|
|
|
114
126
|
${opts.deckLabel}${quickReference}
|
|
115
127
|
|
|
116
128
|
== conversation so far ==
|
|
117
|
-
${renderTranscript(opts.messages)}${deckFiles}
|
|
129
|
+
${renderTranscript(opts.messages)}${deckFiles}${deckSource}
|
|
118
130
|
|
|
119
131
|
== background tasks ==
|
|
120
132
|
${renderTasks(opts.tasks)}
|
|
@@ -139,7 +151,10 @@ export function userTurnInstruction(opts) {
|
|
|
139
151
|
.join("\n\n")}`);
|
|
140
152
|
}
|
|
141
153
|
if (opts.attachments && opts.attachments.length > 0) {
|
|
142
|
-
|
|
154
|
+
// Wording covers both delivery modes: smith gets the images inline as
|
|
155
|
+
// content blocks in this same message (its read tool rejects binaries),
|
|
156
|
+
// while the CLI backends open the saved files themselves.
|
|
157
|
+
parts.push(`The user attached image file(s), saved in the deck at: ${opts.attachments.join(", ")}. If the images are not already visible in this message, open them with your read tool. Take them into account; pass the paths along to task agents that need them.`);
|
|
143
158
|
}
|
|
144
159
|
return parts.join("\n\n");
|
|
145
160
|
}
|
|
@@ -153,12 +168,18 @@ export function buildTaskPrompt(opts) {
|
|
|
153
168
|
const siblings = siblingRows
|
|
154
169
|
? `\n\nOther tasks on this deck's board (snapshot at your start):\n${siblingRows}\nRunning and waiting rows are sibling agents working in this same directory. If a sibling plainly owns something your prompt only references (art, a scene, a behavior), leave it to them -- create only what YOUR prompt says to create. Finished rows' file lists show where recent work landed.\n`
|
|
155
170
|
: "";
|
|
171
|
+
// Same "say there are no docs" reasoning as buildRouterPrompt's
|
|
172
|
+
// quickReference above -- a task agent wastes turns the same way a router
|
|
173
|
+
// does if it has to discover the absence itself via a failed read/grep.
|
|
156
174
|
const quickReference = opts.quickReference?.trim()
|
|
157
175
|
? `\n\nHow this deck works (from its docs -- read the full CLAUDE.md / AGENTS.md only when you need detail beyond this):\n\n${opts.quickReference.trim()}\n`
|
|
158
|
-
: "";
|
|
176
|
+
: "\n\nThis deck has no CLAUDE.md / AGENTS.md quick reference. There is no documentation to read -- do not search for one (CLAUDE.md, README, **/*.md, etc.).\n";
|
|
159
177
|
const layout = opts.deckTree?.trim()
|
|
160
178
|
? `\n\nDeck files (snapshot at task start; parallel sibling tasks may create files named in your prompt that are absent here):\n\n${opts.deckTree.trim()}\n`
|
|
161
179
|
: "";
|
|
180
|
+
const deckSource = opts.deckContents?.trim()
|
|
181
|
+
? `\n\nDeck source (complete current contents of the deck's text files, snapshot at task start -- you do NOT need to read these files before editing them, edit directly; a file marked "not inlined" is either binary/generated or didn't fit the budget, so read it yourself first if you need it):\n\n${opts.deckContents.trim()}\n`
|
|
182
|
+
: "";
|
|
162
183
|
// Claude-only: collapsing the wrap-up (progress 90 + restart + notes) into
|
|
163
184
|
// one shell call reliably saves 1-2 serial ~7s turns there. Cursor's
|
|
164
185
|
// composer sometimes reacts to the same rule with MORE calls, so it stays
|
|
@@ -166,10 +187,10 @@ export function buildTaskPrompt(opts) {
|
|
|
166
187
|
// (We deliberately do NOT tell agents to overwrite files via `cat > … <<EOF`
|
|
167
188
|
// -- blind whole-file rewrites made parallel agents clobber each other's
|
|
168
189
|
// edits. Read-then-edit is slower but safe; that is the right tradeoff.)
|
|
169
|
-
const wrapUp = opts.backend === "claude"
|
|
190
|
+
const wrapUp = opts.backend === "claude" || opts.backend === "smith"
|
|
170
191
|
? `\n- Wrap up in ONE tool call, not several: once your last file edit is done, combine the 90-progress write, the final \`npm run restart\`, and writing the notes file into a single shell command (\`;\`-separated so the notes land even if the restart hiccups). Then stop -- no extra turns after it.`
|
|
171
192
|
: "";
|
|
172
|
-
return `You are a background build agent for the Castle deck "${opts.deckLabel}" (current directory). A separate conversation agent dispatched you with one task. Follow the deck's CLAUDE.md / AGENTS.md conventions, and reload the served deck after changes (\`npm run restart\`).${quickReference}${layout}
|
|
193
|
+
return `You are a background build agent for the Castle deck "${opts.deckLabel}" (current directory). A separate conversation agent dispatched you with one task. Follow the deck's CLAUDE.md / AGENTS.md conventions, and reload the served deck after changes (\`npm run restart\`).${quickReference}${layout}${deckSource}
|
|
173
194
|
|
|
174
195
|
Your task (id ${opts.taskId}): ${opts.title}
|
|
175
196
|
|
package/dist/agent.d.ts
CHANGED
|
@@ -2,8 +2,9 @@ import * as http from "http";
|
|
|
2
2
|
import { Duplex } from "stream";
|
|
3
3
|
export declare const AGENT_WS_PATH = "/__castle/agent";
|
|
4
4
|
export declare const AGENT_ATTACHMENT_PREFIX = "/__castle/agent/attachments/";
|
|
5
|
-
export
|
|
6
|
-
export type
|
|
5
|
+
export declare const AGENT_PLAYTEST_PREFIX = "/__castle/agent/playtest/";
|
|
6
|
+
export type AgentBackend = "cursor" | "claude" | "smith";
|
|
7
|
+
export type ClaudeModel = "sonnet" | "opus" | "fable" | "openrouter";
|
|
7
8
|
type TaskStatus = "waiting" | "running" | "blocked" | "done" | "failed" | "interrupted";
|
|
8
9
|
interface TaskRecord {
|
|
9
10
|
id: string;
|
|
@@ -20,12 +21,14 @@ interface TaskRecord {
|
|
|
20
21
|
pid?: number;
|
|
21
22
|
originMessageId?: string;
|
|
22
23
|
files?: string[];
|
|
24
|
+
playtestFrames?: string[];
|
|
23
25
|
resultSummary?: string;
|
|
24
26
|
avatar?: string;
|
|
25
27
|
phase?: string;
|
|
26
28
|
acknowledged?: boolean;
|
|
27
29
|
rejected?: boolean;
|
|
28
30
|
blockedBy?: string[];
|
|
31
|
+
suspectNoChanges?: boolean;
|
|
29
32
|
}
|
|
30
33
|
export interface DepsState {
|
|
31
34
|
kind: "ready" | "waiting" | "blocked";
|
|
@@ -42,5 +45,7 @@ export interface AgentServer {
|
|
|
42
45
|
export declare function createAgentServer(opts: {
|
|
43
46
|
deckDir: string;
|
|
44
47
|
deckLabel: string;
|
|
48
|
+
port?: number;
|
|
49
|
+
restart?: () => void;
|
|
45
50
|
}): AgentServer;
|
|
46
51
|
export {};
|