castle-web-cli 0.4.27 → 0.4.29
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.js +1 -1
- package/dist/init.js +1 -1
- package/kits/basic-2d/editors/App.jsx +31 -6
- package/package.json +1 -1
package/dist/agent-prompts.js
CHANGED
|
@@ -13,7 +13,7 @@ What a deck is: a normal web project served by vite -- index.html plus plain JS/
|
|
|
13
13
|
Hard rules:
|
|
14
14
|
- You NEVER edit files or run state-changing commands. All building and fixing happens through background task agents -- always hand the longer work to them.
|
|
15
15
|
- You are the fast lane: get to your final reply as quickly as possible. When the user reports something broken, do NOT dig into the code to diagnose it first -- spawn a task whose job is to investigate AND fix it. Only read deck files when your reply itself needs them (answering a question about the deck, grounding a claim -- never make things up); never read as pre-work before spawning a task.
|
|
16
|
-
-
|
|
16
|
+
- Break the user's request into separately testable, parallelizable chunks -- but chunk by what can actually be TESTED alone, never by entity. Mechanics that only work through their interaction are ONE task: paddle + ball + bricks + their collisions is one breakout core, not three tasks shipping untestable pieces. Get the best initial testable chunk -- the smallest thing the user can genuinely play -- then parallelize the truly independent layers on top (separate features, art, levels, polish).
|
|
17
17
|
- Write task prompts for speed: ask each task for the quickest viable, testable change that still delivers a meaningful step up (one or a few features, pieces of art, etc.). Only tell a task to take its time and dive deep when the user specifically asked for that.
|
|
18
18
|
- To spawn a background task, include a fenced block in your reply:
|
|
19
19
|
|
package/dist/init.js
CHANGED
|
@@ -35,7 +35,7 @@ const DEFAULT_KIT = 'basic-2d';
|
|
|
35
35
|
// Registry version of castle-web-sdk to inject when scaffolding from a
|
|
36
36
|
// globally-installed castle-web (not from inside the workspace). Bumped
|
|
37
37
|
// alongside cli/sdk version bumps.
|
|
38
|
-
const PUBLISHED_SDK_VERSION = '0.4.
|
|
38
|
+
const PUBLISHED_SDK_VERSION = '0.4.4';
|
|
39
39
|
// Never copied into a fresh deck: build/dependency junk, and castle.json (a
|
|
40
40
|
// fresh deck has no deckId until its first save-deck).
|
|
41
41
|
const KIT_COPY_EXCLUDE = new Set(['node_modules', '.castle', 'dist', '.git', 'castle.json']);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useEffect, useRef, useState } from 'react';
|
|
2
|
-
import { writeFile } from 'castle-web-sdk';
|
|
2
|
+
import { onBeforeRestart, writeFile } from 'castle-web-sdk';
|
|
3
3
|
import {
|
|
4
4
|
flatFileOrder,
|
|
5
5
|
formatJson,
|
|
@@ -20,6 +20,7 @@ export function App() {
|
|
|
20
20
|
const [multiSelectMode, setMultiSelectMode] = useState(false);
|
|
21
21
|
const saveTimersRef = useRef({});
|
|
22
22
|
const saveVersionsRef = useRef({});
|
|
23
|
+
const pendingWritesRef = useRef({});
|
|
23
24
|
const drawings = {};
|
|
24
25
|
for (const [path, text] of Object.entries(files)) {
|
|
25
26
|
if (!path.endsWith('.drawing')) continue;
|
|
@@ -34,20 +35,44 @@ export function App() {
|
|
|
34
35
|
}));
|
|
35
36
|
scheduleFileWrite(path, nextText);
|
|
36
37
|
}
|
|
38
|
+
function commitFileWrite(path, text, version) {
|
|
39
|
+
return writeFile(path, text)
|
|
40
|
+
.then(() => {
|
|
41
|
+
if (saveVersionsRef.current[path] === version && pendingWritesRef.current[path] === text) {
|
|
42
|
+
delete pendingWritesRef.current[path];
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
.catch((error) => {
|
|
46
|
+
if (saveVersionsRef.current[path] !== version) return;
|
|
47
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
48
|
+
console.error(`Failed to save ${path}: ${message}`);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
37
51
|
function scheduleFileWrite(path, nextText) {
|
|
38
52
|
const version = (saveVersionsRef.current[path] ?? 0) + 1;
|
|
39
53
|
saveVersionsRef.current[path] = version;
|
|
54
|
+
pendingWritesRef.current[path] = nextText;
|
|
40
55
|
const existingTimer = saveTimersRef.current[path];
|
|
41
56
|
if (existingTimer) window.clearTimeout(existingTimer);
|
|
42
57
|
saveTimersRef.current[path] = window.setTimeout(() => {
|
|
43
58
|
delete saveTimersRef.current[path];
|
|
44
|
-
|
|
45
|
-
if (saveVersionsRef.current[path] !== version) return;
|
|
46
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
47
|
-
console.error(`Failed to save ${path}: ${message}`);
|
|
48
|
-
});
|
|
59
|
+
void commitFileWrite(path, nextText, version);
|
|
49
60
|
}, 1500);
|
|
50
61
|
}
|
|
62
|
+
// A reload (npm run restart) can land mid-debounce; flush unsaved edits to
|
|
63
|
+
// disk before the page reloads so in-progress editor work isn't lost.
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
return onBeforeRestart(async () => {
|
|
66
|
+
for (const timer of Object.values(saveTimersRef.current)) window.clearTimeout(timer);
|
|
67
|
+
saveTimersRef.current = {};
|
|
68
|
+
const pending = Object.entries(pendingWritesRef.current);
|
|
69
|
+
await Promise.all(
|
|
70
|
+
pending.map(([path, text]) =>
|
|
71
|
+
commitFileWrite(path, text, saveVersionsRef.current[path] ?? 0)
|
|
72
|
+
)
|
|
73
|
+
);
|
|
74
|
+
});
|
|
75
|
+
}, []);
|
|
51
76
|
const kind = getFileKind(selectedPath);
|
|
52
77
|
const text = files[selectedPath] ?? '';
|
|
53
78
|
function selectFile(path) {
|