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/CHANGELOG.md +44 -0
- package/dist/adapters/openclaw/index.d.ts +1 -1
- package/dist/adapters/openclaw/index.js +1466 -124
- package/dist/{chunk-MEHOGUZE.js → chunk-6T5RXGIR.js} +989 -70
- package/dist/{chunk-Y2BC7RCE.js → chunk-7TDALVPY.js} +1434 -305
- package/dist/{chunk-XD3446YW.js → chunk-DGV6D6Q3.js} +2 -21
- package/dist/chunk-IMQIJPIP.js +886 -0
- package/dist/chunk-MJIB6J5S.js +3059 -0
- package/dist/cli.js +278 -601
- package/dist/core/recall/index.d.ts +535 -107
- package/dist/core/recall/index.js +37 -3
- package/dist/internal-eval-server.d.ts +1 -0
- package/dist/internal-eval-server.js +6 -0
- package/dist/internal-recall-eval-server.js +5 -1816
- package/dist/ports-Nj5nd2Ri.d.ts +719 -0
- package/package.json +3 -2
- package/dist/ports-D2NOK2gR.d.ts +0 -256
package/dist/cli.js
CHANGED
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
tokenizeGroundingText,
|
|
32
32
|
validateEntriesWithIndexes,
|
|
33
33
|
validateSupersessionRules
|
|
34
|
-
} from "./chunk-
|
|
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-
|
|
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-
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
2691
|
-
const modelId =
|
|
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
|
|
2743
|
-
import
|
|
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
|
|
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) =>
|
|
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
|
|
2854
|
-
import
|
|
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 =
|
|
2858
|
-
const stat = await
|
|
2495
|
+
const resolvedTargetPath = path5.resolve(targetPath);
|
|
2496
|
+
const stat = await fs3.stat(resolvedTargetPath);
|
|
2859
2497
|
if (stat.isFile()) {
|
|
2860
|
-
return matchesOpenClawTranscriptFile(
|
|
2498
|
+
return matchesOpenClawTranscriptFile(path5.basename(resolvedTargetPath)) ? [resolvedTargetPath] : [];
|
|
2861
2499
|
}
|
|
2862
|
-
const entries = await
|
|
2863
|
-
return entries.filter((entry) => entry.isFile() && matchesOpenClawTranscriptFile(entry.name)).map((entry) =>
|
|
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 =
|
|
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
|
|
3126
|
-
return stat.isFile() ?
|
|
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 =
|
|
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
|
|
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 =
|
|
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:
|
|
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:
|
|
2919
|
+
recent: normalizeOptionalString2(options.recent),
|
|
3282
2920
|
concurrency: options.concurrency ?? DEFAULT_EPISODE_INGEST_CONCURRENCY,
|
|
3283
|
-
dbOverride:
|
|
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
|
|
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
|
|
3300
|
-
import
|
|
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 =
|
|
3304
|
-
const stat = await
|
|
2941
|
+
const resolvedTargetPath = path7.resolve(targetPath);
|
|
2942
|
+
const stat = await fs5.stat(resolvedTargetPath);
|
|
3305
2943
|
if (stat.isFile()) {
|
|
3306
|
-
return matchesProcedureFileName(
|
|
2944
|
+
return matchesProcedureFileName(path7.basename(resolvedTargetPath)) ? [resolvedTargetPath] : [];
|
|
3307
2945
|
}
|
|
3308
2946
|
const recursive = options.recursive ?? true;
|
|
3309
|
-
const entries = recursive ? await
|
|
3310
|
-
return entries.filter((entry) => entry.isFile() && matchesProcedureFileName(entry.name)).map((entry) =>
|
|
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
|
|
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 =
|
|
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:
|
|
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 ${
|
|
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 ${
|
|
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),
|
|
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(
|
|
3563
|
+
clack4.log.step(buildSkippedMessage(path9.basename(result.file)));
|
|
3926
3564
|
} else {
|
|
3927
|
-
clack4.log.step(buildSkippedMessage(
|
|
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(
|
|
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(
|
|
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 =
|
|
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
|
|
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
|
|
4376
|
-
import
|
|
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
|
|
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
|
|
4050
|
+
return os.homedir();
|
|
4413
4051
|
}
|
|
4414
4052
|
if (trimmed.startsWith("~/")) {
|
|
4415
|
-
return
|
|
4053
|
+
return path10.join(os.homedir(), trimmed.slice(2));
|
|
4416
4054
|
}
|
|
4417
4055
|
if (trimmed.startsWith("~\\")) {
|
|
4418
|
-
return
|
|
4056
|
+
return path10.join(os.homedir(), trimmed.slice(2));
|
|
4419
4057
|
}
|
|
4420
|
-
return
|
|
4058
|
+
return path10.resolve(trimmed);
|
|
4421
4059
|
}
|
|
4422
4060
|
function formatPathForDisplay(filePath) {
|
|
4423
|
-
const home =
|
|
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
|
|
4089
|
+
return normalizeOptionalString3(value) !== void 0;
|
|
4452
4090
|
}
|
|
4453
4091
|
function formatModelRef(config) {
|
|
4454
|
-
const provider =
|
|
4455
|
-
const model =
|
|
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
|
|
4097
|
+
return normalizeOptionalString3(config?.provider) !== void 0 || normalizeOptionalString3(config?.model) !== void 0;
|
|
4460
4098
|
}
|
|
4461
4099
|
function sameModelRef(left, right) {
|
|
4462
|
-
return
|
|
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
|
|
4105
|
+
return normalizeOptionalString3(config?.credentials?.openaiApiKey);
|
|
4468
4106
|
case "anthropic-api-key":
|
|
4469
|
-
return
|
|
4107
|
+
return normalizeOptionalString3(config?.credentials?.anthropicApiKey);
|
|
4470
4108
|
case "anthropic-token":
|
|
4471
|
-
return
|
|
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
|
|
4116
|
+
return normalizeOptionalString3(config?.credentials?.openaiApiKey);
|
|
4479
4117
|
}
|
|
4480
4118
|
function normalizeProvider(value) {
|
|
4481
|
-
const normalized =
|
|
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
|
|
4488
|
-
const normalized =
|
|
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
|
|
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 ||
|
|
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 =
|
|
4774
|
-
const 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 =
|
|
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
|
|
4470
|
+
return normalizeAuthMethod(config.auth) === "openai-api-key" ? "uses the primary OpenAI key" : "separate OpenAI key configured";
|
|
4833
4471
|
}
|
|
4834
|
-
const 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 =
|
|
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 =
|
|
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,
|
|
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 =
|
|
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 =
|
|
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 =
|
|
4930
|
+
const currentModel = normalizeOptionalString3(options.current?.model) ?? options.defaultModel;
|
|
5293
4931
|
const currentAuth = resolveStageAuthChoice(currentProvider, options.defaultAuth);
|
|
5294
|
-
const hasExplicitOverride =
|
|
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
|
|
5494
|
-
import
|
|
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 =
|
|
5229
|
+
const openclawConfigPath = path11.join(stateDir, "openclaw.json");
|
|
5592
5230
|
let root = {};
|
|
5593
5231
|
try {
|
|
5594
|
-
const raw = await
|
|
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
|
|
5621
|
-
await
|
|
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
|
|
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
|
|
5654
|
-
import
|
|
5655
|
-
import
|
|
5291
|
+
import fs7 from "fs";
|
|
5292
|
+
import os2 from "os";
|
|
5293
|
+
import path12 from "path";
|
|
5656
5294
|
function resolveDefaultOpenClawStateDir() {
|
|
5657
|
-
return
|
|
5295
|
+
return path12.join(os2.homedir(), ".openclaw");
|
|
5658
5296
|
}
|
|
5659
|
-
function detectOpenClawInstallation(env = process.env, existsSyncFn =
|
|
5660
|
-
const envStateDir =
|
|
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 ?
|
|
5300
|
+
const stateDir = envStateDir ? resolveUserPath(envStateDir) : resolveDefaultOpenClawStateDir();
|
|
5663
5301
|
return {
|
|
5664
5302
|
detected: envStateDir !== void 0 || existsSyncFn(stateDir),
|
|
5665
5303
|
stateDir,
|
|
5666
|
-
configPath:
|
|
5667
|
-
sessionsRoot:
|
|
5304
|
+
configPath: path12.join(stateDir, "openclaw.json"),
|
|
5305
|
+
sessionsRoot: path12.join(stateDir, "agents"),
|
|
5668
5306
|
source
|
|
5669
5307
|
};
|
|
5670
5308
|
}
|
|
5671
|
-
function
|
|
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
|
|
5678
|
-
import
|
|
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
|
|
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(
|
|
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
|
|
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
|
|
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 =
|
|
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:
|
|
6149
|
-
until:
|
|
6150
|
-
around:
|
|
5801
|
+
since: normalizeOptionalString2(options.since),
|
|
5802
|
+
until: normalizeOptionalString2(options.until),
|
|
5803
|
+
around: normalizeOptionalString2(options.around),
|
|
6151
5804
|
aroundRadius: options.aroundRadius,
|
|
6152
|
-
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
|
|
6230
|
-
import { getModel
|
|
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
|
-
|
|
5968
|
+
normalizeOptionalString5(run.project),
|
|
6292
5969
|
startedAt,
|
|
6293
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
|
7717
|
-
import
|
|
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:
|
|
7998
|
-
type:
|
|
7999
|
-
claimKeyPrefix:
|
|
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
|
|
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
|
|
10444
|
-
import
|
|
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
|
-
|
|
10653
|
-
|
|
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:
|
|
11227
|
+
type: normalizeOptionalString8(params.type),
|
|
11551
11228
|
importanceMax: params.importance_max,
|
|
11552
11229
|
minAgeDays: params.min_age_days,
|
|
11553
|
-
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
|
|
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 =
|
|
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
|
|
11677
|
-
if (!inner.
|
|
11353
|
+
async expandNeighborhood(request) {
|
|
11354
|
+
if (!inner.expandNeighborhood) {
|
|
11678
11355
|
return [];
|
|
11679
11356
|
}
|
|
11680
|
-
const
|
|
11681
|
-
if (
|
|
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.
|
|
11685
|
-
...
|
|
11686
|
-
|
|
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
|
|
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 =
|
|
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
|
|
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 (
|
|
13203
|
-
return
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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 =
|
|
14540
|
-
const startDirectories = Array.from(/* @__PURE__ */ new Set([
|
|
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 (
|
|
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 =
|
|
14566
|
-
const relative =
|
|
14567
|
-
if (relative.startsWith("..") ||
|
|
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(
|
|
14247
|
+
return relative.split(path16.sep).join("/");
|
|
14571
14248
|
}
|
|
14572
14249
|
function findScenarioRootFrom(startDirectory) {
|
|
14573
|
-
let currentDirectory =
|
|
14250
|
+
let currentDirectory = path16.resolve(startDirectory);
|
|
14574
14251
|
while (true) {
|
|
14575
|
-
const candidate =
|
|
14252
|
+
const candidate = path16.join(currentDirectory, ...SCENARIO_ROOT_SEGMENTS);
|
|
14576
14253
|
if (existsSync(candidate)) {
|
|
14577
14254
|
return candidate;
|
|
14578
14255
|
}
|
|
14579
|
-
const parentDirectory =
|
|
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(
|
|
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(
|
|
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
|
|
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 =
|
|
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(
|
|
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
|
|
15002
|
+
import path19 from "path";
|
|
15326
15003
|
var SANDBOX_DB_FILENAME = "knowledge.db";
|
|
15327
15004
|
async function createClaimKeyScenarioSandbox(root) {
|
|
15328
|
-
const resolvedRoot =
|
|
15329
|
-
const dbPath =
|
|
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 =
|
|
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:
|
|
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 ?
|
|
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:
|
|
15396
|
-
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:
|
|
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:
|
|
15488
|
-
claim_support_locator:
|
|
15489
|
-
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
|
|
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 =
|
|
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 =
|
|
15573
|
-
const sandboxRoot =
|
|
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(
|
|
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
|
-
|
|
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:
|
|
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(
|
|
15832
|
-
await writeJson(
|
|
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(
|
|
15513
|
+
await writeJson(path20.join(scenarioArtifactRoot, "warnings.json"), actual.warnings);
|
|
15837
15514
|
if (actual.storeResult) {
|
|
15838
|
-
await writeJson(
|
|
15515
|
+
await writeJson(path20.join(scenarioArtifactRoot, "store-result.json"), actual.storeResult);
|
|
15839
15516
|
}
|
|
15840
15517
|
if (actual.surgeonSummary) {
|
|
15841
|
-
await writeJson(
|
|
15518
|
+
await writeJson(path20.join(scenarioArtifactRoot, "surgeon-summary.json"), actual.surgeonSummary);
|
|
15842
15519
|
}
|
|
15843
15520
|
if (actual.proposals.length > 0) {
|
|
15844
|
-
await writeJson(
|
|
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
|
|
15653
|
+
import path21 from "path";
|
|
15977
15654
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
15978
|
-
import { getModel as
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
16177
|
-
const configPathOverride =
|
|
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:
|
|
16191
|
-
modelId:
|
|
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(
|
|
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
|
|
15916
|
+
return path21.resolve(value);
|
|
16240
15917
|
}
|
|
16241
15918
|
try {
|
|
16242
15919
|
return fileURLToPath3(value);
|
|
16243
15920
|
} catch {
|
|
16244
|
-
return
|
|
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
|
|
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:
|
|
16010
|
+
issueKind: normalizeOptionalString2(options.issueKind),
|
|
16334
16011
|
eligibleOnly: options.eligibleOnly === true,
|
|
16335
|
-
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:
|
|
16345
|
-
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 =
|
|
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:
|
|
16420
|
-
provider:
|
|
16096
|
+
model: normalizeOptionalString2(options.model),
|
|
16097
|
+
provider: normalizeOptionalString2(options.provider),
|
|
16421
16098
|
verbose: options.verbose === true,
|
|
16422
|
-
tracePath:
|
|
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 =
|
|
16820
|
+
const configPathOverride = normalizeOptionalString13(input.env?.AGENR_CONFIG_PATH);
|
|
17144
16821
|
const config = readConfig({
|
|
17145
16822
|
configPath: configPathOverride,
|
|
17146
|
-
dbPath:
|
|
16823
|
+
dbPath: normalizeOptionalString13(input.dbPath) ?? normalizeOptionalString13(input.env?.AGENR_DB_PATH)
|
|
17147
16824
|
});
|
|
17148
|
-
const dbPath =
|
|
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 =
|
|
17181
|
-
const 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
|
|
16870
|
+
function normalizeOptionalString13(value) {
|
|
17194
16871
|
const normalized = value?.trim();
|
|
17195
16872
|
return normalized && normalized.length > 0 ? normalized : void 0;
|
|
17196
16873
|
}
|