@kybernesis/create 0.24.2 → 0.24.4
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/exe-claude-route.d.ts +19 -0
- package/dist/exe-claude-route.js +69 -0
- package/dist/upgrade.js +49 -4
- package/package.json +1 -1
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Give every `exeModel({ …, createOpenAI })` call in an agent the Anthropic
|
|
3
|
+
* factory too.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* Claude on the exe gateway is served on its Messages API, not the OpenAI one.
|
|
7
|
+
* Older scaffolds wrote subagents such as the builder with only `createOpenAI`
|
|
8
|
+
* and a Claude default (`anthropic/claude-sonnet-5`). That never had a working
|
|
9
|
+
* route, and since exe 0.17 `exeModel` refuses it at load, so the agent's whole
|
|
10
|
+
* eval suite stops before the first case and an update is rolled back for a
|
|
11
|
+
* file nobody touched. Passing `createAnthropic` as well is harmless for a
|
|
12
|
+
* non-Claude id (exeModel only uses it for `anthropic/…`), so the repair is
|
|
13
|
+
* unconditional for any call that lacks it.
|
|
14
|
+
*
|
|
15
|
+
* Returns the agent-relative paths it changed.
|
|
16
|
+
*/
|
|
17
|
+
export declare function repairExeClaudeRoute(cwd: string): string[];
|
|
18
|
+
/** The source with `createAnthropic` passed to each exeModel call that has only `createOpenAI`, and imported. */
|
|
19
|
+
export declare function withAnthropicFactory(source: string): string;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { existsSync, readdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join, relative } from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* Give every `exeModel({ …, createOpenAI })` call in an agent the Anthropic
|
|
5
|
+
* factory too.
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* Claude on the exe gateway is served on its Messages API, not the OpenAI one.
|
|
9
|
+
* Older scaffolds wrote subagents such as the builder with only `createOpenAI`
|
|
10
|
+
* and a Claude default (`anthropic/claude-sonnet-5`). That never had a working
|
|
11
|
+
* route, and since exe 0.17 `exeModel` refuses it at load, so the agent's whole
|
|
12
|
+
* eval suite stops before the first case and an update is rolled back for a
|
|
13
|
+
* file nobody touched. Passing `createAnthropic` as well is harmless for a
|
|
14
|
+
* non-Claude id (exeModel only uses it for `anthropic/…`), so the repair is
|
|
15
|
+
* unconditional for any call that lacks it.
|
|
16
|
+
*
|
|
17
|
+
* Returns the agent-relative paths it changed.
|
|
18
|
+
*/
|
|
19
|
+
export function repairExeClaudeRoute(cwd) {
|
|
20
|
+
const root = join(cwd, "agent");
|
|
21
|
+
if (!existsSync(root))
|
|
22
|
+
return [];
|
|
23
|
+
const changed = [];
|
|
24
|
+
for (const file of sourceFiles(root)) {
|
|
25
|
+
const source = readFileSync(file, "utf8");
|
|
26
|
+
const next = withAnthropicFactory(source);
|
|
27
|
+
if (next === source)
|
|
28
|
+
continue;
|
|
29
|
+
writeFileSync(file, next);
|
|
30
|
+
changed.push(relative(cwd, file));
|
|
31
|
+
}
|
|
32
|
+
return changed;
|
|
33
|
+
}
|
|
34
|
+
/** The source with `createAnthropic` passed to each exeModel call that has only `createOpenAI`, and imported. */
|
|
35
|
+
export function withAnthropicFactory(source) {
|
|
36
|
+
if (!/\bexeModel\s*\(/.test(source))
|
|
37
|
+
return source;
|
|
38
|
+
let touched = false;
|
|
39
|
+
const next = source.replace(/\bexeModel\s*\(\s*\{([^{}]*)\}\s*\)/g, (call, body) => {
|
|
40
|
+
if (!/\bcreateOpenAI\b/.test(body) || /\bcreateAnthropic\b/.test(body))
|
|
41
|
+
return call;
|
|
42
|
+
touched = true;
|
|
43
|
+
return call.replace(/\bcreateOpenAI\b/, "createOpenAI, createAnthropic");
|
|
44
|
+
});
|
|
45
|
+
if (!touched)
|
|
46
|
+
return source;
|
|
47
|
+
if (/\bimport\s*\{[^}]*\bcreateAnthropic\b[^}]*\}\s*from\s*["']@ai-sdk\/anthropic["']/.test(next))
|
|
48
|
+
return next;
|
|
49
|
+
const openaiImport = /^import\s*\{[^}]*\bcreateOpenAI\b[^}]*\}\s*from\s*["']@ai-sdk\/openai["'];?[^\n]*\n/m.exec(next);
|
|
50
|
+
const line = 'import { createAnthropic } from "@ai-sdk/anthropic";\n';
|
|
51
|
+
if (openaiImport) {
|
|
52
|
+
const at = openaiImport.index + openaiImport[0].length;
|
|
53
|
+
return next.slice(0, at) + line + next.slice(at);
|
|
54
|
+
}
|
|
55
|
+
return line + next;
|
|
56
|
+
}
|
|
57
|
+
function sourceFiles(dir) {
|
|
58
|
+
const out = [];
|
|
59
|
+
for (const entry of readdirSync(dir)) {
|
|
60
|
+
if (entry === "node_modules" || entry.startsWith("."))
|
|
61
|
+
continue;
|
|
62
|
+
const full = join(dir, entry);
|
|
63
|
+
if (statSync(full).isDirectory())
|
|
64
|
+
out.push(...sourceFiles(full));
|
|
65
|
+
else if (/\.(ts|mts|js|mjs)$/.test(entry))
|
|
66
|
+
out.push(full);
|
|
67
|
+
}
|
|
68
|
+
return out;
|
|
69
|
+
}
|
package/dist/upgrade.js
CHANGED
|
@@ -11,6 +11,7 @@ import { dockerPruneCronArtifact } from "./docker-prune-cron.js";
|
|
|
11
11
|
import { newestOnLine } from "./on-line-version.js";
|
|
12
12
|
import { findMatchingAgentServiceUnit, repairManageRestart } from "./systemd.js";
|
|
13
13
|
import { repairTerminalSandboxCleanupHooks } from "./sandbox-cleanup.js";
|
|
14
|
+
import { repairExeClaudeRoute } from "./exe-claude-route.js";
|
|
14
15
|
import { repairOptInTools, repairRemovedDefaultTools as repairRemovedDefaultTools_ } from "./removed-default-tools.js";
|
|
15
16
|
import { EVE_VERSION, bold, capture, dim, green, parseEnv, red, run, yellow } from "./util.js";
|
|
16
17
|
import { inspectEveAgent } from "./agent-limits.js";
|
|
@@ -75,6 +76,25 @@ function repairLocalQueueTimeouts(cwd, deps) {
|
|
|
75
76
|
` ${dim("slower than 30s was redelivered and its steps re-run — the agent answered twice.")}\n` +
|
|
76
77
|
` ${dim("Takes effect on the next server restart.")}\n`);
|
|
77
78
|
}
|
|
79
|
+
/** Route Claude ids through the gateway's Messages API wherever an agent builds an exe model (see exe-claude-route.ts). */
|
|
80
|
+
function repairExeClaudeRoutes(cwd, deps) {
|
|
81
|
+
if (!deps["@kybernesis/exe"])
|
|
82
|
+
return;
|
|
83
|
+
const changed = repairExeClaudeRoute(cwd);
|
|
84
|
+
if (changed.length === 0)
|
|
85
|
+
return;
|
|
86
|
+
if (!deps["@ai-sdk/anthropic"]) {
|
|
87
|
+
const added = commandResult("npm", ["install", "@ai-sdk/anthropic"], cwd);
|
|
88
|
+
if (added.status !== 0) {
|
|
89
|
+
console.log(red(` ✗ could not install @ai-sdk/anthropic for the Claude route:\n${added.stderr.trim()}`));
|
|
90
|
+
process.exitCode = 1;
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
console.log(` ${green("+")} passed createAnthropic to exeModel in ${changed.join(", ")}\n` +
|
|
95
|
+
` ${dim("Claude on the exe gateway is served on its Messages API; with only createOpenAI")}\n` +
|
|
96
|
+
` ${dim("a Claude id has no route, and exe 0.17+ refuses it when the agent loads.")}\n`);
|
|
97
|
+
}
|
|
78
98
|
/**
|
|
79
99
|
* Finish a Buzz install that a version bump alone leaves half-done.
|
|
80
100
|
*
|
|
@@ -582,7 +602,10 @@ function exeJudgeUrl(cwd, env) {
|
|
|
582
602
|
if (!judgeProvider)
|
|
583
603
|
return null;
|
|
584
604
|
const escaped = judgeProvider.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
585
|
-
|
|
605
|
+
// The provider may be made inline (`model: createAnthropic({ … }).evaluationModel(…)`)
|
|
606
|
+
// as well as bound to a name first; both carry the base URL in the same object.
|
|
607
|
+
const inline = /judge\s*:\s*\{[\s\S]*?model\s*:\s*create[A-Za-z]+\s*\(\s*\{([\s\S]*?)\}\s*\)/.exec(source)?.[1];
|
|
608
|
+
const providerBody = inline ?? new RegExp(`(?:const|let)\\s+${escaped}\\s*=\\s*create[A-Za-z]+\\s*\\(\\s*\\{([\\s\\S]*?)\\}\\s*\\)`).exec(source)?.[1];
|
|
586
609
|
if (!providerBody)
|
|
587
610
|
return /EXE_LLM_URL|llm\.int\.exe\.xyz/.test(source) ? undefined : null;
|
|
588
611
|
if (/EXE_LLM_URL/.test(providerBody))
|
|
@@ -915,6 +938,21 @@ export async function upgrade(options = {}) {
|
|
|
915
938
|
console.log(` ${dim(selfVersion.fix)} ${dim("(continuing: --allow-stale)")}\n`);
|
|
916
939
|
}
|
|
917
940
|
reportAgentInputLimit(cwd);
|
|
941
|
+
// An agent already on a newer eve line than this kyb was certified on must
|
|
942
|
+
// be upgraded by that line's kyb: from here every @kybernesis package would
|
|
943
|
+
// be "upgraded" to a build for the older eve.
|
|
944
|
+
const eveNow = installedPackageValue(cwd, "eve", ".version");
|
|
945
|
+
const nowLine = eveNow ? majorMinor(eveNow) : null;
|
|
946
|
+
const ownLine = majorMinor(EVE_VERSION);
|
|
947
|
+
if (nowLine && ownLine && (nowLine[0] > ownLine[0] || (nowLine[0] === ownLine[0] && nowLine[1] > ownLine[1]))) {
|
|
948
|
+
if (options.check)
|
|
949
|
+
printPlan({ ok: false, unresolved: ["eve"], changes: [], resetsConversations: false });
|
|
950
|
+
fail(`This agent runs eve ${eveNow}, a newer line than this kyb is certified for (${EVE_VERSION}). ` +
|
|
951
|
+
`Run the kyb for its line:\n npx --yes --package=@kybernesis/create@eve-${nowLine[0]}.${nowLine[1]} kyb upgrade\n` +
|
|
952
|
+
`Nothing was changed.`);
|
|
953
|
+
return;
|
|
954
|
+
}
|
|
955
|
+
const selfInstalled = "installed" in selfVersion ? selfVersion.installed : undefined;
|
|
918
956
|
const entries = dependencyEntries(pkg);
|
|
919
957
|
const installedVersions = new Map();
|
|
920
958
|
const targetVersions = new Map();
|
|
@@ -933,11 +971,16 @@ export async function upgrade(options = {}) {
|
|
|
933
971
|
// that supports the eve this host will be running — NOT npm's `latest`,
|
|
934
972
|
// which for a per-eve-line package is routinely a build for a different
|
|
935
973
|
// line and installs without complaint.
|
|
974
|
+
// kyb itself declares no eve peer, so the newest published kyb can belong
|
|
975
|
+
// to another eve line. The project carries the kyb doing this upgrade (a
|
|
976
|
+
// stale one renewed itself above), never a newer one.
|
|
936
977
|
const target = name === "eve"
|
|
937
978
|
? EVE_VERSION
|
|
938
|
-
: name
|
|
939
|
-
?
|
|
940
|
-
:
|
|
979
|
+
: name === "@kybernesis/create"
|
|
980
|
+
? selfInstalled && versionLt(installed, selfInstalled) ? selfInstalled : installed
|
|
981
|
+
: name.startsWith("@kybernesis/")
|
|
982
|
+
? newestBuildForEve(name, EVE_VERSION)
|
|
983
|
+
: capture("npm", ["view", name, "version"])?.trim();
|
|
941
984
|
if (!target) {
|
|
942
985
|
console.log(` ${yellow("!")} ${name}: ` +
|
|
943
986
|
(name.startsWith("@kybernesis/")
|
|
@@ -1038,6 +1081,7 @@ export async function upgrade(options = {}) {
|
|
|
1038
1081
|
repairNotifySetup(cwd, deps);
|
|
1039
1082
|
repairReasoningSandboxes(cwd, deps);
|
|
1040
1083
|
repairManageRestart(cwd, deps);
|
|
1084
|
+
repairExeClaudeRoutes(cwd, deps);
|
|
1041
1085
|
return;
|
|
1042
1086
|
}
|
|
1043
1087
|
console.log(bold(`\nInstalling: ${changed.join(", ")}\n`));
|
|
@@ -1129,6 +1173,7 @@ export async function upgrade(options = {}) {
|
|
|
1129
1173
|
repairNotifySetup(cwd, deps);
|
|
1130
1174
|
repairReasoningSandboxes(cwd, deps);
|
|
1131
1175
|
repairManageRestart(cwd, deps);
|
|
1176
|
+
repairExeClaudeRoutes(cwd, deps);
|
|
1132
1177
|
run("npm", ["run", "typecheck"], { cwd });
|
|
1133
1178
|
if (eveChanged) {
|
|
1134
1179
|
const infoOk = run("npx", ["eve", "info"], { cwd, allowFail: true, quiet: true });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kybernesis/create",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.4",
|
|
4
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",
|