agenr 2.0.1 → 3.0.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 +64 -0
- package/dist/adapters/openclaw/index.d.ts +1 -1
- package/dist/adapters/openclaw/index.js +994 -1420
- package/dist/adapters/skeln/index.d.ts +1951 -0
- package/dist/adapters/skeln/index.js +3899 -0
- package/dist/chunk-575MUIW5.js +1039 -0
- package/dist/{chunk-MEHOGUZE.js → chunk-5LADPJ4C.js} +989 -70
- package/dist/{chunk-Y2BC7RCE.js → chunk-ELR2HSVC.js} +6008 -4618
- package/dist/chunk-GELCEVFA.js +14 -0
- package/dist/{chunk-XD3446YW.js → chunk-LAXNNWHM.js} +3397 -4527
- package/dist/chunk-MYZ2CWY6.js +2738 -0
- package/dist/chunk-P5SB75FK.js +3061 -0
- package/dist/chunk-TBFAARM5.js +1196 -0
- package/dist/claim-slot-policy-CdrW_1l4.d.ts +13 -0
- package/dist/cli.js +292 -613
- package/dist/core/recall/index.d.ts +538 -119
- package/dist/core/recall/index.js +37 -3
- package/dist/internal-eval-server.d.ts +1 -0
- package/dist/internal-eval-server.js +7 -0
- package/dist/internal-recall-eval-server.js +6 -1816
- package/dist/ports-CpzWESmZ.d.ts +925 -0
- package/package.json +9 -6
- package/dist/ports-D2NOK2gR.d.ts +0 -256
package/dist/cli.js
CHANGED
|
@@ -4,6 +4,12 @@ import {
|
|
|
4
4
|
computeProcedureRevisionHash,
|
|
5
5
|
computeProcedureSourceHash
|
|
6
6
|
} from "./chunk-ZYADFKX3.js";
|
|
7
|
+
import {
|
|
8
|
+
deriveOpenClawSessionIdFromFilePath,
|
|
9
|
+
openClawTranscriptParser,
|
|
10
|
+
parseTuiSessionKey,
|
|
11
|
+
readOpenClawSessionsStore
|
|
12
|
+
} from "./chunk-TBFAARM5.js";
|
|
7
13
|
import {
|
|
8
14
|
applyClaimExtractionResultToEntry,
|
|
9
15
|
backfillEpisodeEmbeddings,
|
|
@@ -12,8 +18,7 @@ import {
|
|
|
12
18
|
computeContentHash,
|
|
13
19
|
computeNormContentHash,
|
|
14
20
|
createEpisodeIngestPlan,
|
|
15
|
-
|
|
16
|
-
deriveOpenClawSessionIdFromFilePath,
|
|
21
|
+
createMemoryRepository,
|
|
17
22
|
describeSupersessionRuleFailure,
|
|
18
23
|
detectClaimKeyEntityFamilyCandidates,
|
|
19
24
|
detectClaimKeySingletonAliasCandidates,
|
|
@@ -21,17 +26,14 @@ import {
|
|
|
21
26
|
evaluateClaimKeySupport,
|
|
22
27
|
executeEpisodeIngestPlan,
|
|
23
28
|
normalizeGroundingTags,
|
|
24
|
-
openClawTranscriptParser,
|
|
25
|
-
parseTuiSessionKey,
|
|
26
29
|
prepareEpisodeIngest,
|
|
27
30
|
previewClaimKeyExtraction,
|
|
28
|
-
readOpenClawSessionsStore,
|
|
29
31
|
runBatchClaimExtraction,
|
|
30
32
|
storeEntriesDetailed,
|
|
31
33
|
tokenizeGroundingText,
|
|
32
34
|
validateEntriesWithIndexes,
|
|
33
35
|
validateSupersessionRules
|
|
34
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-LAXNNWHM.js";
|
|
35
37
|
import {
|
|
36
38
|
DEFAULT_CLAIM_EXTRACTION_CONCURRENCY,
|
|
37
39
|
DEFAULT_SURGEON_CONTEXT_LIMIT,
|
|
@@ -45,6 +47,7 @@ import {
|
|
|
45
47
|
ENTRY_TYPES,
|
|
46
48
|
EXPIRY_LEVELS,
|
|
47
49
|
applyClaimKeyLifecycle,
|
|
50
|
+
attachCrossEncoderPort,
|
|
48
51
|
authMethodToProvider,
|
|
49
52
|
buildActiveEntryClause,
|
|
50
53
|
buildClaimKeyLifecycleAuditDetails,
|
|
@@ -60,17 +63,19 @@ import {
|
|
|
60
63
|
configFileExists,
|
|
61
64
|
createDatabase,
|
|
62
65
|
createEmbeddingClient,
|
|
66
|
+
createLlmClient,
|
|
67
|
+
createOpenAICrossEncoder,
|
|
63
68
|
createRecallAdapter,
|
|
64
69
|
deserializeTags,
|
|
65
70
|
getAuthMethodDefinition,
|
|
66
71
|
getEntry,
|
|
67
72
|
getLastBulkIngestAt,
|
|
68
73
|
insertEntry,
|
|
69
|
-
isAgenrAuthMethod,
|
|
70
74
|
mapEntryRow,
|
|
71
75
|
mergeExplicitClaimKeyMetadata,
|
|
72
76
|
normalizeManualClaimKeyUpdate,
|
|
73
77
|
parseAndNormalizeProcedureYaml,
|
|
78
|
+
probeLlmCredentials,
|
|
74
79
|
projectClaimCentricRecallEntry,
|
|
75
80
|
readBoolean,
|
|
76
81
|
readConfig,
|
|
@@ -82,16 +87,20 @@ import {
|
|
|
82
87
|
requireClaimSupportMode,
|
|
83
88
|
resolveClaimExtractionConfig,
|
|
84
89
|
resolveConfigPath,
|
|
90
|
+
resolveCrossEncoderApiKey,
|
|
85
91
|
resolveDbPath,
|
|
86
92
|
resolveEmbeddingApiKey,
|
|
87
93
|
resolveEmbeddingModel,
|
|
94
|
+
resolveLlmApiKey,
|
|
95
|
+
resolveLlmCredentials,
|
|
96
|
+
resolveModel,
|
|
88
97
|
retireEntry,
|
|
89
98
|
supersedeEntry,
|
|
90
99
|
toAgenrConfigInput,
|
|
91
100
|
updateEntry,
|
|
92
101
|
validateTemporalValidityRange,
|
|
93
102
|
writeConfig
|
|
94
|
-
} from "./chunk-
|
|
103
|
+
} from "./chunk-ELR2HSVC.js";
|
|
95
104
|
import {
|
|
96
105
|
compactClaimKey,
|
|
97
106
|
describeClaimKeyNormalizationFailure,
|
|
@@ -102,7 +111,7 @@ import {
|
|
|
102
111
|
normalizeClaimKeySegment,
|
|
103
112
|
recall,
|
|
104
113
|
resolveClaimSlotPolicy
|
|
105
|
-
} from "./chunk-
|
|
114
|
+
} from "./chunk-5LADPJ4C.js";
|
|
106
115
|
|
|
107
116
|
// src/cli/main.ts
|
|
108
117
|
import { Command } from "commander";
|
|
@@ -235,7 +244,7 @@ function formatUnknownError(error) {
|
|
|
235
244
|
}
|
|
236
245
|
|
|
237
246
|
// src/cli/commands/ingest.ts
|
|
238
|
-
import
|
|
247
|
+
import path9 from "path";
|
|
239
248
|
import * as clack4 from "@clack/prompts";
|
|
240
249
|
|
|
241
250
|
// src/core/ingestion/parser.ts
|
|
@@ -2236,378 +2245,9 @@ function matchesTranscriptFileName(fileName) {
|
|
|
2236
2245
|
return GENERIC_TRANSCRIPT_FILE_PATTERN.test(fileName.trim());
|
|
2237
2246
|
}
|
|
2238
2247
|
|
|
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
2248
|
// src/cli/shared/parse.ts
|
|
2609
2249
|
import { InvalidArgumentError } from "commander";
|
|
2610
|
-
function
|
|
2250
|
+
function normalizeOptionalString2(value) {
|
|
2611
2251
|
const trimmed = value?.trim();
|
|
2612
2252
|
return trimmed && trimmed.length > 0 ? trimmed : void 0;
|
|
2613
2253
|
}
|
|
@@ -2615,7 +2255,7 @@ function normalizeStringList(values) {
|
|
|
2615
2255
|
const normalizedValues = [];
|
|
2616
2256
|
const seen = /* @__PURE__ */ new Set();
|
|
2617
2257
|
for (const value of values ?? []) {
|
|
2618
|
-
const normalized =
|
|
2258
|
+
const normalized = normalizeOptionalString2(value);
|
|
2619
2259
|
if (!normalized || seen.has(normalized)) {
|
|
2620
2260
|
continue;
|
|
2621
2261
|
}
|
|
@@ -2625,7 +2265,7 @@ function normalizeStringList(values) {
|
|
|
2625
2265
|
return normalizedValues.length > 0 ? normalizedValues : void 0;
|
|
2626
2266
|
}
|
|
2627
2267
|
function collectStringValue(value, previous) {
|
|
2628
|
-
const normalized =
|
|
2268
|
+
const normalized = normalizeOptionalString2(value);
|
|
2629
2269
|
if (!normalized) {
|
|
2630
2270
|
throw new InvalidArgumentError("Value cannot be empty.");
|
|
2631
2271
|
}
|
|
@@ -2677,7 +2317,7 @@ function parseUnitInterval(value) {
|
|
|
2677
2317
|
return parsed;
|
|
2678
2318
|
}
|
|
2679
2319
|
function parseModelRef(value) {
|
|
2680
|
-
const normalized =
|
|
2320
|
+
const normalized = normalizeOptionalString2(value);
|
|
2681
2321
|
if (!normalized) {
|
|
2682
2322
|
throw new InvalidArgumentError("Model reference cannot be empty.");
|
|
2683
2323
|
}
|
|
@@ -2687,8 +2327,8 @@ function parseModelRef(value) {
|
|
|
2687
2327
|
modelId: normalized
|
|
2688
2328
|
};
|
|
2689
2329
|
}
|
|
2690
|
-
const provider =
|
|
2691
|
-
const modelId =
|
|
2330
|
+
const provider = normalizeOptionalString2(normalized.slice(0, separatorIndex));
|
|
2331
|
+
const modelId = normalizeOptionalString2(normalized.slice(separatorIndex + 1));
|
|
2692
2332
|
if (!provider || !modelId) {
|
|
2693
2333
|
throw new InvalidArgumentError(`Model reference must look like "provider/model" or "model". Received: ${value}.`);
|
|
2694
2334
|
}
|
|
@@ -2739,13 +2379,13 @@ function timestamp() {
|
|
|
2739
2379
|
import { InvalidArgumentError as InvalidArgumentError3, Option as Option2 } from "commander";
|
|
2740
2380
|
|
|
2741
2381
|
// src/cli/commands/ingest-episodes.ts
|
|
2742
|
-
import
|
|
2743
|
-
import
|
|
2382
|
+
import fs4 from "fs/promises";
|
|
2383
|
+
import path6 from "path";
|
|
2744
2384
|
import * as clack2 from "@clack/prompts";
|
|
2745
2385
|
import { InvalidArgumentError as InvalidArgumentError2, Option } from "commander";
|
|
2746
2386
|
|
|
2747
2387
|
// src/adapters/db/episode-ingest-support.ts
|
|
2748
|
-
import
|
|
2388
|
+
import path4 from "path";
|
|
2749
2389
|
function createEpisodeIngestSupportPort(executor) {
|
|
2750
2390
|
return {
|
|
2751
2391
|
countEntries: async () => countRows(executor, "SELECT COUNT(*) AS count FROM entries"),
|
|
@@ -2761,7 +2401,7 @@ async function hasRelevantProvenanceMatch(executor, sampleFiles) {
|
|
|
2761
2401
|
if (ingestLogMatches > 0) {
|
|
2762
2402
|
return true;
|
|
2763
2403
|
}
|
|
2764
|
-
const basenames = Array.from(new Set(sampleFiles.map((filePath) =>
|
|
2404
|
+
const basenames = Array.from(new Set(sampleFiles.map((filePath) => path4.basename(filePath))));
|
|
2765
2405
|
const basenameClauses = basenames.map(() => "(source_file = ? OR source_file LIKE ?)").join(" OR ");
|
|
2766
2406
|
const basenameArgs = basenames.flatMap((basename) => [basename, `%/${basename}`]);
|
|
2767
2407
|
const entryMatches = await countRows(executor, `SELECT COUNT(*) AS count FROM entries WHERE source_file IS NOT NULL AND (${basenameClauses})`, basenameArgs);
|
|
@@ -2850,17 +2490,17 @@ function normalizeNullableString(value) {
|
|
|
2850
2490
|
}
|
|
2851
2491
|
|
|
2852
2492
|
// src/adapters/openclaw/session/transcript-files.ts
|
|
2853
|
-
import
|
|
2854
|
-
import
|
|
2493
|
+
import fs3 from "fs/promises";
|
|
2494
|
+
import path5 from "path";
|
|
2855
2495
|
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
2496
|
async function discoverOpenClawTranscriptFiles(targetPath) {
|
|
2857
|
-
const resolvedTargetPath =
|
|
2858
|
-
const stat = await
|
|
2497
|
+
const resolvedTargetPath = path5.resolve(targetPath);
|
|
2498
|
+
const stat = await fs3.stat(resolvedTargetPath);
|
|
2859
2499
|
if (stat.isFile()) {
|
|
2860
|
-
return matchesOpenClawTranscriptFile(
|
|
2500
|
+
return matchesOpenClawTranscriptFile(path5.basename(resolvedTargetPath)) ? [resolvedTargetPath] : [];
|
|
2861
2501
|
}
|
|
2862
|
-
const entries = await
|
|
2863
|
-
return entries.filter((entry) => entry.isFile() && matchesOpenClawTranscriptFile(entry.name)).map((entry) =>
|
|
2502
|
+
const entries = await fs3.readdir(resolvedTargetPath, { recursive: true, withFileTypes: true });
|
|
2503
|
+
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
2504
|
}
|
|
2865
2505
|
var openClawTranscriptFiles = {
|
|
2866
2506
|
discoverFiles: discoverOpenClawTranscriptFiles
|
|
@@ -2907,7 +2547,7 @@ function registerIngestEpisodesCommand(parent) {
|
|
|
2907
2547
|
}
|
|
2908
2548
|
const { provider, modelId } = resolveEpisodeModel(config, commandInput.modelOverride);
|
|
2909
2549
|
const modelInfo = createEpisodeIngestSummaryModelInfo(provider, modelId);
|
|
2910
|
-
const resolvedTargetPath =
|
|
2550
|
+
const resolvedTargetPath = path6.resolve(normalizedTargetPath);
|
|
2911
2551
|
const sessionsDir = await resolveSessionsDirectory(resolvedTargetPath);
|
|
2912
2552
|
const ports = await createEpisodeIngestPorts(database, sessionsDir);
|
|
2913
2553
|
const embeddingSetup = resolveEpisodeEmbeddingSetup(config, commandInput);
|
|
@@ -3122,18 +2762,18 @@ function createEpisodeIngestSummaryLlm(provider, modelId, apiKey) {
|
|
|
3122
2762
|
};
|
|
3123
2763
|
}
|
|
3124
2764
|
async function resolveSessionsDirectory(targetPath) {
|
|
3125
|
-
const stat = await
|
|
3126
|
-
return stat.isFile() ?
|
|
2765
|
+
const stat = await fs4.stat(targetPath);
|
|
2766
|
+
return stat.isFile() ? path6.dirname(targetPath) : targetPath;
|
|
3127
2767
|
}
|
|
3128
2768
|
function resolveEpisodeDbPath(config, overridePath) {
|
|
3129
|
-
const normalizedOverride =
|
|
2769
|
+
const normalizedOverride = normalizeOptionalString2(overridePath);
|
|
3130
2770
|
if (!normalizedOverride) {
|
|
3131
2771
|
return config?.dbPath ?? resolveDbPath(config);
|
|
3132
2772
|
}
|
|
3133
2773
|
if (normalizedOverride === ":memory:" || normalizedOverride.startsWith("file:")) {
|
|
3134
2774
|
return normalizedOverride;
|
|
3135
2775
|
}
|
|
3136
|
-
return
|
|
2776
|
+
return path6.resolve(normalizedOverride);
|
|
3137
2777
|
}
|
|
3138
2778
|
function resolveEpisodeModel(config, overrideRef) {
|
|
3139
2779
|
const resolved = resolveModel(config, "episode");
|
|
@@ -3247,7 +2887,7 @@ function reportEpisodeProgress(completed, total, session) {
|
|
|
3247
2887
|
}
|
|
3248
2888
|
function formatEpisodeProgressLine(completed, total, session) {
|
|
3249
2889
|
const prefix = completed !== void 0 && total !== void 0 ? `${completed}/${total} ` : "";
|
|
3250
|
-
const fileLabel =
|
|
2890
|
+
const fileLabel = path6.basename(session.filePath);
|
|
3251
2891
|
const details = session.action === "failed" ? `failed (${session.error ?? "unknown error"})` : session.action;
|
|
3252
2892
|
const usage = session.usage.totalCost > 0 ? ` ${formatCost(session.usage.totalCost)}` : "";
|
|
3253
2893
|
return `${prefix}${fileLabel}: ${details}${usage}`;
|
|
@@ -3272,15 +2912,15 @@ function formatUnknownError2(error) {
|
|
|
3272
2912
|
}
|
|
3273
2913
|
function normalizeEpisodeIngestCommand(targetPath, options) {
|
|
3274
2914
|
const commandInput = {
|
|
3275
|
-
targetPath:
|
|
2915
|
+
targetPath: normalizeOptionalString2(targetPath),
|
|
3276
2916
|
verbose: options.verbose === true,
|
|
3277
2917
|
dryRun: options.dryRun === true,
|
|
3278
2918
|
regenerate: options.regenerate === true,
|
|
3279
2919
|
embedOnly: options.embedOnly === true,
|
|
3280
2920
|
noEmbed: options.noEmbed === true,
|
|
3281
|
-
recent:
|
|
2921
|
+
recent: normalizeOptionalString2(options.recent),
|
|
3282
2922
|
concurrency: options.concurrency ?? DEFAULT_EPISODE_INGEST_CONCURRENCY,
|
|
3283
|
-
dbOverride:
|
|
2923
|
+
dbOverride: normalizeOptionalString2(options.db),
|
|
3284
2924
|
modelOverride: options.model ? parseModelRef(options.model) : void 0
|
|
3285
2925
|
};
|
|
3286
2926
|
validateEpisodeIngestOptions(commandInput);
|
|
@@ -3291,26 +2931,26 @@ function parseEpisodeIngestConcurrency(value) {
|
|
|
3291
2931
|
}
|
|
3292
2932
|
|
|
3293
2933
|
// src/cli/commands/ingest-procedures.ts
|
|
3294
|
-
import
|
|
2934
|
+
import path8 from "path";
|
|
3295
2935
|
import * as clack3 from "@clack/prompts";
|
|
3296
2936
|
import "commander";
|
|
3297
2937
|
|
|
3298
2938
|
// src/adapters/files/procedure-files.ts
|
|
3299
|
-
import
|
|
3300
|
-
import
|
|
2939
|
+
import fs5 from "fs/promises";
|
|
2940
|
+
import path7 from "path";
|
|
3301
2941
|
var PROCEDURE_FILE_PATTERN = /^.+\.ya?ml$/iu;
|
|
3302
2942
|
async function discoverProcedureFiles(targetPath, options = {}) {
|
|
3303
|
-
const resolvedTargetPath =
|
|
3304
|
-
const stat = await
|
|
2943
|
+
const resolvedTargetPath = path7.resolve(targetPath);
|
|
2944
|
+
const stat = await fs5.stat(resolvedTargetPath);
|
|
3305
2945
|
if (stat.isFile()) {
|
|
3306
|
-
return matchesProcedureFileName(
|
|
2946
|
+
return matchesProcedureFileName(path7.basename(resolvedTargetPath)) ? [resolvedTargetPath] : [];
|
|
3307
2947
|
}
|
|
3308
2948
|
const recursive = options.recursive ?? true;
|
|
3309
|
-
const entries = recursive ? await
|
|
3310
|
-
return entries.filter((entry) => entry.isFile() && matchesProcedureFileName(entry.name)).map((entry) =>
|
|
2949
|
+
const entries = recursive ? await fs5.readdir(resolvedTargetPath, { recursive: true, withFileTypes: true }) : await fs5.readdir(resolvedTargetPath, { withFileTypes: true });
|
|
2950
|
+
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
2951
|
}
|
|
3312
2952
|
async function readProcedureFile(filePath) {
|
|
3313
|
-
return
|
|
2953
|
+
return fs5.readFile(filePath, "utf-8");
|
|
3314
2954
|
}
|
|
3315
2955
|
var LocalProcedureFiles = class {
|
|
3316
2956
|
/**
|
|
@@ -3645,7 +3285,7 @@ function registerIngestProceduresCommand(parent) {
|
|
|
3645
3285
|
try {
|
|
3646
3286
|
const config = readConfig();
|
|
3647
3287
|
const dbPath = config.dbPath;
|
|
3648
|
-
const resolvedTargetPath =
|
|
3288
|
+
const resolvedTargetPath = path8.resolve(commandInput.targetPath);
|
|
3649
3289
|
database = await createDatabase(dbPath);
|
|
3650
3290
|
if (commandInput.verbose) {
|
|
3651
3291
|
clack3.log.step(`Preparing procedure sync for ${resolvedTargetPath}...`);
|
|
@@ -3701,7 +3341,7 @@ function registerIngestProceduresCommand(parent) {
|
|
|
3701
3341
|
}
|
|
3702
3342
|
function normalizeIngestProceduresCommand(targetPath, options) {
|
|
3703
3343
|
return {
|
|
3704
|
-
targetPath:
|
|
3344
|
+
targetPath: normalizeOptionalString2(targetPath) ?? DEFAULT_PROCEDURE_SYNC_PATH,
|
|
3705
3345
|
verbose: options.verbose === true,
|
|
3706
3346
|
dryRun: options.dryRun === true
|
|
3707
3347
|
};
|
|
@@ -3822,11 +3462,11 @@ function registerIngestEntriesCommand(parent) {
|
|
|
3822
3462
|
const claimApiKey = claimModel ? resolveLlmApiKey(config, claimModel.provider) : void 0;
|
|
3823
3463
|
const sharedEmbedding = createEmbeddingClient(resolveEmbeddingApiKey(config), resolveEmbeddingModel(config));
|
|
3824
3464
|
if (commandInput.verbose) {
|
|
3825
|
-
clack4.log.step(`Discovering transcript files in ${
|
|
3465
|
+
clack4.log.step(`Discovering transcript files in ${path9.resolve(commandInput.targetPath)}...`);
|
|
3826
3466
|
}
|
|
3827
3467
|
const files = await localTranscriptFiles.discoverFiles(commandInput.targetPath);
|
|
3828
3468
|
if (files.length === 0) {
|
|
3829
|
-
clack4.log.warn(`No transcript files found at ${
|
|
3469
|
+
clack4.log.warn(`No transcript files found at ${path9.resolve(commandInput.targetPath)}.`);
|
|
3830
3470
|
clack4.outro("Nothing to ingest.");
|
|
3831
3471
|
return;
|
|
3832
3472
|
}
|
|
@@ -3909,7 +3549,7 @@ function registerIngestEntriesCommand(parent) {
|
|
|
3909
3549
|
failedFiles: 0,
|
|
3910
3550
|
warnings: 0
|
|
3911
3551
|
};
|
|
3912
|
-
const usageTotals = extractionRuns.reduce((total, run) => addUsageStats(total, run.usage),
|
|
3552
|
+
const usageTotals = extractionRuns.reduce((total, run) => addUsageStats(total, run.usage), createEmptyUsageStats2());
|
|
3913
3553
|
addUsageStats(usageTotals, dedupUsage);
|
|
3914
3554
|
let runningCost = 0;
|
|
3915
3555
|
for (const [index, extractionRun] of extractionRuns.entries()) {
|
|
@@ -3922,9 +3562,9 @@ function registerIngestEntriesCommand(parent) {
|
|
|
3922
3562
|
totals.skippedFiles += 1;
|
|
3923
3563
|
if (commandInput.verbose) {
|
|
3924
3564
|
printVerboseFileDetails(result, commandInput, usage);
|
|
3925
|
-
clack4.log.step(buildSkippedMessage(
|
|
3565
|
+
clack4.log.step(buildSkippedMessage(path9.basename(result.file)));
|
|
3926
3566
|
} else {
|
|
3927
|
-
clack4.log.step(buildSkippedMessage(
|
|
3567
|
+
clack4.log.step(buildSkippedMessage(path9.basename(result.file)));
|
|
3928
3568
|
}
|
|
3929
3569
|
continue;
|
|
3930
3570
|
}
|
|
@@ -3933,7 +3573,7 @@ function registerIngestEntriesCommand(parent) {
|
|
|
3933
3573
|
if (commandInput.verbose) {
|
|
3934
3574
|
printVerboseFileDetails(result, commandInput, usage);
|
|
3935
3575
|
}
|
|
3936
|
-
clack4.log.error(buildFailureMessage(
|
|
3576
|
+
clack4.log.error(buildFailureMessage(path9.basename(result.file), result, commandInput, usage, index === 0));
|
|
3937
3577
|
continue;
|
|
3938
3578
|
}
|
|
3939
3579
|
const storeResult = result.storeResult ?? emptyStoreResult2();
|
|
@@ -3943,7 +3583,7 @@ function registerIngestEntriesCommand(parent) {
|
|
|
3943
3583
|
if (commandInput.verbose) {
|
|
3944
3584
|
printVerboseFileDetails(result, commandInput, usage);
|
|
3945
3585
|
}
|
|
3946
|
-
clack4.log.step(buildSuccessMessage(
|
|
3586
|
+
clack4.log.step(buildSuccessMessage(path9.basename(result.file), result, commandInput, usage, index === 0));
|
|
3947
3587
|
}
|
|
3948
3588
|
const summaryParts = [`${totals.stored} ${pluralize3(totals.stored, "entry", "entries")} stored`, `${totals.deduped} deduped`];
|
|
3949
3589
|
if (totals.rejected > 0) {
|
|
@@ -3982,7 +3622,7 @@ function registerIngestEntriesCommand(parent) {
|
|
|
3982
3622
|
});
|
|
3983
3623
|
}
|
|
3984
3624
|
function normalizeIngestEntriesCommand(targetPath, options) {
|
|
3985
|
-
const normalizedTargetPath =
|
|
3625
|
+
const normalizedTargetPath = normalizeOptionalString2(targetPath);
|
|
3986
3626
|
if (!normalizedTargetPath) {
|
|
3987
3627
|
throw new InvalidArgumentError3("Path cannot be empty.");
|
|
3988
3628
|
}
|
|
@@ -4336,7 +3976,7 @@ function truncateText(text2, maxLength) {
|
|
|
4336
3976
|
function isDefined3(value) {
|
|
4337
3977
|
return value !== void 0;
|
|
4338
3978
|
}
|
|
4339
|
-
function
|
|
3979
|
+
function createEmptyUsageStats2() {
|
|
4340
3980
|
return {
|
|
4341
3981
|
calls: 0,
|
|
4342
3982
|
inputTokens: 0,
|
|
@@ -4369,11 +4009,11 @@ function parseConcurrency(value) {
|
|
|
4369
4009
|
}
|
|
4370
4010
|
|
|
4371
4011
|
// src/cli/commands/setup.ts
|
|
4372
|
-
import { getModels } from "@
|
|
4012
|
+
import { getModels } from "@earendil-works/pi-ai";
|
|
4373
4013
|
|
|
4374
4014
|
// src/cli/ui.ts
|
|
4375
|
-
import
|
|
4376
|
-
import
|
|
4015
|
+
import os from "os";
|
|
4016
|
+
import path10 from "path";
|
|
4377
4017
|
import * as clack5 from "@clack/prompts";
|
|
4378
4018
|
function createCliPrompts() {
|
|
4379
4019
|
return {
|
|
@@ -4403,24 +4043,24 @@ function createCliPrompts() {
|
|
|
4403
4043
|
};
|
|
4404
4044
|
}
|
|
4405
4045
|
var cliPrompts = createCliPrompts();
|
|
4406
|
-
function
|
|
4046
|
+
function resolveUserPath(value) {
|
|
4407
4047
|
const trimmed = value.trim();
|
|
4408
4048
|
if (trimmed === ":memory:" || trimmed.startsWith("file:")) {
|
|
4409
4049
|
return trimmed;
|
|
4410
4050
|
}
|
|
4411
4051
|
if (trimmed === "~") {
|
|
4412
|
-
return
|
|
4052
|
+
return os.homedir();
|
|
4413
4053
|
}
|
|
4414
4054
|
if (trimmed.startsWith("~/")) {
|
|
4415
|
-
return
|
|
4055
|
+
return path10.join(os.homedir(), trimmed.slice(2));
|
|
4416
4056
|
}
|
|
4417
4057
|
if (trimmed.startsWith("~\\")) {
|
|
4418
|
-
return
|
|
4058
|
+
return path10.join(os.homedir(), trimmed.slice(2));
|
|
4419
4059
|
}
|
|
4420
|
-
return
|
|
4060
|
+
return path10.resolve(trimmed);
|
|
4421
4061
|
}
|
|
4422
4062
|
function formatPathForDisplay(filePath) {
|
|
4423
|
-
const home =
|
|
4063
|
+
const home = os.homedir();
|
|
4424
4064
|
const resolvedPath = filePath.trim();
|
|
4425
4065
|
return resolvedPath.startsWith(home) ? `~${resolvedPath.slice(home.length)}` : resolvedPath;
|
|
4426
4066
|
}
|
|
@@ -4448,50 +4088,50 @@ function validateSecret(value) {
|
|
|
4448
4088
|
return value?.trim().length ? void 0 : "Value cannot be empty.";
|
|
4449
4089
|
}
|
|
4450
4090
|
function hasSecret(value) {
|
|
4451
|
-
return
|
|
4091
|
+
return normalizeOptionalString3(value) !== void 0;
|
|
4452
4092
|
}
|
|
4453
4093
|
function formatModelRef(config) {
|
|
4454
|
-
const provider =
|
|
4455
|
-
const model =
|
|
4094
|
+
const provider = normalizeOptionalString3(config?.provider) ?? "(provider not set)";
|
|
4095
|
+
const model = normalizeOptionalString3(config?.model) ?? "(model not set)";
|
|
4456
4096
|
return `${provider}/${model}`;
|
|
4457
4097
|
}
|
|
4458
4098
|
function hasModelOverride(config) {
|
|
4459
|
-
return
|
|
4099
|
+
return normalizeOptionalString3(config?.provider) !== void 0 || normalizeOptionalString3(config?.model) !== void 0;
|
|
4460
4100
|
}
|
|
4461
4101
|
function sameModelRef(left, right) {
|
|
4462
|
-
return
|
|
4102
|
+
return normalizeOptionalString3(left?.provider) === normalizeOptionalString3(right?.provider) && normalizeOptionalString3(left?.model) === normalizeOptionalString3(right?.model);
|
|
4463
4103
|
}
|
|
4464
4104
|
function resolveStoredCredentialForAuth(config, auth) {
|
|
4465
4105
|
switch (auth) {
|
|
4466
4106
|
case "openai-api-key":
|
|
4467
|
-
return
|
|
4107
|
+
return normalizeOptionalString3(config?.credentials?.openaiApiKey);
|
|
4468
4108
|
case "anthropic-api-key":
|
|
4469
|
-
return
|
|
4109
|
+
return normalizeOptionalString3(config?.credentials?.anthropicApiKey);
|
|
4470
4110
|
case "anthropic-token":
|
|
4471
|
-
return
|
|
4111
|
+
return normalizeOptionalString3(config?.credentials?.anthropicOauthToken);
|
|
4472
4112
|
case "anthropic-oauth":
|
|
4473
4113
|
case "openai-subscription":
|
|
4474
4114
|
return void 0;
|
|
4475
4115
|
}
|
|
4476
4116
|
}
|
|
4477
4117
|
function resolveStoredEmbeddingCredential(config) {
|
|
4478
|
-
return
|
|
4118
|
+
return normalizeOptionalString3(config?.credentials?.openaiApiKey);
|
|
4479
4119
|
}
|
|
4480
4120
|
function normalizeProvider(value) {
|
|
4481
|
-
const normalized =
|
|
4121
|
+
const normalized = normalizeOptionalString3(value);
|
|
4482
4122
|
if (normalized === "openai" || normalized === "openai-codex" || normalized === "anthropic") {
|
|
4483
4123
|
return normalized;
|
|
4484
4124
|
}
|
|
4485
4125
|
return void 0;
|
|
4486
4126
|
}
|
|
4487
|
-
function
|
|
4488
|
-
const normalized =
|
|
4127
|
+
function normalizeAuthMethod(value) {
|
|
4128
|
+
const normalized = normalizeOptionalString3(value);
|
|
4489
4129
|
if (normalized === "openai-api-key" || normalized === "openai-subscription" || normalized === "anthropic-api-key" || normalized === "anthropic-oauth" || normalized === "anthropic-token") {
|
|
4490
4130
|
return normalized;
|
|
4491
4131
|
}
|
|
4492
4132
|
return void 0;
|
|
4493
4133
|
}
|
|
4494
|
-
function
|
|
4134
|
+
function normalizeOptionalString3(value) {
|
|
4495
4135
|
const trimmed = value?.trim();
|
|
4496
4136
|
return trimmed && trimmed.length > 0 ? trimmed : void 0;
|
|
4497
4137
|
}
|
|
@@ -4733,7 +4373,7 @@ function hasPersistedSurgeonConfig(config) {
|
|
|
4733
4373
|
return false;
|
|
4734
4374
|
}
|
|
4735
4375
|
const retirementConfig = config.passes?.retirement;
|
|
4736
|
-
return hasModelOverride(config.model) || config.costCap !== void 0 || config.dailyCostCap !== void 0 || config.contextLimit !== void 0 ||
|
|
4376
|
+
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
4377
|
}
|
|
4738
4378
|
|
|
4739
4379
|
// src/cli/commands/setup/config.ts
|
|
@@ -4770,8 +4410,8 @@ function isSetupConfigured(config, env = process.env) {
|
|
|
4770
4410
|
return getSetupReadiness(config, env).ready;
|
|
4771
4411
|
}
|
|
4772
4412
|
function getSetupReadiness(config, env = process.env) {
|
|
4773
|
-
const provider =
|
|
4774
|
-
const model =
|
|
4413
|
+
const provider = normalizeOptionalString3(config?.provider);
|
|
4414
|
+
const model = normalizeOptionalString3(config?.model);
|
|
4775
4415
|
if (!provider || !model) {
|
|
4776
4416
|
return {
|
|
4777
4417
|
ready: false,
|
|
@@ -4812,7 +4452,7 @@ function formatSavedConfigSummary(config, configPath, dbPath, options) {
|
|
|
4812
4452
|
return lines.join("\n");
|
|
4813
4453
|
}
|
|
4814
4454
|
function describePrimaryCredentialConfig(config) {
|
|
4815
|
-
const auth =
|
|
4455
|
+
const auth = normalizeAuthMethod(config.auth);
|
|
4816
4456
|
if (!auth) {
|
|
4817
4457
|
return "not set";
|
|
4818
4458
|
}
|
|
@@ -4829,9 +4469,9 @@ function describePrimaryCredentialConfig(config) {
|
|
|
4829
4469
|
}
|
|
4830
4470
|
function describeEmbeddingConfig(config) {
|
|
4831
4471
|
if (hasSecret(resolveStoredEmbeddingCredential(config))) {
|
|
4832
|
-
return
|
|
4472
|
+
return normalizeAuthMethod(config.auth) === "openai-api-key" ? "uses the primary OpenAI key" : "separate OpenAI key configured";
|
|
4833
4473
|
}
|
|
4834
|
-
const auth =
|
|
4474
|
+
const auth = normalizeAuthMethod(config.auth);
|
|
4835
4475
|
if (auth && auth !== "openai-api-key") {
|
|
4836
4476
|
return "missing separate OpenAI key";
|
|
4837
4477
|
}
|
|
@@ -4841,7 +4481,7 @@ function mergeStoredCredentials(existingCredentials, values) {
|
|
|
4841
4481
|
const next = {
|
|
4842
4482
|
...existingCredentials ?? {}
|
|
4843
4483
|
};
|
|
4844
|
-
const normalizedPrimaryCredential =
|
|
4484
|
+
const normalizedPrimaryCredential = normalizeOptionalString3(values.primaryCredential);
|
|
4845
4485
|
if (normalizedPrimaryCredential) {
|
|
4846
4486
|
if (values.auth === "openai-api-key") {
|
|
4847
4487
|
next.openaiApiKey = normalizedPrimaryCredential;
|
|
@@ -4851,7 +4491,7 @@ function mergeStoredCredentials(existingCredentials, values) {
|
|
|
4851
4491
|
next.anthropicOauthToken = normalizedPrimaryCredential;
|
|
4852
4492
|
}
|
|
4853
4493
|
}
|
|
4854
|
-
const normalizedEmbeddingApiKey =
|
|
4494
|
+
const normalizedEmbeddingApiKey = normalizeOptionalString3(values.embeddingApiKey);
|
|
4855
4495
|
if (normalizedEmbeddingApiKey) {
|
|
4856
4496
|
next.openaiApiKey = normalizedEmbeddingApiKey;
|
|
4857
4497
|
}
|
|
@@ -4877,7 +4517,7 @@ async function runSetupCore(options = {}) {
|
|
|
4877
4517
|
}
|
|
4878
4518
|
const existingConfig = options.existingConfig;
|
|
4879
4519
|
const configPath = runtime.resolveConfigPath();
|
|
4880
|
-
const auth = await selectAuthMethod(prompts,
|
|
4520
|
+
const auth = await selectAuthMethod(prompts, normalizeAuthMethod(existingConfig?.auth));
|
|
4881
4521
|
if (auth === null) {
|
|
4882
4522
|
return null;
|
|
4883
4523
|
}
|
|
@@ -4922,7 +4562,7 @@ async function runSetupCore(options = {}) {
|
|
|
4922
4562
|
if (stageOverrides === null) {
|
|
4923
4563
|
return null;
|
|
4924
4564
|
}
|
|
4925
|
-
const defaultDbPath =
|
|
4565
|
+
const defaultDbPath = normalizeOptionalString3(existingConfig?.dbPath) ?? runtime.resolveDbPath(existingConfig);
|
|
4926
4566
|
const dbPathInput = await prompts.text({
|
|
4927
4567
|
message: "Database path:",
|
|
4928
4568
|
initialValue: defaultDbPath,
|
|
@@ -4932,7 +4572,7 @@ async function runSetupCore(options = {}) {
|
|
|
4932
4572
|
if (prompts.isCancel(dbPathInput)) {
|
|
4933
4573
|
return null;
|
|
4934
4574
|
}
|
|
4935
|
-
const dbPath =
|
|
4575
|
+
const dbPath = resolveUserPath(dbPathInput);
|
|
4936
4576
|
const nextConfig = buildNextConfig(existingConfig, {
|
|
4937
4577
|
auth,
|
|
4938
4578
|
provider,
|
|
@@ -5289,9 +4929,9 @@ async function promptTaskModelOverrides(prompts, runtime, options) {
|
|
|
5289
4929
|
async function promptStageOverride(prompts, runtime, options) {
|
|
5290
4930
|
const defaultRef = `${describeAuthMethod(options.defaultAuth)} / ${options.defaultModel}`;
|
|
5291
4931
|
const currentProvider = normalizeProvider(options.current?.provider);
|
|
5292
|
-
const currentModel =
|
|
4932
|
+
const currentModel = normalizeOptionalString3(options.current?.model) ?? options.defaultModel;
|
|
5293
4933
|
const currentAuth = resolveStageAuthChoice(currentProvider, options.defaultAuth);
|
|
5294
|
-
const hasExplicitOverride =
|
|
4934
|
+
const hasExplicitOverride = normalizeOptionalString3(options.current?.provider) !== void 0 || normalizeOptionalString3(options.current?.model) !== void 0;
|
|
5295
4935
|
const action = await prompts.select({
|
|
5296
4936
|
message: `${options.stage.label} model override:`,
|
|
5297
4937
|
options: [
|
|
@@ -5450,7 +5090,7 @@ async function runSetupCore2(options = {}) {
|
|
|
5450
5090
|
}
|
|
5451
5091
|
|
|
5452
5092
|
// src/cli/commands/init/cost-estimator.ts
|
|
5453
|
-
import { getModels as getModels2 } from "@
|
|
5093
|
+
import { getModels as getModels2 } from "@earendil-works/pi-ai";
|
|
5454
5094
|
var CHARS_PER_TOKEN2 = 4;
|
|
5455
5095
|
var EFFECTIVE_CONTENT_RATIO = 0.1;
|
|
5456
5096
|
var OUTPUT_TOKEN_RATIO = 0.1;
|
|
@@ -5490,8 +5130,8 @@ function formatTokenCount(tokens) {
|
|
|
5490
5130
|
|
|
5491
5131
|
// src/cli/commands/init/external-commands.ts
|
|
5492
5132
|
import { execFile, execFileSync } from "child_process";
|
|
5493
|
-
import
|
|
5494
|
-
import
|
|
5133
|
+
import fs6 from "fs/promises";
|
|
5134
|
+
import path11 from "path";
|
|
5495
5135
|
var OPENCLAW_PLUGIN_PACKAGE = "@agenr/agenr-plugin";
|
|
5496
5136
|
function execAsync(command, args, options) {
|
|
5497
5137
|
return new Promise((resolve, reject) => {
|
|
@@ -5588,10 +5228,10 @@ async function restartOpenClawGateway() {
|
|
|
5588
5228
|
}
|
|
5589
5229
|
}
|
|
5590
5230
|
async function writeOpenClawPluginConfig(stateDir, config) {
|
|
5591
|
-
const openclawConfigPath =
|
|
5231
|
+
const openclawConfigPath = path11.join(stateDir, "openclaw.json");
|
|
5592
5232
|
let root = {};
|
|
5593
5233
|
try {
|
|
5594
|
-
const raw = await
|
|
5234
|
+
const raw = await fs6.readFile(openclawConfigPath, "utf8");
|
|
5595
5235
|
const parsed = JSON.parse(raw);
|
|
5596
5236
|
if (isRecord(parsed)) {
|
|
5597
5237
|
root = parsed;
|
|
@@ -5617,13 +5257,13 @@ async function writeOpenClawPluginConfig(stateDir, config) {
|
|
|
5617
5257
|
} else {
|
|
5618
5258
|
delete entryConfig.configPath;
|
|
5619
5259
|
}
|
|
5620
|
-
await
|
|
5621
|
-
await
|
|
5260
|
+
await fs6.mkdir(stateDir, { recursive: true });
|
|
5261
|
+
await fs6.writeFile(openclawConfigPath, `${JSON.stringify(root, null, 2)}
|
|
5622
5262
|
`, "utf8");
|
|
5623
5263
|
return openclawConfigPath;
|
|
5624
5264
|
}
|
|
5625
5265
|
function shouldPersistPluginConfigPath(dbPath, configPath) {
|
|
5626
|
-
return
|
|
5266
|
+
return path11.dirname(dbPath) !== path11.dirname(configPath);
|
|
5627
5267
|
}
|
|
5628
5268
|
function isRecord(value) {
|
|
5629
5269
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -5650,32 +5290,32 @@ function ensureArrayOfStrings(target, key) {
|
|
|
5650
5290
|
}
|
|
5651
5291
|
|
|
5652
5292
|
// src/cli/commands/init/openclaw-detect.ts
|
|
5653
|
-
import
|
|
5654
|
-
import
|
|
5655
|
-
import
|
|
5293
|
+
import fs7 from "fs";
|
|
5294
|
+
import os2 from "os";
|
|
5295
|
+
import path12 from "path";
|
|
5656
5296
|
function resolveDefaultOpenClawStateDir() {
|
|
5657
|
-
return
|
|
5297
|
+
return path12.join(os2.homedir(), ".openclaw");
|
|
5658
5298
|
}
|
|
5659
|
-
function detectOpenClawInstallation(env = process.env, existsSyncFn =
|
|
5660
|
-
const envStateDir =
|
|
5299
|
+
function detectOpenClawInstallation(env = process.env, existsSyncFn = fs7.existsSync) {
|
|
5300
|
+
const envStateDir = normalizeOptionalString4(env.OPENCLAW_STATE_DIR) ?? normalizeOptionalString4(env.OPENCLAW_HOME);
|
|
5661
5301
|
const source = envStateDir ? "environment" : "default";
|
|
5662
|
-
const stateDir = envStateDir ?
|
|
5302
|
+
const stateDir = envStateDir ? resolveUserPath(envStateDir) : resolveDefaultOpenClawStateDir();
|
|
5663
5303
|
return {
|
|
5664
5304
|
detected: envStateDir !== void 0 || existsSyncFn(stateDir),
|
|
5665
5305
|
stateDir,
|
|
5666
|
-
configPath:
|
|
5667
|
-
sessionsRoot:
|
|
5306
|
+
configPath: path12.join(stateDir, "openclaw.json"),
|
|
5307
|
+
sessionsRoot: path12.join(stateDir, "agents"),
|
|
5668
5308
|
source
|
|
5669
5309
|
};
|
|
5670
5310
|
}
|
|
5671
|
-
function
|
|
5311
|
+
function normalizeOptionalString4(value) {
|
|
5672
5312
|
const trimmed = value?.trim();
|
|
5673
5313
|
return trimmed && trimmed.length > 0 ? trimmed : void 0;
|
|
5674
5314
|
}
|
|
5675
5315
|
|
|
5676
5316
|
// src/cli/commands/init/session-scanner.ts
|
|
5677
|
-
import
|
|
5678
|
-
import
|
|
5317
|
+
import fs8 from "fs/promises";
|
|
5318
|
+
import path13 from "path";
|
|
5679
5319
|
async function scanSessionFiles(sessionsRoot, recentDays = 7) {
|
|
5680
5320
|
const result = {
|
|
5681
5321
|
totalFiles: 0,
|
|
@@ -5700,7 +5340,7 @@ async function scanSessionFiles(sessionsRoot, recentDays = 7) {
|
|
|
5700
5340
|
}
|
|
5701
5341
|
let stat;
|
|
5702
5342
|
try {
|
|
5703
|
-
stat = await
|
|
5343
|
+
stat = await fs8.stat(filePath);
|
|
5704
5344
|
} catch (error) {
|
|
5705
5345
|
if (isMissingPathError(error)) {
|
|
5706
5346
|
continue;
|
|
@@ -5718,7 +5358,7 @@ async function scanSessionFiles(sessionsRoot, recentDays = 7) {
|
|
|
5718
5358
|
return result;
|
|
5719
5359
|
}
|
|
5720
5360
|
function isSessionTranscriptPath(filePath) {
|
|
5721
|
-
return filePath.split(
|
|
5361
|
+
return filePath.split(path13.sep).includes("sessions");
|
|
5722
5362
|
}
|
|
5723
5363
|
function isMissingPathError(error) {
|
|
5724
5364
|
return typeof error === "object" && error !== null && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR");
|
|
@@ -6089,7 +5729,7 @@ function registerInitCommand(program2) {
|
|
|
6089
5729
|
import * as clack6 from "@clack/prompts";
|
|
6090
5730
|
import { InvalidArgumentError as InvalidArgumentError4, Option as Option3 } from "commander";
|
|
6091
5731
|
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) => {
|
|
5732
|
+
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
5733
|
clack6.intro(banner());
|
|
6094
5734
|
let db = null;
|
|
6095
5735
|
try {
|
|
@@ -6098,23 +5738,37 @@ function registerRecallCommand(program2) {
|
|
|
6098
5738
|
const dbPath = config.dbPath;
|
|
6099
5739
|
const embeddingClient = createEmbeddingClient(resolveEmbeddingApiKey(config), resolveEmbeddingModel(config));
|
|
6100
5740
|
db = await createDatabase(dbPath);
|
|
6101
|
-
const
|
|
5741
|
+
const recallPorts = createRecallAdapter(db, embeddingClient);
|
|
5742
|
+
const crossEncoder = commandInput.rankingPolicy?.crossEncoder === "disabled" ? void 0 : tryCreateCrossEncoder(config);
|
|
5743
|
+
const adapter = attachCrossEncoderPort(recallPorts, crossEncoder);
|
|
6102
5744
|
let lastTraceSummary;
|
|
6103
5745
|
const spinner6 = clack6.spinner();
|
|
6104
5746
|
spinner6.start("Searching knowledge...");
|
|
6105
|
-
const
|
|
5747
|
+
const recallOptions = {
|
|
6106
5748
|
trace: {
|
|
6107
5749
|
reportSummary(summary) {
|
|
6108
5750
|
lastTraceSummary = summary;
|
|
6109
5751
|
}
|
|
6110
|
-
}
|
|
6111
|
-
|
|
5752
|
+
},
|
|
5753
|
+
...commandInput.rankingPolicy ? { rankingPolicy: commandInput.rankingPolicy } : {}
|
|
5754
|
+
};
|
|
5755
|
+
const results = await recall(commandInput.request, adapter, recallOptions);
|
|
6112
5756
|
spinner6.stop(`Found ${results.length} ${pluralize4(results.length, "result")}.`);
|
|
6113
5757
|
if (lastTraceSummary?.degraded.active) {
|
|
6114
5758
|
for (const notice of lastTraceSummary.degraded.notices) {
|
|
6115
5759
|
clack6.log.warn(notice);
|
|
6116
5760
|
}
|
|
6117
5761
|
}
|
|
5762
|
+
if (commandInput.verbose && lastTraceSummary) {
|
|
5763
|
+
const crossEncoder2 = lastTraceSummary.crossEncoder;
|
|
5764
|
+
if (crossEncoder2.applied) {
|
|
5765
|
+
clack6.log.info(
|
|
5766
|
+
`Cross-encoder reranked top-${crossEncoder2.k} (alpha=${crossEncoder2.alpha.toFixed(2)}, latencyMs=${crossEncoder2.latencyMs}, rescored=${crossEncoder2.rescoredIds.length}).`
|
|
5767
|
+
);
|
|
5768
|
+
} else if (crossEncoder2.degradedReason) {
|
|
5769
|
+
clack6.log.info(`Cross-encoder skipped (${crossEncoder2.degradedReason}).`);
|
|
5770
|
+
}
|
|
5771
|
+
}
|
|
6118
5772
|
if (results.length === 0) {
|
|
6119
5773
|
clack6.outro("No matching entries found.");
|
|
6120
5774
|
return;
|
|
@@ -6133,10 +5787,11 @@ function registerRecallCommand(program2) {
|
|
|
6133
5787
|
});
|
|
6134
5788
|
}
|
|
6135
5789
|
function normalizeRecallCommand(query, options) {
|
|
6136
|
-
const normalizedQuery =
|
|
5790
|
+
const normalizedQuery = normalizeOptionalString2(query);
|
|
6137
5791
|
if (!normalizedQuery) {
|
|
6138
5792
|
throw new InvalidArgumentError4("Query cannot be empty.");
|
|
6139
5793
|
}
|
|
5794
|
+
const rankingPolicy = buildRankingPolicy(options);
|
|
6140
5795
|
return {
|
|
6141
5796
|
request: {
|
|
6142
5797
|
text: normalizedQuery,
|
|
@@ -6145,15 +5800,38 @@ function normalizeRecallCommand(query, options) {
|
|
|
6145
5800
|
budget: options.budget,
|
|
6146
5801
|
types: options.types,
|
|
6147
5802
|
tags: normalizeStringList(options.tags),
|
|
6148
|
-
since:
|
|
6149
|
-
until:
|
|
6150
|
-
around:
|
|
5803
|
+
since: normalizeOptionalString2(options.since),
|
|
5804
|
+
until: normalizeOptionalString2(options.until),
|
|
5805
|
+
around: normalizeOptionalString2(options.around),
|
|
6151
5806
|
aroundRadius: options.aroundRadius,
|
|
6152
|
-
asOf:
|
|
5807
|
+
asOf: normalizeOptionalString2(options.asOf)
|
|
6153
5808
|
},
|
|
6154
|
-
verbose: options.verbose === true
|
|
5809
|
+
verbose: options.verbose === true,
|
|
5810
|
+
...rankingPolicy ? { rankingPolicy } : {}
|
|
6155
5811
|
};
|
|
6156
5812
|
}
|
|
5813
|
+
function buildRankingPolicy(options) {
|
|
5814
|
+
const policy = {};
|
|
5815
|
+
if (options.crossEncoder !== void 0) {
|
|
5816
|
+
policy.crossEncoder = options.crossEncoder;
|
|
5817
|
+
}
|
|
5818
|
+
if (typeof options.crossEncoderTopK === "number") {
|
|
5819
|
+
policy.crossEncoderTopK = options.crossEncoderTopK;
|
|
5820
|
+
}
|
|
5821
|
+
if (typeof options.crossEncoderAlpha === "number") {
|
|
5822
|
+
policy.crossEncoderAlpha = options.crossEncoderAlpha;
|
|
5823
|
+
}
|
|
5824
|
+
return Object.keys(policy).length > 0 ? policy : void 0;
|
|
5825
|
+
}
|
|
5826
|
+
function tryCreateCrossEncoder(config) {
|
|
5827
|
+
try {
|
|
5828
|
+
const apiKey = resolveCrossEncoderApiKey(config);
|
|
5829
|
+
const { modelId } = resolveModel(config, "cross_encoder");
|
|
5830
|
+
return createOpenAICrossEncoder({ apiKey, model: modelId });
|
|
5831
|
+
} catch {
|
|
5832
|
+
return void 0;
|
|
5833
|
+
}
|
|
5834
|
+
}
|
|
6157
5835
|
function formatResult(result, verbose, asOf) {
|
|
6158
5836
|
const projected = projectClaimCentricRecallEntry(result, {
|
|
6159
5837
|
asOf
|
|
@@ -6171,8 +5849,9 @@ function formatResult(result, verbose, asOf) {
|
|
|
6171
5849
|
}
|
|
6172
5850
|
lines.push(` why=${projected.whySurfaced.summary}`);
|
|
6173
5851
|
if (verbose) {
|
|
5852
|
+
const crossEncoderFragment = typeof result.scores.crossEncoder === "number" ? ` crossEncoder=${result.scores.crossEncoder.toFixed(2)}` : "";
|
|
6174
5853
|
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)}`
|
|
5854
|
+
` 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
5855
|
);
|
|
6177
5856
|
}
|
|
6178
5857
|
return lines.join("\n");
|
|
@@ -6226,8 +5905,8 @@ import { InvalidArgumentError as InvalidArgumentError5, Option as Option4 } from
|
|
|
6226
5905
|
// src/app/scenarios/claim-keys/runtime.ts
|
|
6227
5906
|
import { randomUUID as randomUUID11 } from "crypto";
|
|
6228
5907
|
import { mkdir as mkdir2, writeFile } from "fs/promises";
|
|
6229
|
-
import
|
|
6230
|
-
import { getModel
|
|
5908
|
+
import path20 from "path";
|
|
5909
|
+
import { getModel } from "@earendil-works/pi-ai";
|
|
6231
5910
|
|
|
6232
5911
|
// src/adapters/db/surgeon-run-log.ts
|
|
6233
5912
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
@@ -6288,9 +5967,9 @@ async function createSurgeonRun(executor, run) {
|
|
|
6288
5967
|
args: [
|
|
6289
5968
|
id,
|
|
6290
5969
|
run.passType,
|
|
6291
|
-
|
|
5970
|
+
normalizeOptionalString5(run.project),
|
|
6292
5971
|
startedAt,
|
|
6293
|
-
|
|
5972
|
+
normalizeOptionalString5(run.model ?? void 0),
|
|
6294
5973
|
run.dryRun ? 1 : 0,
|
|
6295
5974
|
JSON.stringify(run.config ?? null)
|
|
6296
5975
|
]
|
|
@@ -6323,7 +6002,7 @@ async function completeSurgeonRun(executor, runId, result) {
|
|
|
6323
6002
|
normalizeInteger(result.actionsSkipped),
|
|
6324
6003
|
normalizeInteger(result.entriesRetired),
|
|
6325
6004
|
JSON.stringify(result.summaryJson ?? null),
|
|
6326
|
-
|
|
6005
|
+
normalizeOptionalString5(result.error ?? void 0),
|
|
6327
6006
|
runId.trim()
|
|
6328
6007
|
]
|
|
6329
6008
|
});
|
|
@@ -6460,7 +6139,7 @@ async function logSurgeonProposal(executor, proposal) {
|
|
|
6460
6139
|
proposal.eligibleForApply ? 1 : 0,
|
|
6461
6140
|
reviewStatus,
|
|
6462
6141
|
normalizeTimestamp(reviewedAt ?? void 0),
|
|
6463
|
-
|
|
6142
|
+
normalizeOptionalString5(reviewReason ?? void 0),
|
|
6464
6143
|
normalizeInteger(appliedActionCount ?? 0),
|
|
6465
6144
|
normalizeTimestamp(proposal.createdAt) ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
6466
6145
|
]
|
|
@@ -6824,7 +6503,7 @@ function normalizeEntryIds(entryIds) {
|
|
|
6824
6503
|
function normalizeStringArray(values) {
|
|
6825
6504
|
return Array.from(new Set(values.map((value) => value.trim()).filter((value) => value.length > 0)));
|
|
6826
6505
|
}
|
|
6827
|
-
function
|
|
6506
|
+
function normalizeOptionalString5(value) {
|
|
6828
6507
|
if (value === void 0) {
|
|
6829
6508
|
return null;
|
|
6830
6509
|
}
|
|
@@ -6832,7 +6511,7 @@ function normalizeOptionalString6(value) {
|
|
|
6832
6511
|
return trimmed.length > 0 ? trimmed : null;
|
|
6833
6512
|
}
|
|
6834
6513
|
function normalizeTimestamp(value) {
|
|
6835
|
-
return
|
|
6514
|
+
return normalizeOptionalString5(value);
|
|
6836
6515
|
}
|
|
6837
6516
|
function normalizeInteger(value) {
|
|
6838
6517
|
if (!Number.isFinite(value)) {
|
|
@@ -7125,7 +6804,7 @@ async function listRetirementCandidates(executor, query) {
|
|
|
7125
6804
|
}
|
|
7126
6805
|
async function listSupersessionCandidates(executor, query) {
|
|
7127
6806
|
const scope = normalizeSupersessionScope(query.scope);
|
|
7128
|
-
const type =
|
|
6807
|
+
const type = normalizeOptionalString6(query.type);
|
|
7129
6808
|
const scopes = scope === "all" ? ["claim_key", "subject"] : [scope];
|
|
7130
6809
|
const clusters = (await Promise.all(
|
|
7131
6810
|
scopes.map(async (currentScope) => {
|
|
@@ -7139,7 +6818,7 @@ async function listSupersessionCandidates(executor, query) {
|
|
|
7139
6818
|
return limit === null ? filteredClusters.slice(offset) : filteredClusters.slice(offset, offset + limit);
|
|
7140
6819
|
}
|
|
7141
6820
|
async function countSupersessionCandidates(executor, query) {
|
|
7142
|
-
const type =
|
|
6821
|
+
const type = normalizeOptionalString6(query.type);
|
|
7143
6822
|
const skippedEntryIds = typeof query.skipRecentlyEvaluatedDays === "number" && Number.isFinite(query.skipRecentlyEvaluatedDays) && query.skipRecentlyEvaluatedDays > 0 ? await loadRecentlySkippedSupersessionEntryIds(executor, {
|
|
7144
6823
|
now: query.now ?? /* @__PURE__ */ new Date(),
|
|
7145
6824
|
skipRecentlyEvaluatedDays: query.skipRecentlyEvaluatedDays
|
|
@@ -7352,17 +7031,17 @@ async function inspectSurgeonEntry(executor, entryId) {
|
|
|
7352
7031
|
async function listClaimKeyQualityEntries(executor, query) {
|
|
7353
7032
|
const whereClauses = [query.includeInactive === true ? "1 = 1" : buildActiveEntryClause("e")];
|
|
7354
7033
|
const args = [];
|
|
7355
|
-
const project =
|
|
7034
|
+
const project = normalizeOptionalString6(query.project);
|
|
7356
7035
|
if (project) {
|
|
7357
7036
|
whereClauses.push(`(e.project = ? OR ${buildTagContainsClause("e")})`);
|
|
7358
7037
|
args.push(project, project);
|
|
7359
7038
|
}
|
|
7360
|
-
const type =
|
|
7039
|
+
const type = normalizeOptionalString6(query.type);
|
|
7361
7040
|
if (type) {
|
|
7362
7041
|
whereClauses.push("e.type = ?");
|
|
7363
7042
|
args.push(type);
|
|
7364
7043
|
}
|
|
7365
|
-
const claimKeyPrefix =
|
|
7044
|
+
const claimKeyPrefix = normalizeOptionalString6(query.claimKeyPrefix);
|
|
7366
7045
|
if (claimKeyPrefix) {
|
|
7367
7046
|
whereClauses.push("e.claim_key LIKE ?");
|
|
7368
7047
|
args.push(`${claimKeyPrefix}/%`);
|
|
@@ -7394,7 +7073,7 @@ function buildCandidateFilter(query) {
|
|
|
7394
7073
|
const protectMinImportance = normalizeNonNegativeInteger(query.protectMinImportance);
|
|
7395
7074
|
const protectRecalledDays = normalizeNonNegativeInteger(query.protectRecalledDays);
|
|
7396
7075
|
const protectRecalledCutoffIso = new Date(now.getTime() - protectRecalledDays * DAY_MS).toISOString();
|
|
7397
|
-
const currentRunId =
|
|
7076
|
+
const currentRunId = normalizeOptionalString6(query.runId);
|
|
7398
7077
|
const whereClauses = [buildActiveEntryClause("e"), "e.expiry <> 'core'", "e.importance < ?", "(e.last_recalled_at IS NULL OR e.last_recalled_at < ?)"];
|
|
7399
7078
|
const args = [protectMinImportance, protectRecalledCutoffIso];
|
|
7400
7079
|
if (currentRunId) {
|
|
@@ -7407,12 +7086,12 @@ function buildCandidateFilter(query) {
|
|
|
7407
7086
|
)`);
|
|
7408
7087
|
args.push(currentRunId, ...SURGEON_RETIREMENT_SAME_RUN_SUPPRESSION_ACTION_TYPES);
|
|
7409
7088
|
}
|
|
7410
|
-
const project =
|
|
7089
|
+
const project = normalizeOptionalString6(query.project);
|
|
7411
7090
|
if (project) {
|
|
7412
7091
|
whereClauses.push(buildTagContainsClause("e"));
|
|
7413
7092
|
args.push(project);
|
|
7414
7093
|
}
|
|
7415
|
-
const type =
|
|
7094
|
+
const type = normalizeOptionalString6(query.type);
|
|
7416
7095
|
if (type) {
|
|
7417
7096
|
whereClauses.push("e.type = ?");
|
|
7418
7097
|
args.push(type);
|
|
@@ -7623,7 +7302,7 @@ function normalizeNonNegativeInteger(value) {
|
|
|
7623
7302
|
}
|
|
7624
7303
|
return Math.max(0, Math.floor(value));
|
|
7625
7304
|
}
|
|
7626
|
-
function
|
|
7305
|
+
function normalizeOptionalString6(value) {
|
|
7627
7306
|
if (value === void 0) {
|
|
7628
7307
|
return null;
|
|
7629
7308
|
}
|
|
@@ -7713,9 +7392,9 @@ function createSurgeonPort(executor) {
|
|
|
7713
7392
|
|
|
7714
7393
|
// src/app/surgeon/service.ts
|
|
7715
7394
|
import { randomUUID as randomUUID9 } from "crypto";
|
|
7716
|
-
import
|
|
7717
|
-
import
|
|
7718
|
-
import { runAgentLoop } from "@
|
|
7395
|
+
import fs10 from "fs";
|
|
7396
|
+
import path15 from "path";
|
|
7397
|
+
import { runAgentLoop } from "@earendil-works/pi-agent-core";
|
|
7719
7398
|
|
|
7720
7399
|
// src/core/surgeon/domain/run-presets.ts
|
|
7721
7400
|
var AUTONOMOUS_SURGEON_SEQUENCE = ["claim_key_quality", "proposal_resolution", "supersession", "retirement"];
|
|
@@ -7994,9 +7673,9 @@ var SHADOW_BUCKET_ORDER = [
|
|
|
7994
7673
|
async function runClaimKeyQualityPass(options, deps) {
|
|
7995
7674
|
const selection = {
|
|
7996
7675
|
includeInactive: options.includeInactive === true,
|
|
7997
|
-
project:
|
|
7998
|
-
type:
|
|
7999
|
-
claimKeyPrefix:
|
|
7676
|
+
project: normalizeOptionalString7(options.project) ?? null,
|
|
7677
|
+
type: normalizeOptionalString7(options.type) ?? null,
|
|
7678
|
+
claimKeyPrefix: normalizeOptionalString7(options.claimKeyPrefix) ?? null,
|
|
8000
7679
|
entryIds: normalizeStringArray3(options.entryIds ?? [])
|
|
8001
7680
|
};
|
|
8002
7681
|
const executionStyle = selection.includeInactive || selection.type !== null || selection.claimKeyPrefix !== null || selection.entryIds.length > 0 ? "targeted" : "autonomous";
|
|
@@ -9231,7 +8910,7 @@ function cloneEntry(entry) {
|
|
|
9231
8910
|
embedding: entry.embedding ? [...entry.embedding] : void 0
|
|
9232
8911
|
};
|
|
9233
8912
|
}
|
|
9234
|
-
function
|
|
8913
|
+
function normalizeOptionalString7(value) {
|
|
9235
8914
|
const trimmed = value?.trim();
|
|
9236
8915
|
return trimmed ? trimmed : null;
|
|
9237
8916
|
}
|
|
@@ -10440,8 +10119,8 @@ async function applyProposalToEntries(input, deps) {
|
|
|
10440
10119
|
}
|
|
10441
10120
|
|
|
10442
10121
|
// src/app/surgeon/trace-logger.ts
|
|
10443
|
-
import
|
|
10444
|
-
import
|
|
10122
|
+
import fs9 from "fs";
|
|
10123
|
+
import path14 from "path";
|
|
10445
10124
|
var TRACE_MAX_STRING_LENGTH = 320;
|
|
10446
10125
|
var TRACE_MAX_ARRAY_ITEMS = 12;
|
|
10447
10126
|
var TRACE_MAX_OBJECT_KEYS = 20;
|
|
@@ -10649,8 +10328,8 @@ function appendTrace(tracePath, payload, logger) {
|
|
|
10649
10328
|
return;
|
|
10650
10329
|
}
|
|
10651
10330
|
try {
|
|
10652
|
-
|
|
10653
|
-
|
|
10331
|
+
fs9.mkdirSync(path14.dirname(tracePath), { recursive: true });
|
|
10332
|
+
fs9.appendFileSync(tracePath, `${JSON.stringify({ timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...payload })}
|
|
10654
10333
|
`, "utf8");
|
|
10655
10334
|
} catch (error) {
|
|
10656
10335
|
logger.warn(`failed to write trace file ${tracePath}: ${formatError2(error)}`);
|
|
@@ -11547,10 +11226,10 @@ function createQueryCandidatesTool(deps) {
|
|
|
11547
11226
|
const offset = normalizeOffset2(params.offset);
|
|
11548
11227
|
const page = await deps.port.listRetirementCandidates({
|
|
11549
11228
|
scope,
|
|
11550
|
-
type:
|
|
11229
|
+
type: normalizeOptionalString8(params.type),
|
|
11551
11230
|
importanceMax: params.importance_max,
|
|
11552
11231
|
minAgeDays: params.min_age_days,
|
|
11553
|
-
project:
|
|
11232
|
+
project: normalizeOptionalString8(params.project) ?? deps.project,
|
|
11554
11233
|
limit,
|
|
11555
11234
|
offset,
|
|
11556
11235
|
protectRecalledDays: deps.protection.protectRecalledDays,
|
|
@@ -11613,7 +11292,7 @@ function normalizeOffset2(value) {
|
|
|
11613
11292
|
function normalizeScope2(value) {
|
|
11614
11293
|
return value === "all" ? "all" : "actionable";
|
|
11615
11294
|
}
|
|
11616
|
-
function
|
|
11295
|
+
function normalizeOptionalString8(value) {
|
|
11617
11296
|
const normalized = value?.trim();
|
|
11618
11297
|
return normalized ? normalized : void 0;
|
|
11619
11298
|
}
|
|
@@ -11639,7 +11318,7 @@ function createSimulateRecallTool(deps) {
|
|
|
11639
11318
|
if (!deps.recallPorts) {
|
|
11640
11319
|
throw new Error("Recall simulation is unavailable because no embedding-enabled recall ports are configured.");
|
|
11641
11320
|
}
|
|
11642
|
-
const excludeEntryId =
|
|
11321
|
+
const excludeEntryId = normalizeOptionalString9(params.exclude_entry_id);
|
|
11643
11322
|
const results = await recall(
|
|
11644
11323
|
{
|
|
11645
11324
|
text: params.query.trim(),
|
|
@@ -11673,17 +11352,17 @@ function createSimulationRecallPorts(inner, excludeEntryId) {
|
|
|
11673
11352
|
}
|
|
11674
11353
|
return results.filter((result) => result.entry.id !== excludeEntryId);
|
|
11675
11354
|
},
|
|
11676
|
-
async
|
|
11677
|
-
if (!inner.
|
|
11355
|
+
async expandNeighborhood(request) {
|
|
11356
|
+
if (!inner.expandNeighborhood) {
|
|
11678
11357
|
return [];
|
|
11679
11358
|
}
|
|
11680
|
-
const
|
|
11681
|
-
if (
|
|
11359
|
+
const seedIds = excludeEntryId ? request.seedIds.filter((id) => id !== excludeEntryId) : request.seedIds;
|
|
11360
|
+
if (seedIds.length === 0) {
|
|
11682
11361
|
return [];
|
|
11683
11362
|
}
|
|
11684
|
-
const results = await inner.
|
|
11685
|
-
...
|
|
11686
|
-
|
|
11363
|
+
const results = await inner.expandNeighborhood({
|
|
11364
|
+
...request,
|
|
11365
|
+
seedIds
|
|
11687
11366
|
});
|
|
11688
11367
|
if (!excludeEntryId) {
|
|
11689
11368
|
return results;
|
|
@@ -11704,7 +11383,7 @@ function normalizeLimit3(value) {
|
|
|
11704
11383
|
}
|
|
11705
11384
|
return Math.floor(value);
|
|
11706
11385
|
}
|
|
11707
|
-
function
|
|
11386
|
+
function normalizeOptionalString9(value) {
|
|
11708
11387
|
const normalized = value?.trim();
|
|
11709
11388
|
return normalized ? normalized : void 0;
|
|
11710
11389
|
}
|
|
@@ -11984,7 +11663,7 @@ function createQuerySupersessionCandidatesTool(deps) {
|
|
|
11984
11663
|
const scope = normalizeScope3(params.scope);
|
|
11985
11664
|
const limit = normalizeLimit4(params.limit);
|
|
11986
11665
|
const offset = normalizeOffset3(params.offset);
|
|
11987
|
-
const type =
|
|
11666
|
+
const type = normalizeOptionalString10(params.type);
|
|
11988
11667
|
const progress = deps.completionGuards?.supersession.snapshot();
|
|
11989
11668
|
if ((scope === "subject" || scope === "all") && shouldBlockLowerConfidenceScope(progress)) {
|
|
11990
11669
|
return toolResult({
|
|
@@ -12092,7 +11771,7 @@ function normalizeScope3(value) {
|
|
|
12092
11771
|
}
|
|
12093
11772
|
return "claim_key";
|
|
12094
11773
|
}
|
|
12095
|
-
function
|
|
11774
|
+
function normalizeOptionalString10(value) {
|
|
12096
11775
|
const normalized = value?.trim();
|
|
12097
11776
|
return normalized ? normalized : void 0;
|
|
12098
11777
|
}
|
|
@@ -13199,8 +12878,8 @@ function resolveTracePath(tracePath, passType, runId) {
|
|
|
13199
12878
|
return void 0;
|
|
13200
12879
|
}
|
|
13201
12880
|
try {
|
|
13202
|
-
if (
|
|
13203
|
-
return
|
|
12881
|
+
if (fs10.statSync(tracePath).isDirectory()) {
|
|
12882
|
+
return path15.join(tracePath, `surgeon-${passType}-${runId}.jsonl`);
|
|
13204
12883
|
}
|
|
13205
12884
|
} catch {
|
|
13206
12885
|
return tracePath;
|
|
@@ -14102,7 +13781,7 @@ function formatValue(value) {
|
|
|
14102
13781
|
}
|
|
14103
13782
|
|
|
14104
13783
|
// src/app/scenarios/claim-keys/deterministic-fixtures.ts
|
|
14105
|
-
import { createHash as
|
|
13784
|
+
import { createHash as createHash2 } from "crypto";
|
|
14106
13785
|
var DEFAULT_CONTEXT_WINDOW_TOKENS2 = 16e3;
|
|
14107
13786
|
var DEFAULT_MAX_OUTPUT_TOKENS = 4e3;
|
|
14108
13787
|
var EMBEDDING_DIMENSIONS = 1024;
|
|
@@ -14160,7 +13839,7 @@ function hashToVector(text2, dimensions) {
|
|
|
14160
13839
|
const vector = [];
|
|
14161
13840
|
let counter = 0;
|
|
14162
13841
|
while (vector.length < dimensions) {
|
|
14163
|
-
const block =
|
|
13842
|
+
const block = createHash2("sha256").update(text2).update(String(counter)).digest();
|
|
14164
13843
|
for (let offset = 0; offset + 4 <= block.length && vector.length < dimensions; offset += 4) {
|
|
14165
13844
|
vector.push(block.readInt32LE(offset) / 2147483647);
|
|
14166
13845
|
}
|
|
@@ -14202,7 +13881,7 @@ function isFixtureError(value) {
|
|
|
14202
13881
|
|
|
14203
13882
|
// src/app/scenarios/claim-keys/fixture-loader.ts
|
|
14204
13883
|
import { readFile } from "fs/promises";
|
|
14205
|
-
import
|
|
13884
|
+
import path17 from "path";
|
|
14206
13885
|
|
|
14207
13886
|
// src/app/scenarios/claim-keys/validation/shared.ts
|
|
14208
13887
|
var SUPPORTED_PROPOSAL_SCOPES = ["single_entry", "cluster"];
|
|
@@ -14532,12 +14211,12 @@ function readRequiredTrue(value, label, filePath) {
|
|
|
14532
14211
|
|
|
14533
14212
|
// src/app/scenarios/claim-keys/validation/scenario-root.ts
|
|
14534
14213
|
import { existsSync } from "fs";
|
|
14535
|
-
import
|
|
14214
|
+
import path16 from "path";
|
|
14536
14215
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
14537
14216
|
var SCENARIO_ROOT_SEGMENTS = ["tests", "scenarios", "claim-keys"];
|
|
14538
14217
|
function getDefaultClaimKeyScenarioRoot(options = {}) {
|
|
14539
|
-
const moduleDirectory =
|
|
14540
|
-
const startDirectories = Array.from(/* @__PURE__ */ new Set([
|
|
14218
|
+
const moduleDirectory = path16.dirname(fileURLToPath2(options.moduleUrl ?? import.meta.url));
|
|
14219
|
+
const startDirectories = Array.from(/* @__PURE__ */ new Set([path16.resolve(options.cwd ?? process.cwd()), moduleDirectory]));
|
|
14541
14220
|
for (const startDirectory of startDirectories) {
|
|
14542
14221
|
const discovered = findScenarioRootFrom(startDirectory);
|
|
14543
14222
|
if (discovered) {
|
|
@@ -14559,24 +14238,24 @@ function readOptionalRelativeFixturePath(value, label, filePath, rootDir) {
|
|
|
14559
14238
|
return readRelativeFixturePath(value, label, filePath, rootDir);
|
|
14560
14239
|
}
|
|
14561
14240
|
function normalizeFixturePath(relativePath, rootDir, filePath, label) {
|
|
14562
|
-
if (
|
|
14241
|
+
if (path16.isAbsolute(relativePath)) {
|
|
14563
14242
|
throw new Error(`Invalid scenario ${filePath}: ${label} must be relative to the scenario root.`);
|
|
14564
14243
|
}
|
|
14565
|
-
const resolved =
|
|
14566
|
-
const relative =
|
|
14567
|
-
if (relative.startsWith("..") ||
|
|
14244
|
+
const resolved = path16.resolve(rootDir, relativePath);
|
|
14245
|
+
const relative = path16.relative(rootDir, resolved);
|
|
14246
|
+
if (relative.startsWith("..") || path16.isAbsolute(relative)) {
|
|
14568
14247
|
throw new Error(`Invalid scenario ${filePath}: ${label} must stay inside the scenario root.`);
|
|
14569
14248
|
}
|
|
14570
|
-
return relative.split(
|
|
14249
|
+
return relative.split(path16.sep).join("/");
|
|
14571
14250
|
}
|
|
14572
14251
|
function findScenarioRootFrom(startDirectory) {
|
|
14573
|
-
let currentDirectory =
|
|
14252
|
+
let currentDirectory = path16.resolve(startDirectory);
|
|
14574
14253
|
while (true) {
|
|
14575
|
-
const candidate =
|
|
14254
|
+
const candidate = path16.join(currentDirectory, ...SCENARIO_ROOT_SEGMENTS);
|
|
14576
14255
|
if (existsSync(candidate)) {
|
|
14577
14256
|
return candidate;
|
|
14578
14257
|
}
|
|
14579
|
-
const parentDirectory =
|
|
14258
|
+
const parentDirectory = path16.dirname(currentDirectory);
|
|
14580
14259
|
if (parentDirectory === currentDirectory) {
|
|
14581
14260
|
return void 0;
|
|
14582
14261
|
}
|
|
@@ -14919,7 +14598,7 @@ async function loadSeedFixtureEntries(rootDir, relativePath) {
|
|
|
14919
14598
|
if (!relativePath) {
|
|
14920
14599
|
return null;
|
|
14921
14600
|
}
|
|
14922
|
-
const parsed = await readJsonFile(
|
|
14601
|
+
const parsed = await readJsonFile(path17.join(rootDir, relativePath));
|
|
14923
14602
|
const seedEntries = readSeedEntries(parsed, relativePath);
|
|
14924
14603
|
if (!seedEntries) {
|
|
14925
14604
|
throw new Error(`Seed fixture ${relativePath} must contain an array.`);
|
|
@@ -14982,7 +14661,7 @@ async function readArrayFixture(rootDir, relativePath) {
|
|
|
14982
14661
|
if (!relativePath) {
|
|
14983
14662
|
return null;
|
|
14984
14663
|
}
|
|
14985
|
-
const parsed = await readJsonFile(
|
|
14664
|
+
const parsed = await readJsonFile(path17.join(rootDir, relativePath));
|
|
14986
14665
|
if (!Array.isArray(parsed)) {
|
|
14987
14666
|
throw new Error(`Fixture file ${relativePath} must contain a JSON array.`);
|
|
14988
14667
|
}
|
|
@@ -15036,7 +14715,7 @@ function readExtractionImportance(value, label, filePath) {
|
|
|
15036
14715
|
|
|
15037
14716
|
// src/app/scenarios/claim-keys/load-scenarios.ts
|
|
15038
14717
|
import { readdir, readFile as readFile2 } from "fs/promises";
|
|
15039
|
-
import
|
|
14718
|
+
import path18 from "path";
|
|
15040
14719
|
|
|
15041
14720
|
// src/app/scenarios/claim-keys/validation/expectations.ts
|
|
15042
14721
|
var EXPECTATION_KEYS = /* @__PURE__ */ new Set(["warnings", "rows", "rowCount", "proposals", "storeResult", "surgeonSummary"]);
|
|
@@ -15298,13 +14977,13 @@ function validateClaimKeyScenario(input, filePath, rootDir = getDefaultClaimKeyS
|
|
|
15298
14977
|
async function discoverScenarioFiles(rootDir) {
|
|
15299
14978
|
const files = [];
|
|
15300
14979
|
for (const kind of SUPPORTED_KINDS2) {
|
|
15301
|
-
const directory =
|
|
14980
|
+
const directory = path18.join(rootDir, kind);
|
|
15302
14981
|
const entries = await readdir(directory, { withFileTypes: true });
|
|
15303
14982
|
for (const entry of entries) {
|
|
15304
14983
|
if (!entry.isFile() || !entry.name.endsWith(".json")) {
|
|
15305
14984
|
continue;
|
|
15306
14985
|
}
|
|
15307
|
-
files.push(
|
|
14986
|
+
files.push(path18.join(directory, entry.name));
|
|
15308
14987
|
}
|
|
15309
14988
|
}
|
|
15310
14989
|
return files.sort();
|
|
@@ -15322,11 +15001,11 @@ async function readScenarioJsonFile(filePath) {
|
|
|
15322
15001
|
|
|
15323
15002
|
// src/app/scenarios/claim-keys/sandbox.ts
|
|
15324
15003
|
import { mkdir, rm } from "fs/promises";
|
|
15325
|
-
import
|
|
15004
|
+
import path19 from "path";
|
|
15326
15005
|
var SANDBOX_DB_FILENAME = "knowledge.db";
|
|
15327
15006
|
async function createClaimKeyScenarioSandbox(root) {
|
|
15328
|
-
const resolvedRoot =
|
|
15329
|
-
const dbPath =
|
|
15007
|
+
const resolvedRoot = path19.resolve(root);
|
|
15008
|
+
const dbPath = path19.join(resolvedRoot, SANDBOX_DB_FILENAME);
|
|
15330
15009
|
await mkdir(resolvedRoot, { recursive: true });
|
|
15331
15010
|
await removeDatabaseFiles(dbPath);
|
|
15332
15011
|
const database = await createDatabase(dbPath);
|
|
@@ -15351,7 +15030,7 @@ async function removeDatabaseFiles(dbPath) {
|
|
|
15351
15030
|
import { randomUUID as randomUUID10 } from "crypto";
|
|
15352
15031
|
var DEFAULT_SCENARIO_CREATED_AT = "2026-04-01T10:00:00.000Z";
|
|
15353
15032
|
function buildClaimKeyScenarioSeedEntry(seedEntry) {
|
|
15354
|
-
const seedClaimKey =
|
|
15033
|
+
const seedClaimKey = normalizeOptionalString11(seedEntry.claim_key);
|
|
15355
15034
|
const preserveLegacyStoredClaimKey = shouldPreserveLegacyStoredClaimKey(seedClaimKey);
|
|
15356
15035
|
const validatedInput = validateSeedStoreInput(seedEntry, preserveLegacyStoredClaimKey);
|
|
15357
15036
|
const lifecycle = preserveLegacyStoredClaimKey ? resolveLegacySeedClaimKeyLifecycle(seedEntry) : resolveSeedClaimKeyLifecycle(seedEntry, validatedInput);
|
|
@@ -15373,11 +15052,11 @@ function buildClaimKeyScenarioSeedEntry(seedEntry) {
|
|
|
15373
15052
|
quality_score: 0.5,
|
|
15374
15053
|
recall_count: 0,
|
|
15375
15054
|
last_recalled_at: void 0,
|
|
15376
|
-
superseded_by:
|
|
15055
|
+
superseded_by: normalizeOptionalString11(seedEntry.superseded_by),
|
|
15377
15056
|
valid_from: validatedInput.valid_from,
|
|
15378
15057
|
valid_to: validatedInput.valid_to,
|
|
15379
15058
|
claim_key: preserveLegacyStoredClaimKey ? seedClaimKey : lifecycle?.claim_key,
|
|
15380
|
-
claim_key_raw: preserveLegacyStoredClaimKey ?
|
|
15059
|
+
claim_key_raw: preserveLegacyStoredClaimKey ? normalizeOptionalString11(seedEntry.claim_key_raw) : lifecycle?.claim_key_raw,
|
|
15381
15060
|
claim_key_status: lifecycle?.claim_key_status,
|
|
15382
15061
|
claim_key_source: lifecycle?.claim_key_source,
|
|
15383
15062
|
claim_key_confidence: lifecycle?.claim_key_confidence,
|
|
@@ -15392,8 +15071,8 @@ function buildClaimKeyScenarioSeedEntry(seedEntry) {
|
|
|
15392
15071
|
user_id: validatedInput.user_id,
|
|
15393
15072
|
project: validatedInput.project,
|
|
15394
15073
|
retired: seedEntry.retired ?? false,
|
|
15395
|
-
retired_at:
|
|
15396
|
-
retired_reason:
|
|
15074
|
+
retired_at: normalizeOptionalString11(seedEntry.retired_at),
|
|
15075
|
+
retired_reason: normalizeOptionalString11(seedEntry.retired_reason),
|
|
15397
15076
|
created_at: createdAt,
|
|
15398
15077
|
updated_at: updatedAt
|
|
15399
15078
|
};
|
|
@@ -15479,14 +15158,14 @@ function resolveLegacySeedClaimKeyLifecycle(seedEntry) {
|
|
|
15479
15158
|
}
|
|
15480
15159
|
return {
|
|
15481
15160
|
claim_key: seedEntry.claim_key.trim(),
|
|
15482
|
-
claim_key_raw:
|
|
15161
|
+
claim_key_raw: normalizeOptionalString11(seedEntry.claim_key_raw),
|
|
15483
15162
|
claim_key_status: seedEntry.claim_key_status,
|
|
15484
15163
|
claim_key_source: seedEntry.claim_key_source,
|
|
15485
15164
|
claim_key_confidence: seedEntry.claim_key_confidence,
|
|
15486
15165
|
claim_key_rationale: seedEntry.claim_key_rationale.trim(),
|
|
15487
|
-
claim_support_source_kind:
|
|
15488
|
-
claim_support_locator:
|
|
15489
|
-
claim_support_observed_at:
|
|
15166
|
+
claim_support_source_kind: normalizeOptionalString11(seedEntry.claim_support_source_kind),
|
|
15167
|
+
claim_support_locator: normalizeOptionalString11(seedEntry.claim_support_locator),
|
|
15168
|
+
claim_support_observed_at: normalizeOptionalString11(seedEntry.claim_support_observed_at),
|
|
15490
15169
|
claim_support_mode: seedEntry.claim_support_mode
|
|
15491
15170
|
};
|
|
15492
15171
|
}
|
|
@@ -15497,7 +15176,7 @@ function shouldPreserveLegacyStoredClaimKey(claimKey) {
|
|
|
15497
15176
|
const normalized = normalizeClaimKey(claimKey);
|
|
15498
15177
|
return !normalized.ok || normalized.value.claimKey !== claimKey;
|
|
15499
15178
|
}
|
|
15500
|
-
function
|
|
15179
|
+
function normalizeOptionalString11(value) {
|
|
15501
15180
|
const normalized = value?.trim();
|
|
15502
15181
|
return normalized && normalized.length > 0 ? normalized : void 0;
|
|
15503
15182
|
}
|
|
@@ -15517,7 +15196,7 @@ async function listClaimKeyScenariosRuntime(options = {}) {
|
|
|
15517
15196
|
}
|
|
15518
15197
|
async function runClaimKeyScenariosRuntime(options = {}) {
|
|
15519
15198
|
const runId = buildRunId();
|
|
15520
|
-
const artifactRoot =
|
|
15199
|
+
const artifactRoot = path20.resolve(DEFAULT_ARTIFACT_ROOT, runId);
|
|
15521
15200
|
await mkdir2(artifactRoot, { recursive: true });
|
|
15522
15201
|
let scenarios;
|
|
15523
15202
|
try {
|
|
@@ -15569,11 +15248,11 @@ function filterClaimKeyScenarios(scenarios, options) {
|
|
|
15569
15248
|
}
|
|
15570
15249
|
async function runOneClaimKeyScenario(scenario, options) {
|
|
15571
15250
|
const startedAt = Date.now();
|
|
15572
|
-
const scenarioArtifactRoot =
|
|
15573
|
-
const sandboxRoot =
|
|
15251
|
+
const scenarioArtifactRoot = path20.join(options.artifactRoot, scenario.id);
|
|
15252
|
+
const sandboxRoot = path20.join(scenarioArtifactRoot, "sandbox");
|
|
15574
15253
|
const warnings = [];
|
|
15575
15254
|
await mkdir2(scenarioArtifactRoot, { recursive: true });
|
|
15576
|
-
await writeJson(
|
|
15255
|
+
await writeJson(path20.join(scenarioArtifactRoot, "scenario.json"), scenario);
|
|
15577
15256
|
let actual = {
|
|
15578
15257
|
warnings: [],
|
|
15579
15258
|
rows: [],
|
|
@@ -15686,7 +15365,7 @@ async function runIngestScenario(scenario, database, warnings, rootDir) {
|
|
|
15686
15365
|
throw new Error(`Scenario ${scenario.id} is missing extraction fixture responses.`);
|
|
15687
15366
|
}
|
|
15688
15367
|
const result = await ingestPath(
|
|
15689
|
-
|
|
15368
|
+
path20.join(rootDir, scenario.input.transcriptFile),
|
|
15690
15369
|
{
|
|
15691
15370
|
files: localTranscriptFiles,
|
|
15692
15371
|
transcript: openClawTranscriptParser,
|
|
@@ -15758,7 +15437,7 @@ async function runSurgeonScenario(scenario, database, _warnings, rootDir) {
|
|
|
15758
15437
|
{
|
|
15759
15438
|
port: createSurgeonPort(database),
|
|
15760
15439
|
config: null,
|
|
15761
|
-
model:
|
|
15440
|
+
model: getModel("openai", "gpt-5.4-mini"),
|
|
15762
15441
|
now: () => SCENARIO_NOW,
|
|
15763
15442
|
...claimExtractionResponses ? {
|
|
15764
15443
|
createClaimExtractionLlm: () => createFixtureLlm(claimExtractionResponses)
|
|
@@ -15828,20 +15507,20 @@ async function loadLatestSurgeonProposals(database, runId) {
|
|
|
15828
15507
|
}));
|
|
15829
15508
|
}
|
|
15830
15509
|
async function writeScenarioArtifacts(scenarioArtifactRoot, actual, assertionResults, diffSummary) {
|
|
15831
|
-
await writeJson(
|
|
15832
|
-
await writeJson(
|
|
15510
|
+
await writeJson(path20.join(scenarioArtifactRoot, "actual.json"), actual);
|
|
15511
|
+
await writeJson(path20.join(scenarioArtifactRoot, "diff.json"), {
|
|
15833
15512
|
assertions: assertionResults,
|
|
15834
15513
|
diffSummary
|
|
15835
15514
|
});
|
|
15836
|
-
await writeJson(
|
|
15515
|
+
await writeJson(path20.join(scenarioArtifactRoot, "warnings.json"), actual.warnings);
|
|
15837
15516
|
if (actual.storeResult) {
|
|
15838
|
-
await writeJson(
|
|
15517
|
+
await writeJson(path20.join(scenarioArtifactRoot, "store-result.json"), actual.storeResult);
|
|
15839
15518
|
}
|
|
15840
15519
|
if (actual.surgeonSummary) {
|
|
15841
|
-
await writeJson(
|
|
15520
|
+
await writeJson(path20.join(scenarioArtifactRoot, "surgeon-summary.json"), actual.surgeonSummary);
|
|
15842
15521
|
}
|
|
15843
15522
|
if (actual.proposals.length > 0) {
|
|
15844
|
-
await writeJson(
|
|
15523
|
+
await writeJson(path20.join(scenarioArtifactRoot, "proposals.json"), actual.proposals);
|
|
15845
15524
|
}
|
|
15846
15525
|
}
|
|
15847
15526
|
async function writeJson(filePath, value) {
|
|
@@ -15973,12 +15652,12 @@ import { InvalidArgumentError as InvalidArgumentError6, Option as Option5 } from
|
|
|
15973
15652
|
|
|
15974
15653
|
// src/app/surgeon/runtime.ts
|
|
15975
15654
|
import { copyFile, mkdir as mkdir3 } from "fs/promises";
|
|
15976
|
-
import
|
|
15655
|
+
import path21 from "path";
|
|
15977
15656
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
15978
|
-
import { getModel as
|
|
15657
|
+
import { getModel as getModel2 } from "@earendil-works/pi-ai";
|
|
15979
15658
|
var DEFAULT_SURGEON_PROVIDER = "openai";
|
|
15980
15659
|
var DEFAULT_SURGEON_MODEL = "gpt-5.4-mini";
|
|
15981
|
-
var
|
|
15660
|
+
var getModelWithStrings = getModel2;
|
|
15982
15661
|
async function runSurgeonRuntime(input) {
|
|
15983
15662
|
const runtime = loadRuntimeConfig(input);
|
|
15984
15663
|
const database = await createDatabase(runtime.dbPath);
|
|
@@ -15988,7 +15667,7 @@ async function runSurgeonRuntime(input) {
|
|
|
15988
15667
|
const modelSelection = resolveSurgeonModel(runtime.config, input);
|
|
15989
15668
|
const claimExtractionConfig = selection.includesClaimKeyQuality ? resolveClaimExtractionConfig(runtime.config) : { enabled: false };
|
|
15990
15669
|
const claimModelSelection = claimExtractionConfig.enabled ? resolveModel(runtime.config, "claim") : null;
|
|
15991
|
-
const model =
|
|
15670
|
+
const model = getModelWithStrings(modelSelection.provider, modelSelection.modelId);
|
|
15992
15671
|
const credentials = resolveLlmCredentials(runtime.config, modelSelection.provider, input.env ?? process.env);
|
|
15993
15672
|
const claimCredentials = claimModelSelection && claimModelSelection.provider === modelSelection.provider ? credentials : claimModelSelection ? resolveLlmCredentials(runtime.config, claimModelSelection.provider, input.env ?? process.env) : null;
|
|
15994
15673
|
let recallPorts;
|
|
@@ -16114,7 +15793,7 @@ async function reviewSurgeonProposalRuntime(input) {
|
|
|
16114
15793
|
if (proposal.reviewStatus !== "open") {
|
|
16115
15794
|
throw new Error(`Proposal ${proposal.id} was already reviewed as ${proposal.reviewStatus}.`);
|
|
16116
15795
|
}
|
|
16117
|
-
const reviewReason =
|
|
15796
|
+
const reviewReason = normalizeOptionalString12(input.reason);
|
|
16118
15797
|
if (!reviewReason) {
|
|
16119
15798
|
throw new Error("Review reason is required.");
|
|
16120
15799
|
}
|
|
@@ -16173,8 +15852,8 @@ async function reviewSurgeonProposalRuntime(input) {
|
|
|
16173
15852
|
}
|
|
16174
15853
|
}
|
|
16175
15854
|
function loadRuntimeConfig(input) {
|
|
16176
|
-
const dbPathOverride =
|
|
16177
|
-
const configPathOverride =
|
|
15855
|
+
const dbPathOverride = normalizeOptionalString12(input.dbPath) ?? normalizeOptionalString12(input.env?.AGENR_DB_PATH);
|
|
15856
|
+
const configPathOverride = normalizeOptionalString12(input.env?.AGENR_CONFIG_PATH);
|
|
16178
15857
|
const config = readConfig({
|
|
16179
15858
|
configPath: configPathOverride,
|
|
16180
15859
|
dbPath: dbPathOverride
|
|
@@ -16187,8 +15866,8 @@ function loadRuntimeConfig(input) {
|
|
|
16187
15866
|
function resolveSurgeonModel(config, input) {
|
|
16188
15867
|
const surgeonModel = config.surgeon?.model;
|
|
16189
15868
|
return {
|
|
16190
|
-
provider:
|
|
16191
|
-
modelId:
|
|
15869
|
+
provider: normalizeOptionalString12(input.provider) ?? normalizeOptionalString12(surgeonModel?.provider) ?? normalizeOptionalString12(config.provider) ?? DEFAULT_SURGEON_PROVIDER,
|
|
15870
|
+
modelId: normalizeOptionalString12(input.model) ?? normalizeOptionalString12(surgeonModel?.model) ?? normalizeOptionalString12(config.model) ?? DEFAULT_SURGEON_MODEL
|
|
16192
15871
|
};
|
|
16193
15872
|
}
|
|
16194
15873
|
function resolveRuntimeSelection(input) {
|
|
@@ -16218,7 +15897,7 @@ async function backupDatabaseFile(dbPath) {
|
|
|
16218
15897
|
}
|
|
16219
15898
|
const sourcePath = resolveFilesystemPath(dbPath);
|
|
16220
15899
|
const backupPath = `${sourcePath}.surgeon-backup-${(/* @__PURE__ */ new Date()).toISOString().replaceAll(":", "-").replaceAll(".", "-")}`;
|
|
16221
|
-
await mkdir3(
|
|
15900
|
+
await mkdir3(path21.dirname(backupPath), { recursive: true });
|
|
16222
15901
|
await copyFile(sourcePath, backupPath);
|
|
16223
15902
|
await copySidecarIfPresent(`${sourcePath}-wal`, `${backupPath}-wal`);
|
|
16224
15903
|
await copySidecarIfPresent(`${sourcePath}-shm`, `${backupPath}-shm`);
|
|
@@ -16236,18 +15915,18 @@ async function copySidecarIfPresent(sourcePath, targetPath) {
|
|
|
16236
15915
|
}
|
|
16237
15916
|
function resolveFilesystemPath(value) {
|
|
16238
15917
|
if (!value.startsWith("file:")) {
|
|
16239
|
-
return
|
|
15918
|
+
return path21.resolve(value);
|
|
16240
15919
|
}
|
|
16241
15920
|
try {
|
|
16242
15921
|
return fileURLToPath3(value);
|
|
16243
15922
|
} catch {
|
|
16244
|
-
return
|
|
15923
|
+
return path21.resolve(value.slice("file:".length));
|
|
16245
15924
|
}
|
|
16246
15925
|
}
|
|
16247
15926
|
function isMissingFileError2(error) {
|
|
16248
15927
|
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
16249
15928
|
}
|
|
16250
|
-
function
|
|
15929
|
+
function normalizeOptionalString12(value) {
|
|
16251
15930
|
const normalized = value?.trim();
|
|
16252
15931
|
return normalized && normalized.length > 0 ? normalized : void 0;
|
|
16253
15932
|
}
|
|
@@ -16330,9 +16009,9 @@ function registerSurgeonCommand(program2) {
|
|
|
16330
16009
|
try {
|
|
16331
16010
|
const backlog = await loadSurgeonBacklogRuntime({
|
|
16332
16011
|
state: options.state,
|
|
16333
|
-
issueKind:
|
|
16012
|
+
issueKind: normalizeOptionalString2(options.issueKind),
|
|
16334
16013
|
eligibleOnly: options.eligibleOnly === true,
|
|
16335
|
-
entryId:
|
|
16014
|
+
entryId: normalizeOptionalString2(options.entryId),
|
|
16336
16015
|
limit: options.limit,
|
|
16337
16016
|
offset: options.offset,
|
|
16338
16017
|
env: process.env
|
|
@@ -16341,8 +16020,8 @@ function registerSurgeonCommand(program2) {
|
|
|
16341
16020
|
renderBacklog(backlog, {
|
|
16342
16021
|
state: options.state ?? "open",
|
|
16343
16022
|
eligibleOnly: options.eligibleOnly === true,
|
|
16344
|
-
issueKind:
|
|
16345
|
-
entryId:
|
|
16023
|
+
issueKind: normalizeOptionalString2(options.issueKind),
|
|
16024
|
+
entryId: normalizeOptionalString2(options.entryId),
|
|
16346
16025
|
limit: options.limit ?? 20,
|
|
16347
16026
|
offset: options.offset ?? 0
|
|
16348
16027
|
})
|
|
@@ -16381,7 +16060,7 @@ function registerSurgeonCommand(program2) {
|
|
|
16381
16060
|
});
|
|
16382
16061
|
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
16062
|
try {
|
|
16384
|
-
const reason =
|
|
16063
|
+
const reason = normalizeOptionalString2(options.reason);
|
|
16385
16064
|
if (!reason) {
|
|
16386
16065
|
throw new InvalidArgumentError6("Review reason is required.");
|
|
16387
16066
|
}
|
|
@@ -16416,10 +16095,10 @@ function normalizeSurgeonRunCommand(options) {
|
|
|
16416
16095
|
contextLimit: options.contextLimit,
|
|
16417
16096
|
skipEvaluatedDays: options.skipEvaluatedDays,
|
|
16418
16097
|
apply: options.apply === true,
|
|
16419
|
-
model:
|
|
16420
|
-
provider:
|
|
16098
|
+
model: normalizeOptionalString2(options.model),
|
|
16099
|
+
provider: normalizeOptionalString2(options.provider),
|
|
16421
16100
|
verbose: options.verbose === true,
|
|
16422
|
-
tracePath:
|
|
16101
|
+
tracePath: normalizeOptionalString2(options.trace),
|
|
16423
16102
|
json: options.json === true
|
|
16424
16103
|
};
|
|
16425
16104
|
}
|
|
@@ -17137,17 +16816,17 @@ function formatPassContextSummary(event) {
|
|
|
17137
16816
|
// src/cli/commands/trace.ts
|
|
17138
16817
|
import { Option as Option6 } from "commander";
|
|
17139
16818
|
|
|
17140
|
-
// src/app/
|
|
17141
|
-
async function
|
|
16819
|
+
// src/app/memory/inspect.ts
|
|
16820
|
+
async function loadEntryTraceRuntime(input) {
|
|
17142
16821
|
const selector = normalizeTraceSelector(input);
|
|
17143
|
-
const configPathOverride =
|
|
16822
|
+
const configPathOverride = normalizeOptionalString13(input.env?.AGENR_CONFIG_PATH);
|
|
17144
16823
|
const config = readConfig({
|
|
17145
16824
|
configPath: configPathOverride,
|
|
17146
|
-
dbPath:
|
|
16825
|
+
dbPath: normalizeOptionalString13(input.dbPath) ?? normalizeOptionalString13(input.env?.AGENR_DB_PATH)
|
|
17147
16826
|
});
|
|
17148
|
-
const dbPath =
|
|
16827
|
+
const dbPath = normalizeOptionalString13(input.dbPath) ?? normalizeOptionalString13(input.env?.AGENR_DB_PATH) ?? resolveDbPath(config);
|
|
17149
16828
|
const database = await createDatabase(dbPath);
|
|
17150
|
-
const repository =
|
|
16829
|
+
const repository = createMemoryRepository(database);
|
|
17151
16830
|
try {
|
|
17152
16831
|
const entryId = await resolveTraceEntryId(repository, selector);
|
|
17153
16832
|
const trace = await repository.getEntryTrace(entryId);
|
|
@@ -17177,8 +16856,8 @@ async function resolveTraceEntryId(repository, selector) {
|
|
|
17177
16856
|
return entry.id;
|
|
17178
16857
|
}
|
|
17179
16858
|
function normalizeTraceSelector(selector) {
|
|
17180
|
-
const id =
|
|
17181
|
-
const subject =
|
|
16859
|
+
const id = normalizeOptionalString13(selector.id);
|
|
16860
|
+
const subject = normalizeOptionalString13(selector.subject);
|
|
17182
16861
|
const last = selector.last === true;
|
|
17183
16862
|
const count = (id ? 1 : 0) + (subject ? 1 : 0) + (last ? 1 : 0);
|
|
17184
16863
|
if (count !== 1) {
|
|
@@ -17190,7 +16869,7 @@ function normalizeTraceSelector(selector) {
|
|
|
17190
16869
|
last
|
|
17191
16870
|
};
|
|
17192
16871
|
}
|
|
17193
|
-
function
|
|
16872
|
+
function normalizeOptionalString13(value) {
|
|
17194
16873
|
const normalized = value?.trim();
|
|
17195
16874
|
return normalized && normalized.length > 0 ? normalized : void 0;
|
|
17196
16875
|
}
|
|
@@ -17199,7 +16878,7 @@ function normalizeOptionalString14(value) {
|
|
|
17199
16878
|
function registerTraceCommand(program2) {
|
|
17200
16879
|
program2.command("trace").description("Inspect one entry's provenance and claim-family lineage").addOption(new Option6("--id <id>", "Entry id to inspect")).addOption(new Option6("--subject <text>", "Subject text to resolve when the id is unknown")).option("--last", "Inspect the most recently created entry").option("--json", "Emit structured JSON output").action(async (options) => {
|
|
17201
16880
|
try {
|
|
17202
|
-
const trace = await
|
|
16881
|
+
const trace = await loadEntryTraceRuntime({
|
|
17203
16882
|
id: options.id,
|
|
17204
16883
|
subject: options.subject,
|
|
17205
16884
|
last: options.last === true,
|