agenr 2.0.0 → 2.1.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/dist/cli.js CHANGED
@@ -31,7 +31,7 @@ import {
31
31
  tokenizeGroundingText,
32
32
  validateEntriesWithIndexes,
33
33
  validateSupersessionRules
34
- } from "./chunk-XD3446YW.js";
34
+ } from "./chunk-DGV6D6Q3.js";
35
35
  import {
36
36
  DEFAULT_CLAIM_EXTRACTION_CONCURRENCY,
37
37
  DEFAULT_SURGEON_CONTEXT_LIMIT,
@@ -45,6 +45,7 @@ import {
45
45
  ENTRY_TYPES,
46
46
  EXPIRY_LEVELS,
47
47
  applyClaimKeyLifecycle,
48
+ attachCrossEncoderPort,
48
49
  authMethodToProvider,
49
50
  buildActiveEntryClause,
50
51
  buildClaimKeyLifecycleAuditDetails,
@@ -60,17 +61,19 @@ import {
60
61
  configFileExists,
61
62
  createDatabase,
62
63
  createEmbeddingClient,
64
+ createLlmClient,
65
+ createOpenAICrossEncoder,
63
66
  createRecallAdapter,
64
67
  deserializeTags,
65
68
  getAuthMethodDefinition,
66
69
  getEntry,
67
70
  getLastBulkIngestAt,
68
71
  insertEntry,
69
- isAgenrAuthMethod,
70
72
  mapEntryRow,
71
73
  mergeExplicitClaimKeyMetadata,
72
74
  normalizeManualClaimKeyUpdate,
73
75
  parseAndNormalizeProcedureYaml,
76
+ probeLlmCredentials,
74
77
  projectClaimCentricRecallEntry,
75
78
  readBoolean,
76
79
  readConfig,
@@ -82,16 +85,20 @@ import {
82
85
  requireClaimSupportMode,
83
86
  resolveClaimExtractionConfig,
84
87
  resolveConfigPath,
88
+ resolveCrossEncoderApiKey,
85
89
  resolveDbPath,
86
90
  resolveEmbeddingApiKey,
87
91
  resolveEmbeddingModel,
92
+ resolveLlmApiKey,
93
+ resolveLlmCredentials,
94
+ resolveModel,
88
95
  retireEntry,
89
96
  supersedeEntry,
90
97
  toAgenrConfigInput,
91
98
  updateEntry,
92
99
  validateTemporalValidityRange,
93
100
  writeConfig
94
- } from "./chunk-Y2BC7RCE.js";
101
+ } from "./chunk-7TDALVPY.js";
95
102
  import {
96
103
  compactClaimKey,
97
104
  describeClaimKeyNormalizationFailure,
@@ -102,7 +109,7 @@ import {
102
109
  normalizeClaimKeySegment,
103
110
  recall,
104
111
  resolveClaimSlotPolicy
105
- } from "./chunk-MEHOGUZE.js";
112
+ } from "./chunk-6T5RXGIR.js";
106
113
 
107
114
  // src/cli/main.ts
108
115
  import { Command } from "commander";
@@ -235,7 +242,7 @@ function formatUnknownError(error) {
235
242
  }
236
243
 
237
244
  // src/cli/commands/ingest.ts
238
- import path10 from "path";
245
+ import path9 from "path";
239
246
  import * as clack4 from "@clack/prompts";
240
247
 
241
248
  // src/core/ingestion/parser.ts
@@ -2236,378 +2243,9 @@ function matchesTranscriptFileName(fileName) {
2236
2243
  return GENERIC_TRANSCRIPT_FILE_PATTERN.test(fileName.trim());
2237
2244
  }
2238
2245
 
2239
- // src/adapters/llm.ts
2240
- import { createHash as createHash2 } from "crypto";
2241
- import fs3 from "fs";
2242
- import os from "os";
2243
- import path4 from "path";
2244
- import { createRequire as createRequire2 } from "module";
2245
- import { completeSimple, getEnvApiKey, getModel } from "@mariozechner/pi-ai";
2246
- var DEFAULT_REASONING = "medium";
2247
- var require3 = createRequire2(import.meta.url);
2248
- var getModelWithStrings = getModel;
2249
- function probeLlmCredentials(params) {
2250
- const candidate = resolveCredentialCandidate(params);
2251
- if (!candidate) {
2252
- return {
2253
- available: false,
2254
- guidance: credentialSetupGuidance(params.auth)
2255
- };
2256
- }
2257
- return {
2258
- available: true,
2259
- source: candidate.source,
2260
- guidance: "Credentials available.",
2261
- credentials: {
2262
- apiKey: candidate.token,
2263
- source: candidate.source,
2264
- auth: params.auth
2265
- }
2266
- };
2267
- }
2268
- function resolveAuthCredentials(params) {
2269
- const probe = probeLlmCredentials(params);
2270
- if (!probe.available || !probe.credentials) {
2271
- throw new Error(probe.guidance);
2272
- }
2273
- return probe.credentials;
2274
- }
2275
- function createLlmClient(provider, modelId, options = {}) {
2276
- const model = getModelWithStrings(provider, modelId);
2277
- const metadata = {
2278
- model,
2279
- contextWindowTokens: model.contextWindow,
2280
- maxOutputTokens: model.maxTokens,
2281
- supportsReasoning: model.reasoning,
2282
- usage: createEmptyUsageStats2()
2283
- };
2284
- const resolvedApiKey = normalizeOptionalString2(options.apiKey);
2285
- const requestCompletion = async (systemPrompt, userMessage) => {
2286
- const response = await completeSimple(
2287
- model,
2288
- {
2289
- systemPrompt,
2290
- messages: [
2291
- {
2292
- role: "user",
2293
- content: userMessage,
2294
- timestamp: Date.now()
2295
- }
2296
- ]
2297
- },
2298
- {
2299
- apiKey: resolvedApiKey,
2300
- reasoning: metadata.supportsReasoning ? options.reasoning ?? DEFAULT_REASONING : void 0
2301
- }
2302
- );
2303
- accumulateUsage(metadata.usage, response.usage);
2304
- if (response.stopReason === "error") {
2305
- throw new Error(response.errorMessage ?? `LLM completion failed for ${provider}/${modelId}.`);
2306
- }
2307
- return response;
2308
- };
2309
- const complete = async (systemPrompt, userMessage) => {
2310
- const response = await requestCompletion(systemPrompt, userMessage);
2311
- return extractText(response);
2312
- };
2313
- return {
2314
- metadata,
2315
- complete,
2316
- completeJson: async (systemPrompt, userMessage) => {
2317
- const response = await requestCompletion(systemPrompt, userMessage);
2318
- const text2 = extractText(response);
2319
- return JSON.parse(stripCodeFence3(text2));
2320
- }
2321
- };
2322
- }
2323
- function resolveModel(config, stage) {
2324
- const override = stage === "extraction" ? config?.extractionModel : stage === "dedup" ? config?.dedupModel : stage === "episode" ? config?.episodeModel : config?.claimExtraction?.model ?? config?.extractionModel;
2325
- return {
2326
- provider: normalizeOptionalString2(override?.provider) ?? normalizeOptionalString2(config?.provider) ?? "openai",
2327
- modelId: normalizeOptionalString2(override?.model) ?? normalizeOptionalString2(config?.model) ?? defaultModelForStage(stage)
2328
- };
2329
- }
2330
- function resolveLlmCredentials(config, provider, env = process.env) {
2331
- const normalizedProvider = normalizeOptionalString2(provider);
2332
- if (!normalizedProvider) {
2333
- throw new Error("Provider is required to resolve LLM credentials.");
2334
- }
2335
- const auth = normalizeAuthMethod(config?.auth);
2336
- if (auth && authMethodToProvider(auth) === normalizedProvider) {
2337
- return resolveAuthCredentials({
2338
- auth,
2339
- storedCredentials: config?.credentials,
2340
- env
2341
- });
2342
- }
2343
- const fallback = resolveProviderCredentialCandidate(config, normalizedProvider, env);
2344
- if (fallback) {
2345
- return {
2346
- apiKey: fallback.token,
2347
- source: fallback.source
2348
- };
2349
- }
2350
- if (normalizedProvider === "openai-codex") {
2351
- throw new Error("No OpenAI subscription credential found. Run `codex auth` or configure `auth` as `openai-api-key`.");
2352
- }
2353
- const exampleEnv = normalizedProvider === "anthropic" ? "ANTHROPIC_API_KEY" : "OPENAI_API_KEY";
2354
- throw new Error(`No credential found for provider "${normalizedProvider}". Set the appropriate auth method in config or provide ${exampleEnv}.`);
2355
- }
2356
- function resolveLlmApiKey(config, provider, env = process.env) {
2357
- return resolveLlmCredentials(config, provider, env).apiKey;
2358
- }
2359
- function stripCodeFence3(text2) {
2360
- const trimmed = text2.trim();
2361
- const match = /^```(?:json)?\s*([\s\S]+?)\s*```$/i.exec(trimmed);
2362
- return match?.[1]?.trim() ?? trimmed;
2363
- }
2364
- function defaultModelForStage(stage) {
2365
- switch (stage) {
2366
- case "extraction":
2367
- case "episode":
2368
- case "claim":
2369
- return "gpt-5.4-mini";
2370
- case "dedup":
2371
- return "gpt-5.4-nano";
2372
- }
2373
- }
2374
- function normalizeOptionalString2(value) {
2375
- const trimmed = value?.trim();
2376
- return trimmed && trimmed.length > 0 ? trimmed : void 0;
2377
- }
2378
- function normalizeAuthMethod(value) {
2379
- const normalized = normalizeOptionalString2(value);
2380
- return normalized && isAgenrAuthMethod(normalized) ? normalized : void 0;
2381
- }
2382
- function safeReadJson(filePath) {
2383
- try {
2384
- const raw = fs3.readFileSync(filePath, "utf8");
2385
- return JSON.parse(raw);
2386
- } catch {
2387
- return null;
2388
- }
2389
- }
2390
- function resolveHomeDir(env) {
2391
- const home = normalizeOptionalString2(env.HOME);
2392
- return home ? resolveUserPath(home) : os.homedir();
2393
- }
2394
- function resolveCodexHome(env) {
2395
- const configured = normalizeOptionalString2(env.CODEX_HOME) ?? "~/.codex";
2396
- const resolved = resolveUserPath(configured);
2397
- try {
2398
- return fs3.realpathSync.native(resolved);
2399
- } catch {
2400
- return resolved;
2401
- }
2402
- }
2403
- function resolveUserPath(value) {
2404
- const trimmed = value.trim();
2405
- if (trimmed === "~") {
2406
- return os.homedir();
2407
- }
2408
- if (trimmed.startsWith("~/")) {
2409
- return path4.join(os.homedir(), trimmed.slice(2));
2410
- }
2411
- if (trimmed.startsWith("~\\")) {
2412
- return path4.join(os.homedir(), trimmed.slice(2));
2413
- }
2414
- return path4.resolve(trimmed);
2415
- }
2416
- function parseCodexFromFile(env) {
2417
- const authPath = path4.join(resolveCodexHome(env), "auth.json");
2418
- const parsed = safeReadJson(authPath);
2419
- if (!parsed || typeof parsed !== "object") {
2420
- return null;
2421
- }
2422
- const record = parsed;
2423
- const tokens = record.tokens;
2424
- const accessToken = tokens?.access_token;
2425
- if (typeof accessToken !== "string" || !accessToken.trim()) {
2426
- return null;
2427
- }
2428
- return {
2429
- token: accessToken.trim(),
2430
- source: `file:${authPath}`
2431
- };
2432
- }
2433
- function resolveCodexKeychainAccount(env) {
2434
- const hash = createHash2("sha256").update(resolveCodexHome(env)).digest("hex");
2435
- return `cli|${hash.slice(0, 16)}`;
2436
- }
2437
- function parseCodexFromKeychain(env) {
2438
- if (process.platform !== "darwin") {
2439
- return null;
2440
- }
2441
- try {
2442
- const account = resolveCodexKeychainAccount(env);
2443
- const { execSync } = require3("node:child_process");
2444
- const raw = execSync(`security find-generic-password -s "Codex Auth" -a "${account}" -w`, {
2445
- encoding: "utf8",
2446
- stdio: ["pipe", "pipe", "pipe"],
2447
- timeout: 5e3
2448
- }).trim();
2449
- const parsed = JSON.parse(raw);
2450
- const tokens = parsed.tokens;
2451
- const accessToken = tokens?.access_token;
2452
- if (typeof accessToken !== "string" || !accessToken.trim()) {
2453
- return null;
2454
- }
2455
- return {
2456
- token: accessToken.trim(),
2457
- source: "keychain:Codex Auth"
2458
- };
2459
- } catch {
2460
- return null;
2461
- }
2462
- }
2463
- function parseClaudeCredentialRecord(parsed, source) {
2464
- if (!parsed || typeof parsed !== "object") {
2465
- return null;
2466
- }
2467
- const record = parsed;
2468
- const claudeOauth = record.claudeAiOauth;
2469
- const accessToken = claudeOauth?.accessToken;
2470
- if (typeof accessToken !== "string" || !accessToken.trim()) {
2471
- return null;
2472
- }
2473
- return {
2474
- token: accessToken.trim(),
2475
- source
2476
- };
2477
- }
2478
- function parseClaudeFromFiles(env) {
2479
- const homeDir = resolveHomeDir(env);
2480
- const candidates = [path4.join(homeDir, ".claude", ".credentials.json"), path4.join(homeDir, ".claude", "credentials.json")];
2481
- for (const candidate of candidates) {
2482
- const parsed = safeReadJson(candidate);
2483
- const resolved = parseClaudeCredentialRecord(parsed, `file:${candidate}`);
2484
- if (resolved) {
2485
- return resolved;
2486
- }
2487
- }
2488
- return null;
2489
- }
2490
- function parseClaudeFromKeychain() {
2491
- if (process.platform !== "darwin") {
2492
- return null;
2493
- }
2494
- try {
2495
- const { execSync } = require3("node:child_process");
2496
- const raw = execSync('security find-generic-password -s "Claude Code-credentials" -w', {
2497
- encoding: "utf8",
2498
- stdio: ["pipe", "pipe", "pipe"],
2499
- timeout: 5e3
2500
- }).trim();
2501
- return parseClaudeCredentialRecord(JSON.parse(raw), "keychain:Claude Code-credentials");
2502
- } catch {
2503
- return null;
2504
- }
2505
- }
2506
- function candidateFromToken(token, source) {
2507
- const normalized = normalizeOptionalString2(token);
2508
- if (!normalized) {
2509
- return null;
2510
- }
2511
- return {
2512
- token: normalized,
2513
- source
2514
- };
2515
- }
2516
- function resolveOpenAIApiKeyCandidate(storedCredentials, env) {
2517
- return candidateFromToken(env.OPENAI_API_KEY, "env:OPENAI_API_KEY") ?? candidateFromToken(storedCredentials?.openaiApiKey, "config:credentials.openaiApiKey");
2518
- }
2519
- function resolveAnthropicApiKeyCandidate(storedCredentials, env) {
2520
- return candidateFromToken(env.ANTHROPIC_API_KEY, "env:ANTHROPIC_API_KEY") ?? candidateFromToken(storedCredentials?.anthropicApiKey, "config:credentials.anthropicApiKey");
2521
- }
2522
- function resolveAnthropicTokenCandidate(storedCredentials, env) {
2523
- return candidateFromToken(env.ANTHROPIC_OAUTH_TOKEN, "env:ANTHROPIC_OAUTH_TOKEN") ?? candidateFromToken(storedCredentials?.anthropicOauthToken, "config:credentials.anthropicOauthToken");
2524
- }
2525
- function resolveAnthropicOauthCandidate(env) {
2526
- return parseClaudeFromFiles(env) ?? parseClaudeFromKeychain();
2527
- }
2528
- function resolveOpenAiSubscriptionCandidate(env) {
2529
- return parseCodexFromFile(env) ?? parseCodexFromKeychain(env);
2530
- }
2531
- function credentialSetupGuidance(auth) {
2532
- switch (auth) {
2533
- case "anthropic-oauth":
2534
- return "Claude Code credentials not found. Install Claude Code CLI and sign in with `claude`.";
2535
- case "anthropic-token":
2536
- return "No Anthropic long-lived token found. Set ANTHROPIC_OAUTH_TOKEN or save credentials.anthropicOauthToken.";
2537
- case "anthropic-api-key":
2538
- return "No Anthropic API key found. Set ANTHROPIC_API_KEY or save credentials.anthropicApiKey.";
2539
- case "openai-subscription":
2540
- return "Codex CLI credentials not found or expired. Run `codex auth`.";
2541
- case "openai-api-key":
2542
- return "No OpenAI API key found. Set OPENAI_API_KEY or save credentials.openaiApiKey.";
2543
- }
2544
- }
2545
- function resolveCredentialCandidate(params) {
2546
- const env = params.env ?? process.env;
2547
- switch (params.auth) {
2548
- case "anthropic-oauth":
2549
- return resolveAnthropicOauthCandidate(env);
2550
- case "anthropic-token":
2551
- return resolveAnthropicTokenCandidate(params.storedCredentials, env);
2552
- case "anthropic-api-key":
2553
- return resolveAnthropicApiKeyCandidate(params.storedCredentials, env);
2554
- case "openai-subscription":
2555
- return resolveOpenAiSubscriptionCandidate(env);
2556
- case "openai-api-key":
2557
- return resolveOpenAIApiKeyCandidate(params.storedCredentials, env);
2558
- }
2559
- }
2560
- function resolveProviderCredentialCandidate(config, provider, env) {
2561
- if (provider === "openai") {
2562
- return resolveOpenAIApiKeyCandidate(config?.credentials, env);
2563
- }
2564
- if (provider === "anthropic") {
2565
- const auth = normalizeAuthMethod(config?.auth);
2566
- if (auth && authMethodToProvider(auth) === "anthropic") {
2567
- return resolveCredentialCandidate({
2568
- auth,
2569
- storedCredentials: config?.credentials,
2570
- env
2571
- });
2572
- }
2573
- return resolveAnthropicApiKeyCandidate(config?.credentials, env);
2574
- }
2575
- const envApiKey = getEnvApiKey(provider) ?? getEnvApiKey(provider);
2576
- return candidateFromToken(envApiKey, `env:${provider}`);
2577
- }
2578
- function createEmptyUsageStats2() {
2579
- return {
2580
- calls: 0,
2581
- inputTokens: 0,
2582
- outputTokens: 0,
2583
- cacheReadTokens: 0,
2584
- cacheWriteTokens: 0,
2585
- totalTokens: 0,
2586
- totalCost: 0
2587
- };
2588
- }
2589
- function accumulateUsage(target, usage) {
2590
- target.calls += 1;
2591
- target.inputTokens += usage.input;
2592
- target.outputTokens += usage.output;
2593
- target.cacheReadTokens += usage.cacheRead;
2594
- target.cacheWriteTokens += usage.cacheWrite;
2595
- target.totalTokens += usage.totalTokens;
2596
- target.totalCost += usage.cost.total;
2597
- }
2598
- function extractText(response) {
2599
- const blocks = [];
2600
- for (const contentBlock of response.content) {
2601
- if (contentBlock.type === "text") {
2602
- blocks.push(contentBlock.text);
2603
- }
2604
- }
2605
- return blocks.join("");
2606
- }
2607
-
2608
2246
  // src/cli/shared/parse.ts
2609
2247
  import { InvalidArgumentError } from "commander";
2610
- function normalizeOptionalString3(value) {
2248
+ function normalizeOptionalString2(value) {
2611
2249
  const trimmed = value?.trim();
2612
2250
  return trimmed && trimmed.length > 0 ? trimmed : void 0;
2613
2251
  }
@@ -2615,7 +2253,7 @@ function normalizeStringList(values) {
2615
2253
  const normalizedValues = [];
2616
2254
  const seen = /* @__PURE__ */ new Set();
2617
2255
  for (const value of values ?? []) {
2618
- const normalized = normalizeOptionalString3(value);
2256
+ const normalized = normalizeOptionalString2(value);
2619
2257
  if (!normalized || seen.has(normalized)) {
2620
2258
  continue;
2621
2259
  }
@@ -2625,7 +2263,7 @@ function normalizeStringList(values) {
2625
2263
  return normalizedValues.length > 0 ? normalizedValues : void 0;
2626
2264
  }
2627
2265
  function collectStringValue(value, previous) {
2628
- const normalized = normalizeOptionalString3(value);
2266
+ const normalized = normalizeOptionalString2(value);
2629
2267
  if (!normalized) {
2630
2268
  throw new InvalidArgumentError("Value cannot be empty.");
2631
2269
  }
@@ -2677,7 +2315,7 @@ function parseUnitInterval(value) {
2677
2315
  return parsed;
2678
2316
  }
2679
2317
  function parseModelRef(value) {
2680
- const normalized = normalizeOptionalString3(value);
2318
+ const normalized = normalizeOptionalString2(value);
2681
2319
  if (!normalized) {
2682
2320
  throw new InvalidArgumentError("Model reference cannot be empty.");
2683
2321
  }
@@ -2687,8 +2325,8 @@ function parseModelRef(value) {
2687
2325
  modelId: normalized
2688
2326
  };
2689
2327
  }
2690
- const provider = normalizeOptionalString3(normalized.slice(0, separatorIndex));
2691
- const modelId = normalizeOptionalString3(normalized.slice(separatorIndex + 1));
2328
+ const provider = normalizeOptionalString2(normalized.slice(0, separatorIndex));
2329
+ const modelId = normalizeOptionalString2(normalized.slice(separatorIndex + 1));
2692
2330
  if (!provider || !modelId) {
2693
2331
  throw new InvalidArgumentError(`Model reference must look like "provider/model" or "model". Received: ${value}.`);
2694
2332
  }
@@ -2739,13 +2377,13 @@ function timestamp() {
2739
2377
  import { InvalidArgumentError as InvalidArgumentError3, Option as Option2 } from "commander";
2740
2378
 
2741
2379
  // src/cli/commands/ingest-episodes.ts
2742
- import fs5 from "fs/promises";
2743
- import path7 from "path";
2380
+ import fs4 from "fs/promises";
2381
+ import path6 from "path";
2744
2382
  import * as clack2 from "@clack/prompts";
2745
2383
  import { InvalidArgumentError as InvalidArgumentError2, Option } from "commander";
2746
2384
 
2747
2385
  // src/adapters/db/episode-ingest-support.ts
2748
- import path5 from "path";
2386
+ import path4 from "path";
2749
2387
  function createEpisodeIngestSupportPort(executor) {
2750
2388
  return {
2751
2389
  countEntries: async () => countRows(executor, "SELECT COUNT(*) AS count FROM entries"),
@@ -2761,7 +2399,7 @@ async function hasRelevantProvenanceMatch(executor, sampleFiles) {
2761
2399
  if (ingestLogMatches > 0) {
2762
2400
  return true;
2763
2401
  }
2764
- const basenames = Array.from(new Set(sampleFiles.map((filePath) => path5.basename(filePath))));
2402
+ const basenames = Array.from(new Set(sampleFiles.map((filePath) => path4.basename(filePath))));
2765
2403
  const basenameClauses = basenames.map(() => "(source_file = ? OR source_file LIKE ?)").join(" OR ");
2766
2404
  const basenameArgs = basenames.flatMap((basename) => [basename, `%/${basename}`]);
2767
2405
  const entryMatches = await countRows(executor, `SELECT COUNT(*) AS count FROM entries WHERE source_file IS NOT NULL AND (${basenameClauses})`, basenameArgs);
@@ -2850,17 +2488,17 @@ function normalizeNullableString(value) {
2850
2488
  }
2851
2489
 
2852
2490
  // src/adapters/openclaw/session/transcript-files.ts
2853
- import fs4 from "fs/promises";
2854
- import path6 from "path";
2491
+ import fs3 from "fs/promises";
2492
+ import path5 from "path";
2855
2493
  var OPENCLAW_TRANSCRIPT_FILE_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.jsonl(?:\.(?:reset|deleted)\..+)?$/i;
2856
2494
  async function discoverOpenClawTranscriptFiles(targetPath) {
2857
- const resolvedTargetPath = path6.resolve(targetPath);
2858
- const stat = await fs4.stat(resolvedTargetPath);
2495
+ const resolvedTargetPath = path5.resolve(targetPath);
2496
+ const stat = await fs3.stat(resolvedTargetPath);
2859
2497
  if (stat.isFile()) {
2860
- return matchesOpenClawTranscriptFile(path6.basename(resolvedTargetPath)) ? [resolvedTargetPath] : [];
2498
+ return matchesOpenClawTranscriptFile(path5.basename(resolvedTargetPath)) ? [resolvedTargetPath] : [];
2861
2499
  }
2862
- const entries = await fs4.readdir(resolvedTargetPath, { recursive: true, withFileTypes: true });
2863
- return entries.filter((entry) => entry.isFile() && matchesOpenClawTranscriptFile(entry.name)).map((entry) => path6.resolve(entry.parentPath ?? resolvedTargetPath, entry.name)).sort((left, right) => left.localeCompare(right));
2500
+ const entries = await fs3.readdir(resolvedTargetPath, { recursive: true, withFileTypes: true });
2501
+ return entries.filter((entry) => entry.isFile() && matchesOpenClawTranscriptFile(entry.name)).map((entry) => path5.resolve(entry.parentPath ?? resolvedTargetPath, entry.name)).sort((left, right) => left.localeCompare(right));
2864
2502
  }
2865
2503
  var openClawTranscriptFiles = {
2866
2504
  discoverFiles: discoverOpenClawTranscriptFiles
@@ -2907,7 +2545,7 @@ function registerIngestEpisodesCommand(parent) {
2907
2545
  }
2908
2546
  const { provider, modelId } = resolveEpisodeModel(config, commandInput.modelOverride);
2909
2547
  const modelInfo = createEpisodeIngestSummaryModelInfo(provider, modelId);
2910
- const resolvedTargetPath = path7.resolve(normalizedTargetPath);
2548
+ const resolvedTargetPath = path6.resolve(normalizedTargetPath);
2911
2549
  const sessionsDir = await resolveSessionsDirectory(resolvedTargetPath);
2912
2550
  const ports = await createEpisodeIngestPorts(database, sessionsDir);
2913
2551
  const embeddingSetup = resolveEpisodeEmbeddingSetup(config, commandInput);
@@ -3122,18 +2760,18 @@ function createEpisodeIngestSummaryLlm(provider, modelId, apiKey) {
3122
2760
  };
3123
2761
  }
3124
2762
  async function resolveSessionsDirectory(targetPath) {
3125
- const stat = await fs5.stat(targetPath);
3126
- return stat.isFile() ? path7.dirname(targetPath) : targetPath;
2763
+ const stat = await fs4.stat(targetPath);
2764
+ return stat.isFile() ? path6.dirname(targetPath) : targetPath;
3127
2765
  }
3128
2766
  function resolveEpisodeDbPath(config, overridePath) {
3129
- const normalizedOverride = normalizeOptionalString3(overridePath);
2767
+ const normalizedOverride = normalizeOptionalString2(overridePath);
3130
2768
  if (!normalizedOverride) {
3131
2769
  return config?.dbPath ?? resolveDbPath(config);
3132
2770
  }
3133
2771
  if (normalizedOverride === ":memory:" || normalizedOverride.startsWith("file:")) {
3134
2772
  return normalizedOverride;
3135
2773
  }
3136
- return path7.resolve(normalizedOverride);
2774
+ return path6.resolve(normalizedOverride);
3137
2775
  }
3138
2776
  function resolveEpisodeModel(config, overrideRef) {
3139
2777
  const resolved = resolveModel(config, "episode");
@@ -3247,7 +2885,7 @@ function reportEpisodeProgress(completed, total, session) {
3247
2885
  }
3248
2886
  function formatEpisodeProgressLine(completed, total, session) {
3249
2887
  const prefix = completed !== void 0 && total !== void 0 ? `${completed}/${total} ` : "";
3250
- const fileLabel = path7.basename(session.filePath);
2888
+ const fileLabel = path6.basename(session.filePath);
3251
2889
  const details = session.action === "failed" ? `failed (${session.error ?? "unknown error"})` : session.action;
3252
2890
  const usage = session.usage.totalCost > 0 ? ` ${formatCost(session.usage.totalCost)}` : "";
3253
2891
  return `${prefix}${fileLabel}: ${details}${usage}`;
@@ -3272,15 +2910,15 @@ function formatUnknownError2(error) {
3272
2910
  }
3273
2911
  function normalizeEpisodeIngestCommand(targetPath, options) {
3274
2912
  const commandInput = {
3275
- targetPath: normalizeOptionalString3(targetPath),
2913
+ targetPath: normalizeOptionalString2(targetPath),
3276
2914
  verbose: options.verbose === true,
3277
2915
  dryRun: options.dryRun === true,
3278
2916
  regenerate: options.regenerate === true,
3279
2917
  embedOnly: options.embedOnly === true,
3280
2918
  noEmbed: options.noEmbed === true,
3281
- recent: normalizeOptionalString3(options.recent),
2919
+ recent: normalizeOptionalString2(options.recent),
3282
2920
  concurrency: options.concurrency ?? DEFAULT_EPISODE_INGEST_CONCURRENCY,
3283
- dbOverride: normalizeOptionalString3(options.db),
2921
+ dbOverride: normalizeOptionalString2(options.db),
3284
2922
  modelOverride: options.model ? parseModelRef(options.model) : void 0
3285
2923
  };
3286
2924
  validateEpisodeIngestOptions(commandInput);
@@ -3291,26 +2929,26 @@ function parseEpisodeIngestConcurrency(value) {
3291
2929
  }
3292
2930
 
3293
2931
  // src/cli/commands/ingest-procedures.ts
3294
- import path9 from "path";
2932
+ import path8 from "path";
3295
2933
  import * as clack3 from "@clack/prompts";
3296
2934
  import "commander";
3297
2935
 
3298
2936
  // src/adapters/files/procedure-files.ts
3299
- import fs6 from "fs/promises";
3300
- import path8 from "path";
2937
+ import fs5 from "fs/promises";
2938
+ import path7 from "path";
3301
2939
  var PROCEDURE_FILE_PATTERN = /^.+\.ya?ml$/iu;
3302
2940
  async function discoverProcedureFiles(targetPath, options = {}) {
3303
- const resolvedTargetPath = path8.resolve(targetPath);
3304
- const stat = await fs6.stat(resolvedTargetPath);
2941
+ const resolvedTargetPath = path7.resolve(targetPath);
2942
+ const stat = await fs5.stat(resolvedTargetPath);
3305
2943
  if (stat.isFile()) {
3306
- return matchesProcedureFileName(path8.basename(resolvedTargetPath)) ? [resolvedTargetPath] : [];
2944
+ return matchesProcedureFileName(path7.basename(resolvedTargetPath)) ? [resolvedTargetPath] : [];
3307
2945
  }
3308
2946
  const recursive = options.recursive ?? true;
3309
- const entries = recursive ? await fs6.readdir(resolvedTargetPath, { recursive: true, withFileTypes: true }) : await fs6.readdir(resolvedTargetPath, { withFileTypes: true });
3310
- return entries.filter((entry) => entry.isFile() && matchesProcedureFileName(entry.name)).map((entry) => path8.resolve(entry.parentPath ?? resolvedTargetPath, entry.name)).sort((left, right) => left.localeCompare(right));
2947
+ const entries = recursive ? await fs5.readdir(resolvedTargetPath, { recursive: true, withFileTypes: true }) : await fs5.readdir(resolvedTargetPath, { withFileTypes: true });
2948
+ return entries.filter((entry) => entry.isFile() && matchesProcedureFileName(entry.name)).map((entry) => path7.resolve(entry.parentPath ?? resolvedTargetPath, entry.name)).sort((left, right) => left.localeCompare(right));
3311
2949
  }
3312
2950
  async function readProcedureFile(filePath) {
3313
- return fs6.readFile(filePath, "utf-8");
2951
+ return fs5.readFile(filePath, "utf-8");
3314
2952
  }
3315
2953
  var LocalProcedureFiles = class {
3316
2954
  /**
@@ -3645,7 +3283,7 @@ function registerIngestProceduresCommand(parent) {
3645
3283
  try {
3646
3284
  const config = readConfig();
3647
3285
  const dbPath = config.dbPath;
3648
- const resolvedTargetPath = path9.resolve(commandInput.targetPath);
3286
+ const resolvedTargetPath = path8.resolve(commandInput.targetPath);
3649
3287
  database = await createDatabase(dbPath);
3650
3288
  if (commandInput.verbose) {
3651
3289
  clack3.log.step(`Preparing procedure sync for ${resolvedTargetPath}...`);
@@ -3701,7 +3339,7 @@ function registerIngestProceduresCommand(parent) {
3701
3339
  }
3702
3340
  function normalizeIngestProceduresCommand(targetPath, options) {
3703
3341
  return {
3704
- targetPath: normalizeOptionalString3(targetPath) ?? DEFAULT_PROCEDURE_SYNC_PATH,
3342
+ targetPath: normalizeOptionalString2(targetPath) ?? DEFAULT_PROCEDURE_SYNC_PATH,
3705
3343
  verbose: options.verbose === true,
3706
3344
  dryRun: options.dryRun === true
3707
3345
  };
@@ -3822,11 +3460,11 @@ function registerIngestEntriesCommand(parent) {
3822
3460
  const claimApiKey = claimModel ? resolveLlmApiKey(config, claimModel.provider) : void 0;
3823
3461
  const sharedEmbedding = createEmbeddingClient(resolveEmbeddingApiKey(config), resolveEmbeddingModel(config));
3824
3462
  if (commandInput.verbose) {
3825
- clack4.log.step(`Discovering transcript files in ${path10.resolve(commandInput.targetPath)}...`);
3463
+ clack4.log.step(`Discovering transcript files in ${path9.resolve(commandInput.targetPath)}...`);
3826
3464
  }
3827
3465
  const files = await localTranscriptFiles.discoverFiles(commandInput.targetPath);
3828
3466
  if (files.length === 0) {
3829
- clack4.log.warn(`No transcript files found at ${path10.resolve(commandInput.targetPath)}.`);
3467
+ clack4.log.warn(`No transcript files found at ${path9.resolve(commandInput.targetPath)}.`);
3830
3468
  clack4.outro("Nothing to ingest.");
3831
3469
  return;
3832
3470
  }
@@ -3909,7 +3547,7 @@ function registerIngestEntriesCommand(parent) {
3909
3547
  failedFiles: 0,
3910
3548
  warnings: 0
3911
3549
  };
3912
- const usageTotals = extractionRuns.reduce((total, run) => addUsageStats(total, run.usage), createEmptyUsageStats3());
3550
+ const usageTotals = extractionRuns.reduce((total, run) => addUsageStats(total, run.usage), createEmptyUsageStats2());
3913
3551
  addUsageStats(usageTotals, dedupUsage);
3914
3552
  let runningCost = 0;
3915
3553
  for (const [index, extractionRun] of extractionRuns.entries()) {
@@ -3922,9 +3560,9 @@ function registerIngestEntriesCommand(parent) {
3922
3560
  totals.skippedFiles += 1;
3923
3561
  if (commandInput.verbose) {
3924
3562
  printVerboseFileDetails(result, commandInput, usage);
3925
- clack4.log.step(buildSkippedMessage(path10.basename(result.file)));
3563
+ clack4.log.step(buildSkippedMessage(path9.basename(result.file)));
3926
3564
  } else {
3927
- clack4.log.step(buildSkippedMessage(path10.basename(result.file)));
3565
+ clack4.log.step(buildSkippedMessage(path9.basename(result.file)));
3928
3566
  }
3929
3567
  continue;
3930
3568
  }
@@ -3933,7 +3571,7 @@ function registerIngestEntriesCommand(parent) {
3933
3571
  if (commandInput.verbose) {
3934
3572
  printVerboseFileDetails(result, commandInput, usage);
3935
3573
  }
3936
- clack4.log.error(buildFailureMessage(path10.basename(result.file), result, commandInput, usage, index === 0));
3574
+ clack4.log.error(buildFailureMessage(path9.basename(result.file), result, commandInput, usage, index === 0));
3937
3575
  continue;
3938
3576
  }
3939
3577
  const storeResult = result.storeResult ?? emptyStoreResult2();
@@ -3943,7 +3581,7 @@ function registerIngestEntriesCommand(parent) {
3943
3581
  if (commandInput.verbose) {
3944
3582
  printVerboseFileDetails(result, commandInput, usage);
3945
3583
  }
3946
- clack4.log.step(buildSuccessMessage(path10.basename(result.file), result, commandInput, usage, index === 0));
3584
+ clack4.log.step(buildSuccessMessage(path9.basename(result.file), result, commandInput, usage, index === 0));
3947
3585
  }
3948
3586
  const summaryParts = [`${totals.stored} ${pluralize3(totals.stored, "entry", "entries")} stored`, `${totals.deduped} deduped`];
3949
3587
  if (totals.rejected > 0) {
@@ -3982,7 +3620,7 @@ function registerIngestEntriesCommand(parent) {
3982
3620
  });
3983
3621
  }
3984
3622
  function normalizeIngestEntriesCommand(targetPath, options) {
3985
- const normalizedTargetPath = normalizeOptionalString3(targetPath);
3623
+ const normalizedTargetPath = normalizeOptionalString2(targetPath);
3986
3624
  if (!normalizedTargetPath) {
3987
3625
  throw new InvalidArgumentError3("Path cannot be empty.");
3988
3626
  }
@@ -4336,7 +3974,7 @@ function truncateText(text2, maxLength) {
4336
3974
  function isDefined3(value) {
4337
3975
  return value !== void 0;
4338
3976
  }
4339
- function createEmptyUsageStats3() {
3977
+ function createEmptyUsageStats2() {
4340
3978
  return {
4341
3979
  calls: 0,
4342
3980
  inputTokens: 0,
@@ -4372,8 +4010,8 @@ function parseConcurrency(value) {
4372
4010
  import { getModels } from "@mariozechner/pi-ai";
4373
4011
 
4374
4012
  // src/cli/ui.ts
4375
- import os2 from "os";
4376
- import path11 from "path";
4013
+ import os from "os";
4014
+ import path10 from "path";
4377
4015
  import * as clack5 from "@clack/prompts";
4378
4016
  function createCliPrompts() {
4379
4017
  return {
@@ -4403,24 +4041,24 @@ function createCliPrompts() {
4403
4041
  };
4404
4042
  }
4405
4043
  var cliPrompts = createCliPrompts();
4406
- function resolveUserPath2(value) {
4044
+ function resolveUserPath(value) {
4407
4045
  const trimmed = value.trim();
4408
4046
  if (trimmed === ":memory:" || trimmed.startsWith("file:")) {
4409
4047
  return trimmed;
4410
4048
  }
4411
4049
  if (trimmed === "~") {
4412
- return os2.homedir();
4050
+ return os.homedir();
4413
4051
  }
4414
4052
  if (trimmed.startsWith("~/")) {
4415
- return path11.join(os2.homedir(), trimmed.slice(2));
4053
+ return path10.join(os.homedir(), trimmed.slice(2));
4416
4054
  }
4417
4055
  if (trimmed.startsWith("~\\")) {
4418
- return path11.join(os2.homedir(), trimmed.slice(2));
4056
+ return path10.join(os.homedir(), trimmed.slice(2));
4419
4057
  }
4420
- return path11.resolve(trimmed);
4058
+ return path10.resolve(trimmed);
4421
4059
  }
4422
4060
  function formatPathForDisplay(filePath) {
4423
- const home = os2.homedir();
4061
+ const home = os.homedir();
4424
4062
  const resolvedPath = filePath.trim();
4425
4063
  return resolvedPath.startsWith(home) ? `~${resolvedPath.slice(home.length)}` : resolvedPath;
4426
4064
  }
@@ -4448,50 +4086,50 @@ function validateSecret(value) {
4448
4086
  return value?.trim().length ? void 0 : "Value cannot be empty.";
4449
4087
  }
4450
4088
  function hasSecret(value) {
4451
- return normalizeOptionalString4(value) !== void 0;
4089
+ return normalizeOptionalString3(value) !== void 0;
4452
4090
  }
4453
4091
  function formatModelRef(config) {
4454
- const provider = normalizeOptionalString4(config?.provider) ?? "(provider not set)";
4455
- const model = normalizeOptionalString4(config?.model) ?? "(model not set)";
4092
+ const provider = normalizeOptionalString3(config?.provider) ?? "(provider not set)";
4093
+ const model = normalizeOptionalString3(config?.model) ?? "(model not set)";
4456
4094
  return `${provider}/${model}`;
4457
4095
  }
4458
4096
  function hasModelOverride(config) {
4459
- return normalizeOptionalString4(config?.provider) !== void 0 || normalizeOptionalString4(config?.model) !== void 0;
4097
+ return normalizeOptionalString3(config?.provider) !== void 0 || normalizeOptionalString3(config?.model) !== void 0;
4460
4098
  }
4461
4099
  function sameModelRef(left, right) {
4462
- return normalizeOptionalString4(left?.provider) === normalizeOptionalString4(right?.provider) && normalizeOptionalString4(left?.model) === normalizeOptionalString4(right?.model);
4100
+ return normalizeOptionalString3(left?.provider) === normalizeOptionalString3(right?.provider) && normalizeOptionalString3(left?.model) === normalizeOptionalString3(right?.model);
4463
4101
  }
4464
4102
  function resolveStoredCredentialForAuth(config, auth) {
4465
4103
  switch (auth) {
4466
4104
  case "openai-api-key":
4467
- return normalizeOptionalString4(config?.credentials?.openaiApiKey);
4105
+ return normalizeOptionalString3(config?.credentials?.openaiApiKey);
4468
4106
  case "anthropic-api-key":
4469
- return normalizeOptionalString4(config?.credentials?.anthropicApiKey);
4107
+ return normalizeOptionalString3(config?.credentials?.anthropicApiKey);
4470
4108
  case "anthropic-token":
4471
- return normalizeOptionalString4(config?.credentials?.anthropicOauthToken);
4109
+ return normalizeOptionalString3(config?.credentials?.anthropicOauthToken);
4472
4110
  case "anthropic-oauth":
4473
4111
  case "openai-subscription":
4474
4112
  return void 0;
4475
4113
  }
4476
4114
  }
4477
4115
  function resolveStoredEmbeddingCredential(config) {
4478
- return normalizeOptionalString4(config?.credentials?.openaiApiKey);
4116
+ return normalizeOptionalString3(config?.credentials?.openaiApiKey);
4479
4117
  }
4480
4118
  function normalizeProvider(value) {
4481
- const normalized = normalizeOptionalString4(value);
4119
+ const normalized = normalizeOptionalString3(value);
4482
4120
  if (normalized === "openai" || normalized === "openai-codex" || normalized === "anthropic") {
4483
4121
  return normalized;
4484
4122
  }
4485
4123
  return void 0;
4486
4124
  }
4487
- function normalizeAuthMethod2(value) {
4488
- const normalized = normalizeOptionalString4(value);
4125
+ function normalizeAuthMethod(value) {
4126
+ const normalized = normalizeOptionalString3(value);
4489
4127
  if (normalized === "openai-api-key" || normalized === "openai-subscription" || normalized === "anthropic-api-key" || normalized === "anthropic-oauth" || normalized === "anthropic-token") {
4490
4128
  return normalized;
4491
4129
  }
4492
4130
  return void 0;
4493
4131
  }
4494
- function normalizeOptionalString4(value) {
4132
+ function normalizeOptionalString3(value) {
4495
4133
  const trimmed = value?.trim();
4496
4134
  return trimmed && trimmed.length > 0 ? trimmed : void 0;
4497
4135
  }
@@ -4733,7 +4371,7 @@ function hasPersistedSurgeonConfig(config) {
4733
4371
  return false;
4734
4372
  }
4735
4373
  const retirementConfig = config.passes?.retirement;
4736
- return hasModelOverride(config.model) || config.costCap !== void 0 || config.dailyCostCap !== void 0 || config.contextLimit !== void 0 || normalizeOptionalString4(config.customInstructions) !== void 0 || retirementConfig?.protectRecalledDays !== void 0 || retirementConfig?.protectMinImportance !== void 0 || retirementConfig?.skipRecentlyEvaluatedDays !== void 0;
4374
+ return hasModelOverride(config.model) || config.costCap !== void 0 || config.dailyCostCap !== void 0 || config.contextLimit !== void 0 || normalizeOptionalString3(config.customInstructions) !== void 0 || retirementConfig?.protectRecalledDays !== void 0 || retirementConfig?.protectMinImportance !== void 0 || retirementConfig?.skipRecentlyEvaluatedDays !== void 0;
4737
4375
  }
4738
4376
 
4739
4377
  // src/cli/commands/setup/config.ts
@@ -4770,8 +4408,8 @@ function isSetupConfigured(config, env = process.env) {
4770
4408
  return getSetupReadiness(config, env).ready;
4771
4409
  }
4772
4410
  function getSetupReadiness(config, env = process.env) {
4773
- const provider = normalizeOptionalString4(config?.provider);
4774
- const model = normalizeOptionalString4(config?.model);
4411
+ const provider = normalizeOptionalString3(config?.provider);
4412
+ const model = normalizeOptionalString3(config?.model);
4775
4413
  if (!provider || !model) {
4776
4414
  return {
4777
4415
  ready: false,
@@ -4812,7 +4450,7 @@ function formatSavedConfigSummary(config, configPath, dbPath, options) {
4812
4450
  return lines.join("\n");
4813
4451
  }
4814
4452
  function describePrimaryCredentialConfig(config) {
4815
- const auth = normalizeAuthMethod2(config.auth);
4453
+ const auth = normalizeAuthMethod(config.auth);
4816
4454
  if (!auth) {
4817
4455
  return "not set";
4818
4456
  }
@@ -4829,9 +4467,9 @@ function describePrimaryCredentialConfig(config) {
4829
4467
  }
4830
4468
  function describeEmbeddingConfig(config) {
4831
4469
  if (hasSecret(resolveStoredEmbeddingCredential(config))) {
4832
- return normalizeAuthMethod2(config.auth) === "openai-api-key" ? "uses the primary OpenAI key" : "separate OpenAI key configured";
4470
+ return normalizeAuthMethod(config.auth) === "openai-api-key" ? "uses the primary OpenAI key" : "separate OpenAI key configured";
4833
4471
  }
4834
- const auth = normalizeAuthMethod2(config.auth);
4472
+ const auth = normalizeAuthMethod(config.auth);
4835
4473
  if (auth && auth !== "openai-api-key") {
4836
4474
  return "missing separate OpenAI key";
4837
4475
  }
@@ -4841,7 +4479,7 @@ function mergeStoredCredentials(existingCredentials, values) {
4841
4479
  const next = {
4842
4480
  ...existingCredentials ?? {}
4843
4481
  };
4844
- const normalizedPrimaryCredential = normalizeOptionalString4(values.primaryCredential);
4482
+ const normalizedPrimaryCredential = normalizeOptionalString3(values.primaryCredential);
4845
4483
  if (normalizedPrimaryCredential) {
4846
4484
  if (values.auth === "openai-api-key") {
4847
4485
  next.openaiApiKey = normalizedPrimaryCredential;
@@ -4851,7 +4489,7 @@ function mergeStoredCredentials(existingCredentials, values) {
4851
4489
  next.anthropicOauthToken = normalizedPrimaryCredential;
4852
4490
  }
4853
4491
  }
4854
- const normalizedEmbeddingApiKey = normalizeOptionalString4(values.embeddingApiKey);
4492
+ const normalizedEmbeddingApiKey = normalizeOptionalString3(values.embeddingApiKey);
4855
4493
  if (normalizedEmbeddingApiKey) {
4856
4494
  next.openaiApiKey = normalizedEmbeddingApiKey;
4857
4495
  }
@@ -4877,7 +4515,7 @@ async function runSetupCore(options = {}) {
4877
4515
  }
4878
4516
  const existingConfig = options.existingConfig;
4879
4517
  const configPath = runtime.resolveConfigPath();
4880
- const auth = await selectAuthMethod(prompts, normalizeAuthMethod2(existingConfig?.auth));
4518
+ const auth = await selectAuthMethod(prompts, normalizeAuthMethod(existingConfig?.auth));
4881
4519
  if (auth === null) {
4882
4520
  return null;
4883
4521
  }
@@ -4922,7 +4560,7 @@ async function runSetupCore(options = {}) {
4922
4560
  if (stageOverrides === null) {
4923
4561
  return null;
4924
4562
  }
4925
- const defaultDbPath = normalizeOptionalString4(existingConfig?.dbPath) ?? runtime.resolveDbPath(existingConfig);
4563
+ const defaultDbPath = normalizeOptionalString3(existingConfig?.dbPath) ?? runtime.resolveDbPath(existingConfig);
4926
4564
  const dbPathInput = await prompts.text({
4927
4565
  message: "Database path:",
4928
4566
  initialValue: defaultDbPath,
@@ -4932,7 +4570,7 @@ async function runSetupCore(options = {}) {
4932
4570
  if (prompts.isCancel(dbPathInput)) {
4933
4571
  return null;
4934
4572
  }
4935
- const dbPath = resolveUserPath2(dbPathInput);
4573
+ const dbPath = resolveUserPath(dbPathInput);
4936
4574
  const nextConfig = buildNextConfig(existingConfig, {
4937
4575
  auth,
4938
4576
  provider,
@@ -5289,9 +4927,9 @@ async function promptTaskModelOverrides(prompts, runtime, options) {
5289
4927
  async function promptStageOverride(prompts, runtime, options) {
5290
4928
  const defaultRef = `${describeAuthMethod(options.defaultAuth)} / ${options.defaultModel}`;
5291
4929
  const currentProvider = normalizeProvider(options.current?.provider);
5292
- const currentModel = normalizeOptionalString4(options.current?.model) ?? options.defaultModel;
4930
+ const currentModel = normalizeOptionalString3(options.current?.model) ?? options.defaultModel;
5293
4931
  const currentAuth = resolveStageAuthChoice(currentProvider, options.defaultAuth);
5294
- const hasExplicitOverride = normalizeOptionalString4(options.current?.provider) !== void 0 || normalizeOptionalString4(options.current?.model) !== void 0;
4932
+ const hasExplicitOverride = normalizeOptionalString3(options.current?.provider) !== void 0 || normalizeOptionalString3(options.current?.model) !== void 0;
5295
4933
  const action = await prompts.select({
5296
4934
  message: `${options.stage.label} model override:`,
5297
4935
  options: [
@@ -5490,8 +5128,8 @@ function formatTokenCount(tokens) {
5490
5128
 
5491
5129
  // src/cli/commands/init/external-commands.ts
5492
5130
  import { execFile, execFileSync } from "child_process";
5493
- import fs7 from "fs/promises";
5494
- import path12 from "path";
5131
+ import fs6 from "fs/promises";
5132
+ import path11 from "path";
5495
5133
  var OPENCLAW_PLUGIN_PACKAGE = "@agenr/agenr-plugin";
5496
5134
  function execAsync(command, args, options) {
5497
5135
  return new Promise((resolve, reject) => {
@@ -5588,10 +5226,10 @@ async function restartOpenClawGateway() {
5588
5226
  }
5589
5227
  }
5590
5228
  async function writeOpenClawPluginConfig(stateDir, config) {
5591
- const openclawConfigPath = path12.join(stateDir, "openclaw.json");
5229
+ const openclawConfigPath = path11.join(stateDir, "openclaw.json");
5592
5230
  let root = {};
5593
5231
  try {
5594
- const raw = await fs7.readFile(openclawConfigPath, "utf8");
5232
+ const raw = await fs6.readFile(openclawConfigPath, "utf8");
5595
5233
  const parsed = JSON.parse(raw);
5596
5234
  if (isRecord(parsed)) {
5597
5235
  root = parsed;
@@ -5617,13 +5255,13 @@ async function writeOpenClawPluginConfig(stateDir, config) {
5617
5255
  } else {
5618
5256
  delete entryConfig.configPath;
5619
5257
  }
5620
- await fs7.mkdir(stateDir, { recursive: true });
5621
- await fs7.writeFile(openclawConfigPath, `${JSON.stringify(root, null, 2)}
5258
+ await fs6.mkdir(stateDir, { recursive: true });
5259
+ await fs6.writeFile(openclawConfigPath, `${JSON.stringify(root, null, 2)}
5622
5260
  `, "utf8");
5623
5261
  return openclawConfigPath;
5624
5262
  }
5625
5263
  function shouldPersistPluginConfigPath(dbPath, configPath) {
5626
- return path12.dirname(dbPath) !== path12.dirname(configPath);
5264
+ return path11.dirname(dbPath) !== path11.dirname(configPath);
5627
5265
  }
5628
5266
  function isRecord(value) {
5629
5267
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -5650,32 +5288,32 @@ function ensureArrayOfStrings(target, key) {
5650
5288
  }
5651
5289
 
5652
5290
  // src/cli/commands/init/openclaw-detect.ts
5653
- import fs8 from "fs";
5654
- import os3 from "os";
5655
- import path13 from "path";
5291
+ import fs7 from "fs";
5292
+ import os2 from "os";
5293
+ import path12 from "path";
5656
5294
  function resolveDefaultOpenClawStateDir() {
5657
- return path13.join(os3.homedir(), ".openclaw");
5295
+ return path12.join(os2.homedir(), ".openclaw");
5658
5296
  }
5659
- function detectOpenClawInstallation(env = process.env, existsSyncFn = fs8.existsSync) {
5660
- const envStateDir = normalizeOptionalString5(env.OPENCLAW_STATE_DIR) ?? normalizeOptionalString5(env.OPENCLAW_HOME);
5297
+ function detectOpenClawInstallation(env = process.env, existsSyncFn = fs7.existsSync) {
5298
+ const envStateDir = normalizeOptionalString4(env.OPENCLAW_STATE_DIR) ?? normalizeOptionalString4(env.OPENCLAW_HOME);
5661
5299
  const source = envStateDir ? "environment" : "default";
5662
- const stateDir = envStateDir ? resolveUserPath2(envStateDir) : resolveDefaultOpenClawStateDir();
5300
+ const stateDir = envStateDir ? resolveUserPath(envStateDir) : resolveDefaultOpenClawStateDir();
5663
5301
  return {
5664
5302
  detected: envStateDir !== void 0 || existsSyncFn(stateDir),
5665
5303
  stateDir,
5666
- configPath: path13.join(stateDir, "openclaw.json"),
5667
- sessionsRoot: path13.join(stateDir, "agents"),
5304
+ configPath: path12.join(stateDir, "openclaw.json"),
5305
+ sessionsRoot: path12.join(stateDir, "agents"),
5668
5306
  source
5669
5307
  };
5670
5308
  }
5671
- function normalizeOptionalString5(value) {
5309
+ function normalizeOptionalString4(value) {
5672
5310
  const trimmed = value?.trim();
5673
5311
  return trimmed && trimmed.length > 0 ? trimmed : void 0;
5674
5312
  }
5675
5313
 
5676
5314
  // src/cli/commands/init/session-scanner.ts
5677
- import fs9 from "fs/promises";
5678
- import path14 from "path";
5315
+ import fs8 from "fs/promises";
5316
+ import path13 from "path";
5679
5317
  async function scanSessionFiles(sessionsRoot, recentDays = 7) {
5680
5318
  const result = {
5681
5319
  totalFiles: 0,
@@ -5700,7 +5338,7 @@ async function scanSessionFiles(sessionsRoot, recentDays = 7) {
5700
5338
  }
5701
5339
  let stat;
5702
5340
  try {
5703
- stat = await fs9.stat(filePath);
5341
+ stat = await fs8.stat(filePath);
5704
5342
  } catch (error) {
5705
5343
  if (isMissingPathError(error)) {
5706
5344
  continue;
@@ -5718,7 +5356,7 @@ async function scanSessionFiles(sessionsRoot, recentDays = 7) {
5718
5356
  return result;
5719
5357
  }
5720
5358
  function isSessionTranscriptPath(filePath) {
5721
- return filePath.split(path14.sep).includes("sessions");
5359
+ return filePath.split(path13.sep).includes("sessions");
5722
5360
  }
5723
5361
  function isMissingPathError(error) {
5724
5362
  return typeof error === "object" && error !== null && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR");
@@ -6089,7 +5727,7 @@ function registerInitCommand(program2) {
6089
5727
  import * as clack6 from "@clack/prompts";
6090
5728
  import { InvalidArgumentError as InvalidArgumentError4, Option as Option3 } from "commander";
6091
5729
  function registerRecallCommand(program2) {
6092
- program2.command("recall <query>").description("Search the knowledge database with the v1 hybrid recall pipeline").addOption(new Option3("--limit <n>", "Max results").argParser(parsePositiveInteger).default(10)).addOption(new Option3("--threshold <n>", "Minimum score cutoff").argParser(parseUnitInterval).default(0)).addOption(new Option3("--budget <n>", "Max token budget").argParser(parsePositiveInteger)).addOption(new Option3("--types <types>", "Comma-separated entry types").argParser(parseEntryTypes)).addOption(new Option3("--tags <tags>", "Comma-separated tags").argParser(parseCsvList)).option("--since <date>", "Only entries after this date (ISO or relative like 7d)").option("--until <date>", "Only entries before this date").option("--around <date>", "Bias results toward this date").option("--as-of <date>", "Resolve current vs prior state at this reference time").addOption(new Option3("--around-radius <n>", "Gaussian radius in days").argParser(parsePositiveNumber).default(14)).option("--verbose", "Show score breakdowns").action(async (query, options) => {
5730
+ program2.command("recall <query>").description("Search the knowledge database with the v1 hybrid recall pipeline").addOption(new Option3("--limit <n>", "Max results").argParser(parsePositiveInteger).default(10)).addOption(new Option3("--threshold <n>", "Minimum score cutoff").argParser(parseUnitInterval).default(0)).addOption(new Option3("--budget <n>", "Max token budget").argParser(parsePositiveInteger)).addOption(new Option3("--types <types>", "Comma-separated entry types").argParser(parseEntryTypes)).addOption(new Option3("--tags <tags>", "Comma-separated tags").argParser(parseCsvList)).option("--since <date>", "Only entries after this date (ISO or relative like 7d)").option("--until <date>", "Only entries before this date").option("--around <date>", "Bias results toward this date").option("--as-of <date>", "Resolve current vs prior state at this reference time").addOption(new Option3("--around-radius <n>", "Gaussian radius in days").argParser(parsePositiveNumber).default(14)).addOption(new Option3("--cross-encoder <state>", "Enable or disable the cross-encoder rerank stage").choices(["enabled", "disabled"])).addOption(new Option3("--cross-encoder-top-k <n>", "Top-K shortlist size for cross-encoder rerank").argParser(parsePositiveInteger)).addOption(new Option3("--cross-encoder-alpha <n>", "Blend weight for cross-encoder vs prior score (0-1)").argParser(parseUnitInterval)).option("--verbose", "Show score breakdowns").action(async (query, options) => {
6093
5731
  clack6.intro(banner());
6094
5732
  let db = null;
6095
5733
  try {
@@ -6098,23 +5736,37 @@ function registerRecallCommand(program2) {
6098
5736
  const dbPath = config.dbPath;
6099
5737
  const embeddingClient = createEmbeddingClient(resolveEmbeddingApiKey(config), resolveEmbeddingModel(config));
6100
5738
  db = await createDatabase(dbPath);
6101
- const adapter = createRecallAdapter(db, embeddingClient);
5739
+ const recallPorts = createRecallAdapter(db, embeddingClient);
5740
+ const crossEncoder = commandInput.rankingPolicy?.crossEncoder === "disabled" ? void 0 : tryCreateCrossEncoder(config);
5741
+ const adapter = attachCrossEncoderPort(recallPorts, crossEncoder);
6102
5742
  let lastTraceSummary;
6103
5743
  const spinner6 = clack6.spinner();
6104
5744
  spinner6.start("Searching knowledge...");
6105
- const results = await recall(commandInput.request, adapter, {
5745
+ const recallOptions = {
6106
5746
  trace: {
6107
5747
  reportSummary(summary) {
6108
5748
  lastTraceSummary = summary;
6109
5749
  }
6110
- }
6111
- });
5750
+ },
5751
+ ...commandInput.rankingPolicy ? { rankingPolicy: commandInput.rankingPolicy } : {}
5752
+ };
5753
+ const results = await recall(commandInput.request, adapter, recallOptions);
6112
5754
  spinner6.stop(`Found ${results.length} ${pluralize4(results.length, "result")}.`);
6113
5755
  if (lastTraceSummary?.degraded.active) {
6114
5756
  for (const notice of lastTraceSummary.degraded.notices) {
6115
5757
  clack6.log.warn(notice);
6116
5758
  }
6117
5759
  }
5760
+ if (commandInput.verbose && lastTraceSummary) {
5761
+ const crossEncoder2 = lastTraceSummary.crossEncoder;
5762
+ if (crossEncoder2.applied) {
5763
+ clack6.log.info(
5764
+ `Cross-encoder reranked top-${crossEncoder2.k} (alpha=${crossEncoder2.alpha.toFixed(2)}, latencyMs=${crossEncoder2.latencyMs}, rescored=${crossEncoder2.rescoredIds.length}).`
5765
+ );
5766
+ } else if (crossEncoder2.degradedReason) {
5767
+ clack6.log.info(`Cross-encoder skipped (${crossEncoder2.degradedReason}).`);
5768
+ }
5769
+ }
6118
5770
  if (results.length === 0) {
6119
5771
  clack6.outro("No matching entries found.");
6120
5772
  return;
@@ -6133,10 +5785,11 @@ function registerRecallCommand(program2) {
6133
5785
  });
6134
5786
  }
6135
5787
  function normalizeRecallCommand(query, options) {
6136
- const normalizedQuery = normalizeOptionalString3(query);
5788
+ const normalizedQuery = normalizeOptionalString2(query);
6137
5789
  if (!normalizedQuery) {
6138
5790
  throw new InvalidArgumentError4("Query cannot be empty.");
6139
5791
  }
5792
+ const rankingPolicy = buildRankingPolicy(options);
6140
5793
  return {
6141
5794
  request: {
6142
5795
  text: normalizedQuery,
@@ -6145,15 +5798,38 @@ function normalizeRecallCommand(query, options) {
6145
5798
  budget: options.budget,
6146
5799
  types: options.types,
6147
5800
  tags: normalizeStringList(options.tags),
6148
- since: normalizeOptionalString3(options.since),
6149
- until: normalizeOptionalString3(options.until),
6150
- around: normalizeOptionalString3(options.around),
5801
+ since: normalizeOptionalString2(options.since),
5802
+ until: normalizeOptionalString2(options.until),
5803
+ around: normalizeOptionalString2(options.around),
6151
5804
  aroundRadius: options.aroundRadius,
6152
- asOf: normalizeOptionalString3(options.asOf)
5805
+ asOf: normalizeOptionalString2(options.asOf)
6153
5806
  },
6154
- verbose: options.verbose === true
5807
+ verbose: options.verbose === true,
5808
+ ...rankingPolicy ? { rankingPolicy } : {}
6155
5809
  };
6156
5810
  }
5811
+ function buildRankingPolicy(options) {
5812
+ const policy = {};
5813
+ if (options.crossEncoder !== void 0) {
5814
+ policy.crossEncoder = options.crossEncoder;
5815
+ }
5816
+ if (typeof options.crossEncoderTopK === "number") {
5817
+ policy.crossEncoderTopK = options.crossEncoderTopK;
5818
+ }
5819
+ if (typeof options.crossEncoderAlpha === "number") {
5820
+ policy.crossEncoderAlpha = options.crossEncoderAlpha;
5821
+ }
5822
+ return Object.keys(policy).length > 0 ? policy : void 0;
5823
+ }
5824
+ function tryCreateCrossEncoder(config) {
5825
+ try {
5826
+ const apiKey = resolveCrossEncoderApiKey(config);
5827
+ const { modelId } = resolveModel(config, "cross_encoder");
5828
+ return createOpenAICrossEncoder({ apiKey, model: modelId });
5829
+ } catch {
5830
+ return void 0;
5831
+ }
5832
+ }
6157
5833
  function formatResult(result, verbose, asOf) {
6158
5834
  const projected = projectClaimCentricRecallEntry(result, {
6159
5835
  asOf
@@ -6171,8 +5847,9 @@ function formatResult(result, verbose, asOf) {
6171
5847
  }
6172
5848
  lines.push(` why=${projected.whySurfaced.summary}`);
6173
5849
  if (verbose) {
5850
+ const crossEncoderFragment = typeof result.scores.crossEncoder === "number" ? ` crossEncoder=${result.scores.crossEncoder.toFixed(2)}` : "";
6174
5851
  lines.push(
6175
- ` vector=${result.scores.vector.toFixed(2)} lexical=${result.scores.lexical.toFixed(2)} recency=${result.scores.recency.toFixed(2)} importance=${result.scores.importance.toFixed(2)} relevance=${result.scores.relevance.toFixed(2)} historicalLineage=${result.scores.historicalLineage.toFixed(2)} claimKeyTrustPenalty=${result.scores.claimKeyTrustPenalty.toFixed(2)} claimKeyRedundancyPenalty=${result.scores.claimKeyRedundancyPenalty.toFixed(2)}`
5852
+ ` vector=${result.scores.vector.toFixed(2)} lexical=${result.scores.lexical.toFixed(2)} recency=${result.scores.recency.toFixed(2)} importance=${result.scores.importance.toFixed(2)} relevance=${result.scores.relevance.toFixed(2)} historicalLineage=${result.scores.historicalLineage.toFixed(2)} claimKeyTrustPenalty=${result.scores.claimKeyTrustPenalty.toFixed(2)} claimKeyRedundancyPenalty=${result.scores.claimKeyRedundancyPenalty.toFixed(2)}${crossEncoderFragment}`
6176
5853
  );
6177
5854
  }
6178
5855
  return lines.join("\n");
@@ -6226,8 +5903,8 @@ import { InvalidArgumentError as InvalidArgumentError5, Option as Option4 } from
6226
5903
  // src/app/scenarios/claim-keys/runtime.ts
6227
5904
  import { randomUUID as randomUUID11 } from "crypto";
6228
5905
  import { mkdir as mkdir2, writeFile } from "fs/promises";
6229
- import path21 from "path";
6230
- import { getModel as getModel2 } from "@mariozechner/pi-ai";
5906
+ import path20 from "path";
5907
+ import { getModel } from "@mariozechner/pi-ai";
6231
5908
 
6232
5909
  // src/adapters/db/surgeon-run-log.ts
6233
5910
  import { randomUUID as randomUUID2 } from "crypto";
@@ -6288,9 +5965,9 @@ async function createSurgeonRun(executor, run) {
6288
5965
  args: [
6289
5966
  id,
6290
5967
  run.passType,
6291
- normalizeOptionalString6(run.project),
5968
+ normalizeOptionalString5(run.project),
6292
5969
  startedAt,
6293
- normalizeOptionalString6(run.model ?? void 0),
5970
+ normalizeOptionalString5(run.model ?? void 0),
6294
5971
  run.dryRun ? 1 : 0,
6295
5972
  JSON.stringify(run.config ?? null)
6296
5973
  ]
@@ -6323,7 +6000,7 @@ async function completeSurgeonRun(executor, runId, result) {
6323
6000
  normalizeInteger(result.actionsSkipped),
6324
6001
  normalizeInteger(result.entriesRetired),
6325
6002
  JSON.stringify(result.summaryJson ?? null),
6326
- normalizeOptionalString6(result.error ?? void 0),
6003
+ normalizeOptionalString5(result.error ?? void 0),
6327
6004
  runId.trim()
6328
6005
  ]
6329
6006
  });
@@ -6460,7 +6137,7 @@ async function logSurgeonProposal(executor, proposal) {
6460
6137
  proposal.eligibleForApply ? 1 : 0,
6461
6138
  reviewStatus,
6462
6139
  normalizeTimestamp(reviewedAt ?? void 0),
6463
- normalizeOptionalString6(reviewReason ?? void 0),
6140
+ normalizeOptionalString5(reviewReason ?? void 0),
6464
6141
  normalizeInteger(appliedActionCount ?? 0),
6465
6142
  normalizeTimestamp(proposal.createdAt) ?? (/* @__PURE__ */ new Date()).toISOString()
6466
6143
  ]
@@ -6824,7 +6501,7 @@ function normalizeEntryIds(entryIds) {
6824
6501
  function normalizeStringArray(values) {
6825
6502
  return Array.from(new Set(values.map((value) => value.trim()).filter((value) => value.length > 0)));
6826
6503
  }
6827
- function normalizeOptionalString6(value) {
6504
+ function normalizeOptionalString5(value) {
6828
6505
  if (value === void 0) {
6829
6506
  return null;
6830
6507
  }
@@ -6832,7 +6509,7 @@ function normalizeOptionalString6(value) {
6832
6509
  return trimmed.length > 0 ? trimmed : null;
6833
6510
  }
6834
6511
  function normalizeTimestamp(value) {
6835
- return normalizeOptionalString6(value);
6512
+ return normalizeOptionalString5(value);
6836
6513
  }
6837
6514
  function normalizeInteger(value) {
6838
6515
  if (!Number.isFinite(value)) {
@@ -7125,7 +6802,7 @@ async function listRetirementCandidates(executor, query) {
7125
6802
  }
7126
6803
  async function listSupersessionCandidates(executor, query) {
7127
6804
  const scope = normalizeSupersessionScope(query.scope);
7128
- const type = normalizeOptionalString7(query.type);
6805
+ const type = normalizeOptionalString6(query.type);
7129
6806
  const scopes = scope === "all" ? ["claim_key", "subject"] : [scope];
7130
6807
  const clusters = (await Promise.all(
7131
6808
  scopes.map(async (currentScope) => {
@@ -7139,7 +6816,7 @@ async function listSupersessionCandidates(executor, query) {
7139
6816
  return limit === null ? filteredClusters.slice(offset) : filteredClusters.slice(offset, offset + limit);
7140
6817
  }
7141
6818
  async function countSupersessionCandidates(executor, query) {
7142
- const type = normalizeOptionalString7(query.type);
6819
+ const type = normalizeOptionalString6(query.type);
7143
6820
  const skippedEntryIds = typeof query.skipRecentlyEvaluatedDays === "number" && Number.isFinite(query.skipRecentlyEvaluatedDays) && query.skipRecentlyEvaluatedDays > 0 ? await loadRecentlySkippedSupersessionEntryIds(executor, {
7144
6821
  now: query.now ?? /* @__PURE__ */ new Date(),
7145
6822
  skipRecentlyEvaluatedDays: query.skipRecentlyEvaluatedDays
@@ -7352,17 +7029,17 @@ async function inspectSurgeonEntry(executor, entryId) {
7352
7029
  async function listClaimKeyQualityEntries(executor, query) {
7353
7030
  const whereClauses = [query.includeInactive === true ? "1 = 1" : buildActiveEntryClause("e")];
7354
7031
  const args = [];
7355
- const project = normalizeOptionalString7(query.project);
7032
+ const project = normalizeOptionalString6(query.project);
7356
7033
  if (project) {
7357
7034
  whereClauses.push(`(e.project = ? OR ${buildTagContainsClause("e")})`);
7358
7035
  args.push(project, project);
7359
7036
  }
7360
- const type = normalizeOptionalString7(query.type);
7037
+ const type = normalizeOptionalString6(query.type);
7361
7038
  if (type) {
7362
7039
  whereClauses.push("e.type = ?");
7363
7040
  args.push(type);
7364
7041
  }
7365
- const claimKeyPrefix = normalizeOptionalString7(query.claimKeyPrefix);
7042
+ const claimKeyPrefix = normalizeOptionalString6(query.claimKeyPrefix);
7366
7043
  if (claimKeyPrefix) {
7367
7044
  whereClauses.push("e.claim_key LIKE ?");
7368
7045
  args.push(`${claimKeyPrefix}/%`);
@@ -7394,7 +7071,7 @@ function buildCandidateFilter(query) {
7394
7071
  const protectMinImportance = normalizeNonNegativeInteger(query.protectMinImportance);
7395
7072
  const protectRecalledDays = normalizeNonNegativeInteger(query.protectRecalledDays);
7396
7073
  const protectRecalledCutoffIso = new Date(now.getTime() - protectRecalledDays * DAY_MS).toISOString();
7397
- const currentRunId = normalizeOptionalString7(query.runId);
7074
+ const currentRunId = normalizeOptionalString6(query.runId);
7398
7075
  const whereClauses = [buildActiveEntryClause("e"), "e.expiry <> 'core'", "e.importance < ?", "(e.last_recalled_at IS NULL OR e.last_recalled_at < ?)"];
7399
7076
  const args = [protectMinImportance, protectRecalledCutoffIso];
7400
7077
  if (currentRunId) {
@@ -7407,12 +7084,12 @@ function buildCandidateFilter(query) {
7407
7084
  )`);
7408
7085
  args.push(currentRunId, ...SURGEON_RETIREMENT_SAME_RUN_SUPPRESSION_ACTION_TYPES);
7409
7086
  }
7410
- const project = normalizeOptionalString7(query.project);
7087
+ const project = normalizeOptionalString6(query.project);
7411
7088
  if (project) {
7412
7089
  whereClauses.push(buildTagContainsClause("e"));
7413
7090
  args.push(project);
7414
7091
  }
7415
- const type = normalizeOptionalString7(query.type);
7092
+ const type = normalizeOptionalString6(query.type);
7416
7093
  if (type) {
7417
7094
  whereClauses.push("e.type = ?");
7418
7095
  args.push(type);
@@ -7623,7 +7300,7 @@ function normalizeNonNegativeInteger(value) {
7623
7300
  }
7624
7301
  return Math.max(0, Math.floor(value));
7625
7302
  }
7626
- function normalizeOptionalString7(value) {
7303
+ function normalizeOptionalString6(value) {
7627
7304
  if (value === void 0) {
7628
7305
  return null;
7629
7306
  }
@@ -7713,8 +7390,8 @@ function createSurgeonPort(executor) {
7713
7390
 
7714
7391
  // src/app/surgeon/service.ts
7715
7392
  import { randomUUID as randomUUID9 } from "crypto";
7716
- import fs11 from "fs";
7717
- import path16 from "path";
7393
+ import fs10 from "fs";
7394
+ import path15 from "path";
7718
7395
  import { runAgentLoop } from "@mariozechner/pi-agent-core";
7719
7396
 
7720
7397
  // src/core/surgeon/domain/run-presets.ts
@@ -7994,9 +7671,9 @@ var SHADOW_BUCKET_ORDER = [
7994
7671
  async function runClaimKeyQualityPass(options, deps) {
7995
7672
  const selection = {
7996
7673
  includeInactive: options.includeInactive === true,
7997
- project: normalizeOptionalString8(options.project) ?? null,
7998
- type: normalizeOptionalString8(options.type) ?? null,
7999
- claimKeyPrefix: normalizeOptionalString8(options.claimKeyPrefix) ?? null,
7674
+ project: normalizeOptionalString7(options.project) ?? null,
7675
+ type: normalizeOptionalString7(options.type) ?? null,
7676
+ claimKeyPrefix: normalizeOptionalString7(options.claimKeyPrefix) ?? null,
8000
7677
  entryIds: normalizeStringArray3(options.entryIds ?? [])
8001
7678
  };
8002
7679
  const executionStyle = selection.includeInactive || selection.type !== null || selection.claimKeyPrefix !== null || selection.entryIds.length > 0 ? "targeted" : "autonomous";
@@ -9231,7 +8908,7 @@ function cloneEntry(entry) {
9231
8908
  embedding: entry.embedding ? [...entry.embedding] : void 0
9232
8909
  };
9233
8910
  }
9234
- function normalizeOptionalString8(value) {
8911
+ function normalizeOptionalString7(value) {
9235
8912
  const trimmed = value?.trim();
9236
8913
  return trimmed ? trimmed : null;
9237
8914
  }
@@ -10440,8 +10117,8 @@ async function applyProposalToEntries(input, deps) {
10440
10117
  }
10441
10118
 
10442
10119
  // src/app/surgeon/trace-logger.ts
10443
- import fs10 from "fs";
10444
- import path15 from "path";
10120
+ import fs9 from "fs";
10121
+ import path14 from "path";
10445
10122
  var TRACE_MAX_STRING_LENGTH = 320;
10446
10123
  var TRACE_MAX_ARRAY_ITEMS = 12;
10447
10124
  var TRACE_MAX_OBJECT_KEYS = 20;
@@ -10649,8 +10326,8 @@ function appendTrace(tracePath, payload, logger) {
10649
10326
  return;
10650
10327
  }
10651
10328
  try {
10652
- fs10.mkdirSync(path15.dirname(tracePath), { recursive: true });
10653
- fs10.appendFileSync(tracePath, `${JSON.stringify({ timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...payload })}
10329
+ fs9.mkdirSync(path14.dirname(tracePath), { recursive: true });
10330
+ fs9.appendFileSync(tracePath, `${JSON.stringify({ timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...payload })}
10654
10331
  `, "utf8");
10655
10332
  } catch (error) {
10656
10333
  logger.warn(`failed to write trace file ${tracePath}: ${formatError2(error)}`);
@@ -11547,10 +11224,10 @@ function createQueryCandidatesTool(deps) {
11547
11224
  const offset = normalizeOffset2(params.offset);
11548
11225
  const page = await deps.port.listRetirementCandidates({
11549
11226
  scope,
11550
- type: normalizeOptionalString9(params.type),
11227
+ type: normalizeOptionalString8(params.type),
11551
11228
  importanceMax: params.importance_max,
11552
11229
  minAgeDays: params.min_age_days,
11553
- project: normalizeOptionalString9(params.project) ?? deps.project,
11230
+ project: normalizeOptionalString8(params.project) ?? deps.project,
11554
11231
  limit,
11555
11232
  offset,
11556
11233
  protectRecalledDays: deps.protection.protectRecalledDays,
@@ -11613,7 +11290,7 @@ function normalizeOffset2(value) {
11613
11290
  function normalizeScope2(value) {
11614
11291
  return value === "all" ? "all" : "actionable";
11615
11292
  }
11616
- function normalizeOptionalString9(value) {
11293
+ function normalizeOptionalString8(value) {
11617
11294
  const normalized = value?.trim();
11618
11295
  return normalized ? normalized : void 0;
11619
11296
  }
@@ -11639,7 +11316,7 @@ function createSimulateRecallTool(deps) {
11639
11316
  if (!deps.recallPorts) {
11640
11317
  throw new Error("Recall simulation is unavailable because no embedding-enabled recall ports are configured.");
11641
11318
  }
11642
- const excludeEntryId = normalizeOptionalString10(params.exclude_entry_id);
11319
+ const excludeEntryId = normalizeOptionalString9(params.exclude_entry_id);
11643
11320
  const results = await recall(
11644
11321
  {
11645
11322
  text: params.query.trim(),
@@ -11673,17 +11350,17 @@ function createSimulationRecallPorts(inner, excludeEntryId) {
11673
11350
  }
11674
11351
  return results.filter((result) => result.entry.id !== excludeEntryId);
11675
11352
  },
11676
- async fetchPredecessors(params) {
11677
- if (!inner.fetchPredecessors) {
11353
+ async expandNeighborhood(request) {
11354
+ if (!inner.expandNeighborhood) {
11678
11355
  return [];
11679
11356
  }
11680
- const activeEntryIds = excludeEntryId ? params.activeEntryIds.filter((id) => id !== excludeEntryId) : params.activeEntryIds;
11681
- if (activeEntryIds.length === 0) {
11357
+ const seedIds = excludeEntryId ? request.seedIds.filter((id) => id !== excludeEntryId) : request.seedIds;
11358
+ if (seedIds.length === 0) {
11682
11359
  return [];
11683
11360
  }
11684
- const results = await inner.fetchPredecessors({
11685
- ...params,
11686
- activeEntryIds
11361
+ const results = await inner.expandNeighborhood({
11362
+ ...request,
11363
+ seedIds
11687
11364
  });
11688
11365
  if (!excludeEntryId) {
11689
11366
  return results;
@@ -11704,7 +11381,7 @@ function normalizeLimit3(value) {
11704
11381
  }
11705
11382
  return Math.floor(value);
11706
11383
  }
11707
- function normalizeOptionalString10(value) {
11384
+ function normalizeOptionalString9(value) {
11708
11385
  const normalized = value?.trim();
11709
11386
  return normalized ? normalized : void 0;
11710
11387
  }
@@ -11984,7 +11661,7 @@ function createQuerySupersessionCandidatesTool(deps) {
11984
11661
  const scope = normalizeScope3(params.scope);
11985
11662
  const limit = normalizeLimit4(params.limit);
11986
11663
  const offset = normalizeOffset3(params.offset);
11987
- const type = normalizeOptionalString11(params.type);
11664
+ const type = normalizeOptionalString10(params.type);
11988
11665
  const progress = deps.completionGuards?.supersession.snapshot();
11989
11666
  if ((scope === "subject" || scope === "all") && shouldBlockLowerConfidenceScope(progress)) {
11990
11667
  return toolResult({
@@ -12092,7 +11769,7 @@ function normalizeScope3(value) {
12092
11769
  }
12093
11770
  return "claim_key";
12094
11771
  }
12095
- function normalizeOptionalString11(value) {
11772
+ function normalizeOptionalString10(value) {
12096
11773
  const normalized = value?.trim();
12097
11774
  return normalized ? normalized : void 0;
12098
11775
  }
@@ -13199,8 +12876,8 @@ function resolveTracePath(tracePath, passType, runId) {
13199
12876
  return void 0;
13200
12877
  }
13201
12878
  try {
13202
- if (fs11.statSync(tracePath).isDirectory()) {
13203
- return path16.join(tracePath, `surgeon-${passType}-${runId}.jsonl`);
12879
+ if (fs10.statSync(tracePath).isDirectory()) {
12880
+ return path15.join(tracePath, `surgeon-${passType}-${runId}.jsonl`);
13204
12881
  }
13205
12882
  } catch {
13206
12883
  return tracePath;
@@ -14102,7 +13779,7 @@ function formatValue(value) {
14102
13779
  }
14103
13780
 
14104
13781
  // src/app/scenarios/claim-keys/deterministic-fixtures.ts
14105
- import { createHash as createHash3 } from "crypto";
13782
+ import { createHash as createHash2 } from "crypto";
14106
13783
  var DEFAULT_CONTEXT_WINDOW_TOKENS2 = 16e3;
14107
13784
  var DEFAULT_MAX_OUTPUT_TOKENS = 4e3;
14108
13785
  var EMBEDDING_DIMENSIONS = 1024;
@@ -14160,7 +13837,7 @@ function hashToVector(text2, dimensions) {
14160
13837
  const vector = [];
14161
13838
  let counter = 0;
14162
13839
  while (vector.length < dimensions) {
14163
- const block = createHash3("sha256").update(text2).update(String(counter)).digest();
13840
+ const block = createHash2("sha256").update(text2).update(String(counter)).digest();
14164
13841
  for (let offset = 0; offset + 4 <= block.length && vector.length < dimensions; offset += 4) {
14165
13842
  vector.push(block.readInt32LE(offset) / 2147483647);
14166
13843
  }
@@ -14202,7 +13879,7 @@ function isFixtureError(value) {
14202
13879
 
14203
13880
  // src/app/scenarios/claim-keys/fixture-loader.ts
14204
13881
  import { readFile } from "fs/promises";
14205
- import path18 from "path";
13882
+ import path17 from "path";
14206
13883
 
14207
13884
  // src/app/scenarios/claim-keys/validation/shared.ts
14208
13885
  var SUPPORTED_PROPOSAL_SCOPES = ["single_entry", "cluster"];
@@ -14532,12 +14209,12 @@ function readRequiredTrue(value, label, filePath) {
14532
14209
 
14533
14210
  // src/app/scenarios/claim-keys/validation/scenario-root.ts
14534
14211
  import { existsSync } from "fs";
14535
- import path17 from "path";
14212
+ import path16 from "path";
14536
14213
  import { fileURLToPath as fileURLToPath2 } from "url";
14537
14214
  var SCENARIO_ROOT_SEGMENTS = ["tests", "scenarios", "claim-keys"];
14538
14215
  function getDefaultClaimKeyScenarioRoot(options = {}) {
14539
- const moduleDirectory = path17.dirname(fileURLToPath2(options.moduleUrl ?? import.meta.url));
14540
- const startDirectories = Array.from(/* @__PURE__ */ new Set([path17.resolve(options.cwd ?? process.cwd()), moduleDirectory]));
14216
+ const moduleDirectory = path16.dirname(fileURLToPath2(options.moduleUrl ?? import.meta.url));
14217
+ const startDirectories = Array.from(/* @__PURE__ */ new Set([path16.resolve(options.cwd ?? process.cwd()), moduleDirectory]));
14541
14218
  for (const startDirectory of startDirectories) {
14542
14219
  const discovered = findScenarioRootFrom(startDirectory);
14543
14220
  if (discovered) {
@@ -14559,24 +14236,24 @@ function readOptionalRelativeFixturePath(value, label, filePath, rootDir) {
14559
14236
  return readRelativeFixturePath(value, label, filePath, rootDir);
14560
14237
  }
14561
14238
  function normalizeFixturePath(relativePath, rootDir, filePath, label) {
14562
- if (path17.isAbsolute(relativePath)) {
14239
+ if (path16.isAbsolute(relativePath)) {
14563
14240
  throw new Error(`Invalid scenario ${filePath}: ${label} must be relative to the scenario root.`);
14564
14241
  }
14565
- const resolved = path17.resolve(rootDir, relativePath);
14566
- const relative = path17.relative(rootDir, resolved);
14567
- if (relative.startsWith("..") || path17.isAbsolute(relative)) {
14242
+ const resolved = path16.resolve(rootDir, relativePath);
14243
+ const relative = path16.relative(rootDir, resolved);
14244
+ if (relative.startsWith("..") || path16.isAbsolute(relative)) {
14568
14245
  throw new Error(`Invalid scenario ${filePath}: ${label} must stay inside the scenario root.`);
14569
14246
  }
14570
- return relative.split(path17.sep).join("/");
14247
+ return relative.split(path16.sep).join("/");
14571
14248
  }
14572
14249
  function findScenarioRootFrom(startDirectory) {
14573
- let currentDirectory = path17.resolve(startDirectory);
14250
+ let currentDirectory = path16.resolve(startDirectory);
14574
14251
  while (true) {
14575
- const candidate = path17.join(currentDirectory, ...SCENARIO_ROOT_SEGMENTS);
14252
+ const candidate = path16.join(currentDirectory, ...SCENARIO_ROOT_SEGMENTS);
14576
14253
  if (existsSync(candidate)) {
14577
14254
  return candidate;
14578
14255
  }
14579
- const parentDirectory = path17.dirname(currentDirectory);
14256
+ const parentDirectory = path16.dirname(currentDirectory);
14580
14257
  if (parentDirectory === currentDirectory) {
14581
14258
  return void 0;
14582
14259
  }
@@ -14919,7 +14596,7 @@ async function loadSeedFixtureEntries(rootDir, relativePath) {
14919
14596
  if (!relativePath) {
14920
14597
  return null;
14921
14598
  }
14922
- const parsed = await readJsonFile(path18.join(rootDir, relativePath));
14599
+ const parsed = await readJsonFile(path17.join(rootDir, relativePath));
14923
14600
  const seedEntries = readSeedEntries(parsed, relativePath);
14924
14601
  if (!seedEntries) {
14925
14602
  throw new Error(`Seed fixture ${relativePath} must contain an array.`);
@@ -14982,7 +14659,7 @@ async function readArrayFixture(rootDir, relativePath) {
14982
14659
  if (!relativePath) {
14983
14660
  return null;
14984
14661
  }
14985
- const parsed = await readJsonFile(path18.join(rootDir, relativePath));
14662
+ const parsed = await readJsonFile(path17.join(rootDir, relativePath));
14986
14663
  if (!Array.isArray(parsed)) {
14987
14664
  throw new Error(`Fixture file ${relativePath} must contain a JSON array.`);
14988
14665
  }
@@ -15036,7 +14713,7 @@ function readExtractionImportance(value, label, filePath) {
15036
14713
 
15037
14714
  // src/app/scenarios/claim-keys/load-scenarios.ts
15038
14715
  import { readdir, readFile as readFile2 } from "fs/promises";
15039
- import path19 from "path";
14716
+ import path18 from "path";
15040
14717
 
15041
14718
  // src/app/scenarios/claim-keys/validation/expectations.ts
15042
14719
  var EXPECTATION_KEYS = /* @__PURE__ */ new Set(["warnings", "rows", "rowCount", "proposals", "storeResult", "surgeonSummary"]);
@@ -15298,13 +14975,13 @@ function validateClaimKeyScenario(input, filePath, rootDir = getDefaultClaimKeyS
15298
14975
  async function discoverScenarioFiles(rootDir) {
15299
14976
  const files = [];
15300
14977
  for (const kind of SUPPORTED_KINDS2) {
15301
- const directory = path19.join(rootDir, kind);
14978
+ const directory = path18.join(rootDir, kind);
15302
14979
  const entries = await readdir(directory, { withFileTypes: true });
15303
14980
  for (const entry of entries) {
15304
14981
  if (!entry.isFile() || !entry.name.endsWith(".json")) {
15305
14982
  continue;
15306
14983
  }
15307
- files.push(path19.join(directory, entry.name));
14984
+ files.push(path18.join(directory, entry.name));
15308
14985
  }
15309
14986
  }
15310
14987
  return files.sort();
@@ -15322,11 +14999,11 @@ async function readScenarioJsonFile(filePath) {
15322
14999
 
15323
15000
  // src/app/scenarios/claim-keys/sandbox.ts
15324
15001
  import { mkdir, rm } from "fs/promises";
15325
- import path20 from "path";
15002
+ import path19 from "path";
15326
15003
  var SANDBOX_DB_FILENAME = "knowledge.db";
15327
15004
  async function createClaimKeyScenarioSandbox(root) {
15328
- const resolvedRoot = path20.resolve(root);
15329
- const dbPath = path20.join(resolvedRoot, SANDBOX_DB_FILENAME);
15005
+ const resolvedRoot = path19.resolve(root);
15006
+ const dbPath = path19.join(resolvedRoot, SANDBOX_DB_FILENAME);
15330
15007
  await mkdir(resolvedRoot, { recursive: true });
15331
15008
  await removeDatabaseFiles(dbPath);
15332
15009
  const database = await createDatabase(dbPath);
@@ -15351,7 +15028,7 @@ async function removeDatabaseFiles(dbPath) {
15351
15028
  import { randomUUID as randomUUID10 } from "crypto";
15352
15029
  var DEFAULT_SCENARIO_CREATED_AT = "2026-04-01T10:00:00.000Z";
15353
15030
  function buildClaimKeyScenarioSeedEntry(seedEntry) {
15354
- const seedClaimKey = normalizeOptionalString12(seedEntry.claim_key);
15031
+ const seedClaimKey = normalizeOptionalString11(seedEntry.claim_key);
15355
15032
  const preserveLegacyStoredClaimKey = shouldPreserveLegacyStoredClaimKey(seedClaimKey);
15356
15033
  const validatedInput = validateSeedStoreInput(seedEntry, preserveLegacyStoredClaimKey);
15357
15034
  const lifecycle = preserveLegacyStoredClaimKey ? resolveLegacySeedClaimKeyLifecycle(seedEntry) : resolveSeedClaimKeyLifecycle(seedEntry, validatedInput);
@@ -15373,11 +15050,11 @@ function buildClaimKeyScenarioSeedEntry(seedEntry) {
15373
15050
  quality_score: 0.5,
15374
15051
  recall_count: 0,
15375
15052
  last_recalled_at: void 0,
15376
- superseded_by: normalizeOptionalString12(seedEntry.superseded_by),
15053
+ superseded_by: normalizeOptionalString11(seedEntry.superseded_by),
15377
15054
  valid_from: validatedInput.valid_from,
15378
15055
  valid_to: validatedInput.valid_to,
15379
15056
  claim_key: preserveLegacyStoredClaimKey ? seedClaimKey : lifecycle?.claim_key,
15380
- claim_key_raw: preserveLegacyStoredClaimKey ? normalizeOptionalString12(seedEntry.claim_key_raw) : lifecycle?.claim_key_raw,
15057
+ claim_key_raw: preserveLegacyStoredClaimKey ? normalizeOptionalString11(seedEntry.claim_key_raw) : lifecycle?.claim_key_raw,
15381
15058
  claim_key_status: lifecycle?.claim_key_status,
15382
15059
  claim_key_source: lifecycle?.claim_key_source,
15383
15060
  claim_key_confidence: lifecycle?.claim_key_confidence,
@@ -15392,8 +15069,8 @@ function buildClaimKeyScenarioSeedEntry(seedEntry) {
15392
15069
  user_id: validatedInput.user_id,
15393
15070
  project: validatedInput.project,
15394
15071
  retired: seedEntry.retired ?? false,
15395
- retired_at: normalizeOptionalString12(seedEntry.retired_at),
15396
- retired_reason: normalizeOptionalString12(seedEntry.retired_reason),
15072
+ retired_at: normalizeOptionalString11(seedEntry.retired_at),
15073
+ retired_reason: normalizeOptionalString11(seedEntry.retired_reason),
15397
15074
  created_at: createdAt,
15398
15075
  updated_at: updatedAt
15399
15076
  };
@@ -15479,14 +15156,14 @@ function resolveLegacySeedClaimKeyLifecycle(seedEntry) {
15479
15156
  }
15480
15157
  return {
15481
15158
  claim_key: seedEntry.claim_key.trim(),
15482
- claim_key_raw: normalizeOptionalString12(seedEntry.claim_key_raw),
15159
+ claim_key_raw: normalizeOptionalString11(seedEntry.claim_key_raw),
15483
15160
  claim_key_status: seedEntry.claim_key_status,
15484
15161
  claim_key_source: seedEntry.claim_key_source,
15485
15162
  claim_key_confidence: seedEntry.claim_key_confidence,
15486
15163
  claim_key_rationale: seedEntry.claim_key_rationale.trim(),
15487
- claim_support_source_kind: normalizeOptionalString12(seedEntry.claim_support_source_kind),
15488
- claim_support_locator: normalizeOptionalString12(seedEntry.claim_support_locator),
15489
- claim_support_observed_at: normalizeOptionalString12(seedEntry.claim_support_observed_at),
15164
+ claim_support_source_kind: normalizeOptionalString11(seedEntry.claim_support_source_kind),
15165
+ claim_support_locator: normalizeOptionalString11(seedEntry.claim_support_locator),
15166
+ claim_support_observed_at: normalizeOptionalString11(seedEntry.claim_support_observed_at),
15490
15167
  claim_support_mode: seedEntry.claim_support_mode
15491
15168
  };
15492
15169
  }
@@ -15497,7 +15174,7 @@ function shouldPreserveLegacyStoredClaimKey(claimKey) {
15497
15174
  const normalized = normalizeClaimKey(claimKey);
15498
15175
  return !normalized.ok || normalized.value.claimKey !== claimKey;
15499
15176
  }
15500
- function normalizeOptionalString12(value) {
15177
+ function normalizeOptionalString11(value) {
15501
15178
  const normalized = value?.trim();
15502
15179
  return normalized && normalized.length > 0 ? normalized : void 0;
15503
15180
  }
@@ -15517,7 +15194,7 @@ async function listClaimKeyScenariosRuntime(options = {}) {
15517
15194
  }
15518
15195
  async function runClaimKeyScenariosRuntime(options = {}) {
15519
15196
  const runId = buildRunId();
15520
- const artifactRoot = path21.resolve(DEFAULT_ARTIFACT_ROOT, runId);
15197
+ const artifactRoot = path20.resolve(DEFAULT_ARTIFACT_ROOT, runId);
15521
15198
  await mkdir2(artifactRoot, { recursive: true });
15522
15199
  let scenarios;
15523
15200
  try {
@@ -15569,11 +15246,11 @@ function filterClaimKeyScenarios(scenarios, options) {
15569
15246
  }
15570
15247
  async function runOneClaimKeyScenario(scenario, options) {
15571
15248
  const startedAt = Date.now();
15572
- const scenarioArtifactRoot = path21.join(options.artifactRoot, scenario.id);
15573
- const sandboxRoot = path21.join(scenarioArtifactRoot, "sandbox");
15249
+ const scenarioArtifactRoot = path20.join(options.artifactRoot, scenario.id);
15250
+ const sandboxRoot = path20.join(scenarioArtifactRoot, "sandbox");
15574
15251
  const warnings = [];
15575
15252
  await mkdir2(scenarioArtifactRoot, { recursive: true });
15576
- await writeJson(path21.join(scenarioArtifactRoot, "scenario.json"), scenario);
15253
+ await writeJson(path20.join(scenarioArtifactRoot, "scenario.json"), scenario);
15577
15254
  let actual = {
15578
15255
  warnings: [],
15579
15256
  rows: [],
@@ -15686,7 +15363,7 @@ async function runIngestScenario(scenario, database, warnings, rootDir) {
15686
15363
  throw new Error(`Scenario ${scenario.id} is missing extraction fixture responses.`);
15687
15364
  }
15688
15365
  const result = await ingestPath(
15689
- path21.join(rootDir, scenario.input.transcriptFile),
15366
+ path20.join(rootDir, scenario.input.transcriptFile),
15690
15367
  {
15691
15368
  files: localTranscriptFiles,
15692
15369
  transcript: openClawTranscriptParser,
@@ -15758,7 +15435,7 @@ async function runSurgeonScenario(scenario, database, _warnings, rootDir) {
15758
15435
  {
15759
15436
  port: createSurgeonPort(database),
15760
15437
  config: null,
15761
- model: getModel2("openai", "gpt-5.4-mini"),
15438
+ model: getModel("openai", "gpt-5.4-mini"),
15762
15439
  now: () => SCENARIO_NOW,
15763
15440
  ...claimExtractionResponses ? {
15764
15441
  createClaimExtractionLlm: () => createFixtureLlm(claimExtractionResponses)
@@ -15828,20 +15505,20 @@ async function loadLatestSurgeonProposals(database, runId) {
15828
15505
  }));
15829
15506
  }
15830
15507
  async function writeScenarioArtifacts(scenarioArtifactRoot, actual, assertionResults, diffSummary) {
15831
- await writeJson(path21.join(scenarioArtifactRoot, "actual.json"), actual);
15832
- await writeJson(path21.join(scenarioArtifactRoot, "diff.json"), {
15508
+ await writeJson(path20.join(scenarioArtifactRoot, "actual.json"), actual);
15509
+ await writeJson(path20.join(scenarioArtifactRoot, "diff.json"), {
15833
15510
  assertions: assertionResults,
15834
15511
  diffSummary
15835
15512
  });
15836
- await writeJson(path21.join(scenarioArtifactRoot, "warnings.json"), actual.warnings);
15513
+ await writeJson(path20.join(scenarioArtifactRoot, "warnings.json"), actual.warnings);
15837
15514
  if (actual.storeResult) {
15838
- await writeJson(path21.join(scenarioArtifactRoot, "store-result.json"), actual.storeResult);
15515
+ await writeJson(path20.join(scenarioArtifactRoot, "store-result.json"), actual.storeResult);
15839
15516
  }
15840
15517
  if (actual.surgeonSummary) {
15841
- await writeJson(path21.join(scenarioArtifactRoot, "surgeon-summary.json"), actual.surgeonSummary);
15518
+ await writeJson(path20.join(scenarioArtifactRoot, "surgeon-summary.json"), actual.surgeonSummary);
15842
15519
  }
15843
15520
  if (actual.proposals.length > 0) {
15844
- await writeJson(path21.join(scenarioArtifactRoot, "proposals.json"), actual.proposals);
15521
+ await writeJson(path20.join(scenarioArtifactRoot, "proposals.json"), actual.proposals);
15845
15522
  }
15846
15523
  }
15847
15524
  async function writeJson(filePath, value) {
@@ -15973,12 +15650,12 @@ import { InvalidArgumentError as InvalidArgumentError6, Option as Option5 } from
15973
15650
 
15974
15651
  // src/app/surgeon/runtime.ts
15975
15652
  import { copyFile, mkdir as mkdir3 } from "fs/promises";
15976
- import path22 from "path";
15653
+ import path21 from "path";
15977
15654
  import { fileURLToPath as fileURLToPath3 } from "url";
15978
- import { getModel as getModel3 } from "@mariozechner/pi-ai";
15655
+ import { getModel as getModel2 } from "@mariozechner/pi-ai";
15979
15656
  var DEFAULT_SURGEON_PROVIDER = "openai";
15980
15657
  var DEFAULT_SURGEON_MODEL = "gpt-5.4-mini";
15981
- var getModelWithStrings2 = getModel3;
15658
+ var getModelWithStrings = getModel2;
15982
15659
  async function runSurgeonRuntime(input) {
15983
15660
  const runtime = loadRuntimeConfig(input);
15984
15661
  const database = await createDatabase(runtime.dbPath);
@@ -15988,7 +15665,7 @@ async function runSurgeonRuntime(input) {
15988
15665
  const modelSelection = resolveSurgeonModel(runtime.config, input);
15989
15666
  const claimExtractionConfig = selection.includesClaimKeyQuality ? resolveClaimExtractionConfig(runtime.config) : { enabled: false };
15990
15667
  const claimModelSelection = claimExtractionConfig.enabled ? resolveModel(runtime.config, "claim") : null;
15991
- const model = getModelWithStrings2(modelSelection.provider, modelSelection.modelId);
15668
+ const model = getModelWithStrings(modelSelection.provider, modelSelection.modelId);
15992
15669
  const credentials = resolveLlmCredentials(runtime.config, modelSelection.provider, input.env ?? process.env);
15993
15670
  const claimCredentials = claimModelSelection && claimModelSelection.provider === modelSelection.provider ? credentials : claimModelSelection ? resolveLlmCredentials(runtime.config, claimModelSelection.provider, input.env ?? process.env) : null;
15994
15671
  let recallPorts;
@@ -16114,7 +15791,7 @@ async function reviewSurgeonProposalRuntime(input) {
16114
15791
  if (proposal.reviewStatus !== "open") {
16115
15792
  throw new Error(`Proposal ${proposal.id} was already reviewed as ${proposal.reviewStatus}.`);
16116
15793
  }
16117
- const reviewReason = normalizeOptionalString13(input.reason);
15794
+ const reviewReason = normalizeOptionalString12(input.reason);
16118
15795
  if (!reviewReason) {
16119
15796
  throw new Error("Review reason is required.");
16120
15797
  }
@@ -16173,8 +15850,8 @@ async function reviewSurgeonProposalRuntime(input) {
16173
15850
  }
16174
15851
  }
16175
15852
  function loadRuntimeConfig(input) {
16176
- const dbPathOverride = normalizeOptionalString13(input.dbPath) ?? normalizeOptionalString13(input.env?.AGENR_DB_PATH);
16177
- const configPathOverride = normalizeOptionalString13(input.env?.AGENR_CONFIG_PATH);
15853
+ const dbPathOverride = normalizeOptionalString12(input.dbPath) ?? normalizeOptionalString12(input.env?.AGENR_DB_PATH);
15854
+ const configPathOverride = normalizeOptionalString12(input.env?.AGENR_CONFIG_PATH);
16178
15855
  const config = readConfig({
16179
15856
  configPath: configPathOverride,
16180
15857
  dbPath: dbPathOverride
@@ -16187,8 +15864,8 @@ function loadRuntimeConfig(input) {
16187
15864
  function resolveSurgeonModel(config, input) {
16188
15865
  const surgeonModel = config.surgeon?.model;
16189
15866
  return {
16190
- provider: normalizeOptionalString13(input.provider) ?? normalizeOptionalString13(surgeonModel?.provider) ?? normalizeOptionalString13(config.provider) ?? DEFAULT_SURGEON_PROVIDER,
16191
- modelId: normalizeOptionalString13(input.model) ?? normalizeOptionalString13(surgeonModel?.model) ?? normalizeOptionalString13(config.model) ?? DEFAULT_SURGEON_MODEL
15867
+ provider: normalizeOptionalString12(input.provider) ?? normalizeOptionalString12(surgeonModel?.provider) ?? normalizeOptionalString12(config.provider) ?? DEFAULT_SURGEON_PROVIDER,
15868
+ modelId: normalizeOptionalString12(input.model) ?? normalizeOptionalString12(surgeonModel?.model) ?? normalizeOptionalString12(config.model) ?? DEFAULT_SURGEON_MODEL
16192
15869
  };
16193
15870
  }
16194
15871
  function resolveRuntimeSelection(input) {
@@ -16218,7 +15895,7 @@ async function backupDatabaseFile(dbPath) {
16218
15895
  }
16219
15896
  const sourcePath = resolveFilesystemPath(dbPath);
16220
15897
  const backupPath = `${sourcePath}.surgeon-backup-${(/* @__PURE__ */ new Date()).toISOString().replaceAll(":", "-").replaceAll(".", "-")}`;
16221
- await mkdir3(path22.dirname(backupPath), { recursive: true });
15898
+ await mkdir3(path21.dirname(backupPath), { recursive: true });
16222
15899
  await copyFile(sourcePath, backupPath);
16223
15900
  await copySidecarIfPresent(`${sourcePath}-wal`, `${backupPath}-wal`);
16224
15901
  await copySidecarIfPresent(`${sourcePath}-shm`, `${backupPath}-shm`);
@@ -16236,18 +15913,18 @@ async function copySidecarIfPresent(sourcePath, targetPath) {
16236
15913
  }
16237
15914
  function resolveFilesystemPath(value) {
16238
15915
  if (!value.startsWith("file:")) {
16239
- return path22.resolve(value);
15916
+ return path21.resolve(value);
16240
15917
  }
16241
15918
  try {
16242
15919
  return fileURLToPath3(value);
16243
15920
  } catch {
16244
- return path22.resolve(value.slice("file:".length));
15921
+ return path21.resolve(value.slice("file:".length));
16245
15922
  }
16246
15923
  }
16247
15924
  function isMissingFileError2(error) {
16248
15925
  return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
16249
15926
  }
16250
- function normalizeOptionalString13(value) {
15927
+ function normalizeOptionalString12(value) {
16251
15928
  const normalized = value?.trim();
16252
15929
  return normalized && normalized.length > 0 ? normalized : void 0;
16253
15930
  }
@@ -16330,9 +16007,9 @@ function registerSurgeonCommand(program2) {
16330
16007
  try {
16331
16008
  const backlog = await loadSurgeonBacklogRuntime({
16332
16009
  state: options.state,
16333
- issueKind: normalizeOptionalString3(options.issueKind),
16010
+ issueKind: normalizeOptionalString2(options.issueKind),
16334
16011
  eligibleOnly: options.eligibleOnly === true,
16335
- entryId: normalizeOptionalString3(options.entryId),
16012
+ entryId: normalizeOptionalString2(options.entryId),
16336
16013
  limit: options.limit,
16337
16014
  offset: options.offset,
16338
16015
  env: process.env
@@ -16341,8 +16018,8 @@ function registerSurgeonCommand(program2) {
16341
16018
  renderBacklog(backlog, {
16342
16019
  state: options.state ?? "open",
16343
16020
  eligibleOnly: options.eligibleOnly === true,
16344
- issueKind: normalizeOptionalString3(options.issueKind),
16345
- entryId: normalizeOptionalString3(options.entryId),
16021
+ issueKind: normalizeOptionalString2(options.issueKind),
16022
+ entryId: normalizeOptionalString2(options.entryId),
16346
16023
  limit: options.limit ?? 20,
16347
16024
  offset: options.offset ?? 0
16348
16025
  })
@@ -16381,7 +16058,7 @@ function registerSurgeonCommand(program2) {
16381
16058
  });
16382
16059
  surgeonCommand.command("review <proposalId>").description("Apply or reject one open proposal").addOption(new Option5("--decision <decision>", "Review decision").choices(["apply", "reject"]).makeOptionMandatory(true)).option("--reason <text>", "Why this review decision was taken").action(async (proposalId, options) => {
16383
16060
  try {
16384
- const reason = normalizeOptionalString3(options.reason);
16061
+ const reason = normalizeOptionalString2(options.reason);
16385
16062
  if (!reason) {
16386
16063
  throw new InvalidArgumentError6("Review reason is required.");
16387
16064
  }
@@ -16416,10 +16093,10 @@ function normalizeSurgeonRunCommand(options) {
16416
16093
  contextLimit: options.contextLimit,
16417
16094
  skipEvaluatedDays: options.skipEvaluatedDays,
16418
16095
  apply: options.apply === true,
16419
- model: normalizeOptionalString3(options.model),
16420
- provider: normalizeOptionalString3(options.provider),
16096
+ model: normalizeOptionalString2(options.model),
16097
+ provider: normalizeOptionalString2(options.provider),
16421
16098
  verbose: options.verbose === true,
16422
- tracePath: normalizeOptionalString3(options.trace),
16099
+ tracePath: normalizeOptionalString2(options.trace),
16423
16100
  json: options.json === true
16424
16101
  };
16425
16102
  }
@@ -17140,12 +16817,12 @@ import { Option as Option6 } from "commander";
17140
16817
  // src/app/openclaw/inspect.ts
17141
16818
  async function loadOpenClawEntryTraceRuntime(input) {
17142
16819
  const selector = normalizeTraceSelector(input);
17143
- const configPathOverride = normalizeOptionalString14(input.env?.AGENR_CONFIG_PATH);
16820
+ const configPathOverride = normalizeOptionalString13(input.env?.AGENR_CONFIG_PATH);
17144
16821
  const config = readConfig({
17145
16822
  configPath: configPathOverride,
17146
- dbPath: normalizeOptionalString14(input.dbPath) ?? normalizeOptionalString14(input.env?.AGENR_DB_PATH)
16823
+ dbPath: normalizeOptionalString13(input.dbPath) ?? normalizeOptionalString13(input.env?.AGENR_DB_PATH)
17147
16824
  });
17148
- const dbPath = normalizeOptionalString14(input.dbPath) ?? normalizeOptionalString14(input.env?.AGENR_DB_PATH) ?? resolveDbPath(config);
16825
+ const dbPath = normalizeOptionalString13(input.dbPath) ?? normalizeOptionalString13(input.env?.AGENR_DB_PATH) ?? resolveDbPath(config);
17149
16826
  const database = await createDatabase(dbPath);
17150
16827
  const repository = createOpenClawRepository(database);
17151
16828
  try {
@@ -17177,8 +16854,8 @@ async function resolveTraceEntryId(repository, selector) {
17177
16854
  return entry.id;
17178
16855
  }
17179
16856
  function normalizeTraceSelector(selector) {
17180
- const id = normalizeOptionalString14(selector.id);
17181
- const subject = normalizeOptionalString14(selector.subject);
16857
+ const id = normalizeOptionalString13(selector.id);
16858
+ const subject = normalizeOptionalString13(selector.subject);
17182
16859
  const last = selector.last === true;
17183
16860
  const count = (id ? 1 : 0) + (subject ? 1 : 0) + (last ? 1 : 0);
17184
16861
  if (count !== 1) {
@@ -17190,7 +16867,7 @@ function normalizeTraceSelector(selector) {
17190
16867
  last
17191
16868
  };
17192
16869
  }
17193
- function normalizeOptionalString14(value) {
16870
+ function normalizeOptionalString13(value) {
17194
16871
  const normalized = value?.trim();
17195
16872
  return normalized && normalized.length > 0 ? normalized : void 0;
17196
16873
  }