create-kudzu 0.1.156 → 0.1.157
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 +7 -2
- package/ai.mjs +17 -3
- package/index.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,13 +10,13 @@ cd my-app
|
|
|
10
10
|
npm run dev
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
The generated project is a working showcase on `@kudzujs/core@^0.16.
|
|
13
|
+
The generated project is a working showcase on `@kudzujs/core@^0.16.36` with reusable components, an interactive state example, a zero-JavaScript static route, page metadata, responsive CSS, and `npm run check`. Configuration remains optional until the app needs custom assets, document defaults, navigation, or build hooks.
|
|
14
14
|
|
|
15
15
|
Use `--no-install` to create the files without installing dependencies.
|
|
16
16
|
|
|
17
17
|
## Optional AI authoring guidance
|
|
18
18
|
|
|
19
|
-
`create-kudzu@0.1.
|
|
19
|
+
`create-kudzu@0.1.157` provides optional local AI developer tools with managed check cancellation:
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
22
|
npm create kudzu@latest my-app -- --ai
|
|
@@ -53,6 +53,11 @@ npm run ai -- check --timeout-ms 600000
|
|
|
53
53
|
log excerpt. Failure stays nonzero. The default timeout is five minutes; choose
|
|
54
54
|
an integer from 1 to 1,200,000 ms. Timeout/cancellation terminates the spawned
|
|
55
55
|
process group on Unix or process tree on Windows and reports failure.
|
|
56
|
+
Under the existing `KUDZU_AI_DELIVERY_GROUP=1` managed-runner contract, Unix
|
|
57
|
+
checks inherit their outer group so a hard group cancellation also reaches
|
|
58
|
+
their ordinary descendants. A check-local timeout or interruption uses native
|
|
59
|
+
`ps` PID/parent-PID inspection to stop only that check's descendant snapshot,
|
|
60
|
+
preserving sibling work; inspection errors are reported as failures.
|
|
56
61
|
- Full stdout/stderr are retained in a unique `.kudzu-ai/check-*/output.log`.
|
|
57
62
|
Large logs show the first/last 2,048 bytes with an omission marker; an error may
|
|
58
63
|
be in the omitted middle. Read the full log when needed. Old logs are not deleted
|
package/ai.mjs
CHANGED
|
@@ -41,20 +41,34 @@ export async function check(root, timeoutMs = 300000) {
|
|
|
41
41
|
const directory = await mkdtemp(join(logs, "check-")), path = join(directory, "output.log")
|
|
42
42
|
const log = await open(path, "wx+")
|
|
43
43
|
const start = performance.now()
|
|
44
|
+
const managed = process.env.KUDZU_AI_DELIVERY_GROUP === "1"
|
|
44
45
|
try {
|
|
45
46
|
const result = await new Promise(resolveRun => {
|
|
46
47
|
const child = spawn(process.platform === "win32" ? "npm.cmd" : "npm", ["run", "check"], {
|
|
47
|
-
cwd: root, detached: process.platform !== "win32", shell: process.platform === "win32",
|
|
48
|
+
cwd: root, detached: process.platform !== "win32" && !managed, shell: process.platform === "win32",
|
|
48
49
|
stdio: ["ignore", log.fd, log.fd], env: { ...process.env, FORCE_COLOR: "0", KUDZU_AI_CHECK_ROOT: root },
|
|
49
50
|
})
|
|
50
51
|
let timedOut = false, interrupted = null, error = null
|
|
51
52
|
const terminate = () => {
|
|
52
|
-
if (!child.pid) return
|
|
53
|
+
if (!child.pid || child.exitCode !== null || child.signalCode !== null) return
|
|
53
54
|
if (process.platform === "win32") {
|
|
54
55
|
const killed = spawnSync("taskkill", ["/pid", String(child.pid), "/T", "/F"], { encoding: "utf8" })
|
|
55
56
|
if (killed.status !== 0) error = killed.error?.message ?? killed.stderr ?? "Could not terminate check tree"
|
|
56
57
|
} else {
|
|
57
|
-
|
|
58
|
+
const pids = [managed ? child.pid : -child.pid]
|
|
59
|
+
if (managed) {
|
|
60
|
+
// Keep the outer group alive on this tool's timeout; stop only its ordinary descendants.
|
|
61
|
+
const table = spawnSync("ps", ["-A", "-o", "pid=", "-o", "ppid="], { encoding: "utf8", timeout: 1000, maxBuffer: 1024 * 1024 })
|
|
62
|
+
if (table.status !== 0) error = table.error?.message || table.stderr?.trim() || "Could not inspect managed check descendants"
|
|
63
|
+
else {
|
|
64
|
+
const parents = table.stdout.trim().split("\n").map(line => line.trim().split(/\s+/).map(Number))
|
|
65
|
+
if (parents.some(row => row.length !== 2 || row.some(id => !Number.isSafeInteger(id) || id < 0))) error = "Invalid managed check process table"
|
|
66
|
+
else for (let index = 0; index < pids.length; index++) for (const [pid, parent] of parents) {
|
|
67
|
+
if (parent === pids[index] && pid > 1 && pid !== process.pid && !pids.includes(pid)) pids.push(pid)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
for (const pid of pids.reverse()) try { process.kill(pid, "SIGKILL") } catch (failure) { if (failure.code !== "ESRCH") error = failure.message }
|
|
58
72
|
}
|
|
59
73
|
}
|
|
60
74
|
const onInterrupt = signal => { interrupted = signal; terminate() }
|
package/index.mjs
CHANGED