@kybernesis/create 0.24.2 → 0.24.3

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.
@@ -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
- const providerBody = new RegExp(`(?:const|let)\\s+${escaped}\\s*=\\s*create[A-Za-z]+\\s*\\(\\s*\\{([\\s\\S]*?)\\}\\s*\\)`).exec(source)?.[1];
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))
@@ -1038,6 +1061,7 @@ export async function upgrade(options = {}) {
1038
1061
  repairNotifySetup(cwd, deps);
1039
1062
  repairReasoningSandboxes(cwd, deps);
1040
1063
  repairManageRestart(cwd, deps);
1064
+ repairExeClaudeRoutes(cwd, deps);
1041
1065
  return;
1042
1066
  }
1043
1067
  console.log(bold(`\nInstalling: ${changed.join(", ")}\n`));
@@ -1129,6 +1153,7 @@ export async function upgrade(options = {}) {
1129
1153
  repairNotifySetup(cwd, deps);
1130
1154
  repairReasoningSandboxes(cwd, deps);
1131
1155
  repairManageRestart(cwd, deps);
1156
+ repairExeClaudeRoutes(cwd, deps);
1132
1157
  run("npm", ["run", "typecheck"], { cwd });
1133
1158
  if (eveChanged) {
1134
1159
  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.2",
3
+ "version": "0.24.3",
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",