@kybernesis/create 0.13.4 → 0.14.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 +6 -0
- package/dist/add.d.ts +6 -0
- package/dist/add.js +32 -1
- package/dist/cli.js +1 -0
- package/dist/credential.js +5 -3
- package/dist/docker-templates.d.ts +46 -0
- package/dist/docker-templates.js +254 -0
- package/dist/doctor.d.ts +27 -0
- package/dist/doctor.js +61 -11
- package/dist/host-artifacts.d.ts +24 -0
- package/dist/host-artifacts.js +57 -0
- package/dist/init.js +15 -9
- package/dist/removed-default-tools.d.ts +29 -0
- package/dist/removed-default-tools.js +86 -0
- package/dist/sandbox-cleanup.d.ts +18 -0
- package/dist/sandbox-cleanup.js +57 -0
- package/dist/systemd.d.ts +41 -0
- package/dist/systemd.js +136 -0
- package/dist/templates.d.ts +12 -0
- package/dist/templates.js +53 -2
- package/dist/upgrade.js +124 -42
- package/dist/util.d.ts +1 -1
- package/dist/util.js +1 -1
- package/package.json +4 -3
- package/skills/fde-engagement/references/playbook.md +3 -3
- package/skills/kybernesis-packages/SKILL.md +5 -2
package/dist/upgrade.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { upsertEnv } from "./envfile.js";
|
|
4
|
+
import { reconcileHostArtifact } from "./host-artifacts.js";
|
|
5
|
+
import { repairManageRestart } from "./systemd.js";
|
|
6
|
+
import { repairTerminalSandboxCleanupHooks } from "./sandbox-cleanup.js";
|
|
7
|
+
import { repairRemovedDefaultTools as repairRemovedDefaultTools_ } from "./removed-default-tools.js";
|
|
4
8
|
import { EVE_VERSION, bold, capture, dim, green, red, run, yellow } from "./util.js";
|
|
5
9
|
/**
|
|
6
10
|
* Which packages to upgrade: every `@kybernesis/*` this agent depends on.
|
|
@@ -179,54 +183,125 @@ function repairBuzzSetup(cwd, deps) {
|
|
|
179
183
|
console.log(` ${dim("Takes effect after the next build and restart.")}\n`);
|
|
180
184
|
}
|
|
181
185
|
}
|
|
186
|
+
/** Quote one argument for the manual shell commands printed after a failed repair. */
|
|
187
|
+
function shellQuote(value) {
|
|
188
|
+
return `'${value.replaceAll("'", `'"'"'`)}'`;
|
|
189
|
+
}
|
|
182
190
|
/**
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
* collects the old ones, and it leaves session CONTAINERS running — a turn that
|
|
188
|
-
* took four minutes can still own a container, and its writable layer, eight
|
|
189
|
-
* days later. Forty stale images accumulated on one agent in a week; another
|
|
190
|
-
* reached 94% full and began failing in ways that looked like anything but a
|
|
191
|
-
* disk problem. Every self-hosted agent hits this; it is a property of the
|
|
192
|
-
* runtime, not of any one deployment.
|
|
193
|
-
*
|
|
194
|
-
* Installed rather than documented, and DAILY rather than weekly, because the
|
|
195
|
-
* accumulation is measured in gigabytes per day on an agent doing real work.
|
|
196
|
-
* The first version of this ran weekly and was already too slow.
|
|
191
|
+
* eve 0.39 removed glob and grep from the default tool set; see
|
|
192
|
+
* removed-default-tools.ts. Runs before typecheck because a stale disable
|
|
193
|
+
* file is a compile error from 0.39 on, and an upgrade must never leave an
|
|
194
|
+
* agent that cannot build.
|
|
197
195
|
*/
|
|
198
|
-
function
|
|
196
|
+
function repairRemovedDefaultTools(cwd) {
|
|
197
|
+
const { removed, optedIn } = repairRemovedDefaultTools_(cwd);
|
|
198
|
+
for (const file of removed) {
|
|
199
|
+
console.log(` ${green("-")} removed ${file} ${dim("(disabled a tool eve no longer provides by default; a compile error from eve 0.39)")}`);
|
|
200
|
+
}
|
|
201
|
+
for (const file of optedIn) {
|
|
202
|
+
console.log(` ${green("+")} wrote ${file} ${dim("(keeps the tool this scope had on eve 0.38)")}`);
|
|
203
|
+
}
|
|
204
|
+
if (removed.length || optedIn.length)
|
|
205
|
+
console.log();
|
|
206
|
+
}
|
|
207
|
+
function repairSandboxCleanupHooks(cwd, deps) {
|
|
199
208
|
if (!deps["@kybernesis/exe"])
|
|
200
209
|
return;
|
|
201
|
-
|
|
210
|
+
const added = repairTerminalSandboxCleanupHooks(cwd);
|
|
211
|
+
if (added.length === 0)
|
|
202
212
|
return;
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
213
|
+
console.log(` ${green("+")} installed terminal sandbox cleanup for ${added.length} agent scope(s) ` +
|
|
214
|
+
`${dim("(completed and failed sessions only)")}\n`);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Keep package-owned host files synchronized with the package that installed them.
|
|
218
|
+
*
|
|
219
|
+
* Existing artifacts are compared even when the capability they support is
|
|
220
|
+
* temporarily unavailable. Missing cron installation remains Docker-gated, and
|
|
221
|
+
* a missing systemd unit remains an explicit operator choice.
|
|
222
|
+
*/
|
|
223
|
+
function repairHostArtifacts(cwd, deps) {
|
|
224
|
+
if (!deps["@kybernesis/exe"])
|
|
208
225
|
return;
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
const
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
226
|
+
const scripts = join(cwd, "node_modules/@kybernesis/exe/scripts");
|
|
227
|
+
const pruneSource = join(scripts, "docker-prune.sh");
|
|
228
|
+
const pruneTarget = "/etc/cron.daily/kyb-docker-prune";
|
|
229
|
+
const hasDocker = capture("sh", ["-c", "command -v docker >/dev/null && echo yes"])?.trim() === "yes";
|
|
230
|
+
if (existsSync(pruneSource)) {
|
|
231
|
+
const pruneResult = reconcileHostArtifact({
|
|
232
|
+
targetPath: pruneTarget,
|
|
233
|
+
desiredContent: readFileSync(pruneSource),
|
|
234
|
+
expectedMode: 0o755,
|
|
235
|
+
installIfMissing: hasDocker,
|
|
236
|
+
owner: "@kybernesis/exe/scripts/docker-prune.sh",
|
|
237
|
+
update: () => run("sudo", ["-n", "install", "-m", "0755", pruneSource, pruneTarget], {
|
|
238
|
+
cwd,
|
|
239
|
+
allowFail: true,
|
|
240
|
+
quiet: true,
|
|
241
|
+
}),
|
|
242
|
+
manualCommand: `sudo install -m 0755 ${shellQuote(pruneSource)} ${pruneTarget}`,
|
|
243
|
+
});
|
|
244
|
+
if ((pruneResult === "current" || pruneResult === "updated") && existsSync("/etc/cron.weekly/docker-prune")) {
|
|
245
|
+
const removed = run("sudo", ["-n", "rm", "-f", "/etc/cron.weekly/docker-prune"], {
|
|
246
|
+
cwd,
|
|
247
|
+
allowFail: true,
|
|
248
|
+
quiet: true,
|
|
249
|
+
});
|
|
250
|
+
if (!removed) {
|
|
251
|
+
console.log(` ${yellow("!")} the daily docker reclaim is current, but the legacy weekly job remains. Run:\n` +
|
|
252
|
+
` ${dim("sudo rm -f /etc/cron.weekly/docker-prune")}`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
224
255
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
256
|
+
const serviceScript = join(scripts, "install-service.sh");
|
|
257
|
+
if (!existsSync(serviceScript))
|
|
258
|
+
return;
|
|
259
|
+
const unitTarget = capture("bash", [serviceScript, "--unit-path"], cwd)?.trim();
|
|
260
|
+
const unitContent = capture("bash", [serviceScript, "--print-unit"], cwd);
|
|
261
|
+
const marker = capture("bash", [serviceScript, "--managed-marker"], cwd)?.trim();
|
|
262
|
+
if (!unitTarget || unitContent === null || !marker)
|
|
263
|
+
return;
|
|
264
|
+
/**
|
|
265
|
+
* Only a unit this package wrote is this package's to rewrite.
|
|
266
|
+
*
|
|
267
|
+
* Every host from before the installer existed has a hand-written unit —
|
|
268
|
+
* some with Environment= lines the renderer knows nothing about. Reconciling
|
|
269
|
+
* those would report "drifted (content)" and replace them, and a warning
|
|
270
|
+
* that scrolls past in the middle of an upgrade is not consent. The marker
|
|
271
|
+
* is the first line of every generated unit; a unit without it is reported
|
|
272
|
+
* and left exactly as it is.
|
|
273
|
+
*/
|
|
274
|
+
if (existsSync(unitTarget)) {
|
|
275
|
+
let installed;
|
|
276
|
+
try {
|
|
277
|
+
installed = readFileSync(unitTarget, "utf8");
|
|
278
|
+
}
|
|
279
|
+
catch (error) {
|
|
280
|
+
console.log(` ${yellow("!")} could not read ${unitTarget} to check whether it is package-managed ` +
|
|
281
|
+
`(${error.message}); leaving it alone.`);
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
if (!installed.includes(marker)) {
|
|
285
|
+
console.log(` ${yellow("!")} ${unitTarget} was not written by @kybernesis/exe, so it was left as is.\n` +
|
|
286
|
+
` To adopt the package-managed unit (the current file is kept at ${unitTarget}.bak):\n` +
|
|
287
|
+
` ${dim(`bash ${shellQuote(serviceScript)} --refresh-unit`)}\n` +
|
|
288
|
+
` Host-specific settings belong in a drop-in: ${dim(`sudo systemctl edit <name>-agent`)}`);
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
229
291
|
}
|
|
292
|
+
reconcileHostArtifact({
|
|
293
|
+
targetPath: unitTarget,
|
|
294
|
+
desiredContent: Buffer.from(unitContent),
|
|
295
|
+
expectedMode: 0o644,
|
|
296
|
+
installIfMissing: false,
|
|
297
|
+
owner: "@kybernesis/exe/scripts/install-service.sh",
|
|
298
|
+
update: () => run("env", ["KYB_NONINTERACTIVE=1", "bash", serviceScript, "--refresh-unit"], {
|
|
299
|
+
cwd,
|
|
300
|
+
allowFail: true,
|
|
301
|
+
quiet: true,
|
|
302
|
+
}),
|
|
303
|
+
manualCommand: `bash ${shellQuote(serviceScript)} --refresh-unit`,
|
|
304
|
+
});
|
|
230
305
|
}
|
|
231
306
|
export async function upgrade(skipEval) {
|
|
232
307
|
const cwd = process.cwd();
|
|
@@ -286,6 +361,7 @@ export async function upgrade(skipEval) {
|
|
|
286
361
|
console.log(`\n${yellow(`Checked what could be read. ${unresolved.length} package(s) could not be ` +
|
|
287
362
|
`resolved, so this is not a clean bill of health.`)}\n` +
|
|
288
363
|
` ${dim("Usually: dependencies are not installed here. Run npm install, then kyb upgrade.")}\n`);
|
|
364
|
+
repairManageRestart(cwd, deps);
|
|
289
365
|
return;
|
|
290
366
|
}
|
|
291
367
|
if (toUpgrade.length === 0) {
|
|
@@ -293,7 +369,10 @@ export async function upgrade(skipEval) {
|
|
|
293
369
|
// Still repair: being on the right versions is not the same as being set
|
|
294
370
|
// up. An agent can sit at latest for weeks with a capability switched off.
|
|
295
371
|
repairBuzzSetup(cwd, deps);
|
|
296
|
-
|
|
372
|
+
repairRemovedDefaultTools(cwd);
|
|
373
|
+
repairSandboxCleanupHooks(cwd, deps);
|
|
374
|
+
repairHostArtifacts(cwd, deps);
|
|
375
|
+
repairManageRestart(cwd, deps);
|
|
297
376
|
return;
|
|
298
377
|
}
|
|
299
378
|
console.log(bold(`\nInstalling: ${toUpgrade.join(", ")}\n`));
|
|
@@ -308,7 +387,10 @@ export async function upgrade(skipEval) {
|
|
|
308
387
|
* bug that hides itself, because by then it looks like it always worked.
|
|
309
388
|
*/
|
|
310
389
|
repairBuzzSetup(cwd, deps);
|
|
311
|
-
|
|
390
|
+
repairRemovedDefaultTools(cwd);
|
|
391
|
+
repairSandboxCleanupHooks(cwd, deps);
|
|
392
|
+
repairHostArtifacts(cwd, deps);
|
|
393
|
+
repairManageRestart(cwd, deps);
|
|
312
394
|
run("npm", ["run", "typecheck"], { cwd });
|
|
313
395
|
if (eveChanged) {
|
|
314
396
|
// A framework bump must also pass discovery/compile, not just types.
|
package/dist/util.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const EVE_VERSION = "0.
|
|
1
|
+
export declare const EVE_VERSION = "0.49.0";
|
|
2
2
|
export declare const REGISTRY_URL = "https://registry.kybernesis.ai/r/{name}.json";
|
|
3
3
|
export declare const DEFAULT_ISSUER = "https://agent.kybernesis.ai";
|
|
4
4
|
export declare const green: (s: string) => string;
|
package/dist/util.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
2
|
import { createInterface } from "node:readline/promises";
|
|
3
|
-
export const EVE_VERSION = "0.
|
|
3
|
+
export const EVE_VERSION = "0.49.0";
|
|
4
4
|
export const REGISTRY_URL = "https://registry.kybernesis.ai/r/{name}.json";
|
|
5
5
|
export const DEFAULT_ISSUER = "https://agent.kybernesis.ai";
|
|
6
6
|
const TTY = process.stdout.isTTY === true;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kybernesis/create",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "The Kybernesis agent scaffolder and FDE toolkit: one command to a governed, remembering, multiplayer, self-testing eve agent
|
|
3
|
+
"version": "0.14.0",
|
|
4
|
+
"description": "The Kybernesis agent scaffolder and FDE toolkit: one command to a governed, remembering, multiplayer, self-testing eve agent \u2014 plus doctor and upgrade.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"homepage": "https://kybernesis.ai",
|
|
@@ -33,7 +33,8 @@
|
|
|
33
33
|
"build": "tsc -p tsconfig.build.json",
|
|
34
34
|
"prepack": "tsc -p tsconfig.build.json",
|
|
35
35
|
"typecheck": "tsc --noEmit",
|
|
36
|
-
"prepublishOnly": "node ../../scripts/prepublish.mjs"
|
|
36
|
+
"prepublishOnly": "node ../../scripts/prepublish.mjs",
|
|
37
|
+
"test": "node --test \"test/**/*.test.mjs\""
|
|
37
38
|
},
|
|
38
39
|
"devDependencies": {
|
|
39
40
|
"@types/node": "24.x",
|
|
@@ -188,7 +188,7 @@ something. Chase them a week out — an unprovisioned Vercel team on Day 1 costs
|
|
|
188
188
|
`@kybernesis/arcana@0.1.1`, `@kybernesis/enterprise@0.1.2`,
|
|
189
189
|
`@kybernesis/multiplayer@0.1.0`, `@kybernesis/evals@0.2.1`,
|
|
190
190
|
`@kybernesis/create@0.1.4`, `@kybernesis/engineer@0.2.0`, and
|
|
191
|
-
`eve@0.
|
|
191
|
+
`eve@0.49.0` (the Kybernesis-certified version). All public on npm;
|
|
192
192
|
`kyb doctor` checks the wiring.
|
|
193
193
|
|
|
194
194
|
---
|
|
@@ -354,8 +354,8 @@ npx eve registry view @kybernesis/arcana
|
|
|
354
354
|
### 3.4 Pin your versions
|
|
355
355
|
|
|
356
356
|
Before you install anything else, decide and record the versions this engagement pins.
|
|
357
|
-
Put them in the repo README. Pin `eve@0.
|
|
358
|
-
(certification run 2026-
|
|
357
|
+
Put them in the repo README. Pin `eve@0.49.0` — the **Kybernesis-certified** version
|
|
358
|
+
(certification run 2026-09-01: full suite green; one schedule API change, see HANDOFF). Never pin blind
|
|
359
359
|
npm-latest; `kyb upgrade` carries a client to the certified pin behind their own eval
|
|
360
360
|
gate, and that upgrade is a **deliberate, eval-gated step**, never something that
|
|
361
361
|
happens by accident mid-pilot.
|
|
@@ -10,7 +10,10 @@ Twelve packages, npm-public under `@kybernesis`, Apache-2.0, monorepo
|
|
|
10
10
|
then `eve add @kybernesis/<item>`). Each covers one axis:
|
|
11
11
|
|
|
12
12
|
- **arcana** — memory. Extension mount `arcana({ apiKey, workspace,
|
|
13
|
-
resolveWorkspace? })
|
|
13
|
+
resolveWorkspace? })`; from eve 0.49 also a memory PROVIDER:
|
|
14
|
+
`arcanaMemory()` from `@kybernesis/arcana/memory` in an `agent/memory/*.ts`
|
|
15
|
+
slot (`kyb add memory` writes it) — recall before every turn, skipped
|
|
16
|
+
under 4 words, capture off by default, tools left to the extension. Workspace-scoped `kb_` keys (403 outside their
|
|
14
17
|
workspace — one key per brain). `resolveWorkspace` only from VERIFIED
|
|
15
18
|
session context, never model output, and only key-reachable workspaces.
|
|
16
19
|
Subagents: local extension mount (`subagents/<id>/extensions/arcana.ts`,
|
|
@@ -127,7 +130,7 @@ then `eve add @kybernesis/<item>`). Each covers one axis:
|
|
|
127
130
|
asterisks onto the URL in Slack and breaks it. Coach agents in prose, not
|
|
128
131
|
shell (WAFs eat shell-syntax Slack messages).
|
|
129
132
|
- **ESM packaging**: relative imports need `.js` extensions (tsc doesn't
|
|
130
|
-
rewrite); eve is a peer dep with an explicit range (`>=0.
|
|
133
|
+
rewrite); eve is a peer dep with an explicit range (`>=0.49.0 <0.50.0`),
|
|
131
134
|
pinned exactly in devDeps.
|
|
132
135
|
- **Eval fixtures are hardened on purpose** — in-test nonces (eve caches
|
|
133
136
|
compiled eval modules), per-run unique keys (workspaces accumulate),
|