@massa-ai/tools-api 1.60.1 → 1.61.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +671 -415
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -979,7 +979,7 @@ function getConfigForEnv() {
|
|
|
979
979
|
} else {
|
|
980
980
|
console.error(`[getConfigForEnv] embedding.provider "${provider}" has no env-projection branch \u2014 no embedding env vars were set`);
|
|
981
981
|
}
|
|
982
|
-
env.
|
|
982
|
+
env.MASSA_AI_LOG_LEVEL = config.logging.level;
|
|
983
983
|
env.ENABLE_METRICS = String(config.logging.enableMetrics);
|
|
984
984
|
return env;
|
|
985
985
|
}
|
|
@@ -2025,7 +2025,7 @@ var init_config = __esm(() => {
|
|
|
2025
2025
|
corsOrigins: envList("MASSA_AI_API_CORS_ORIGINS", fileConfig.security?.corsOrigins ?? [])
|
|
2026
2026
|
},
|
|
2027
2027
|
logging: {
|
|
2028
|
-
level: process.env.
|
|
2028
|
+
level: process.env.MASSA_AI_LOG_LEVEL || fileConfig.logging?.level || "info",
|
|
2029
2029
|
enableMetrics: process.env.ENABLE_METRICS === "true" || process.env.ENABLE_METRICS === undefined && !!fileConfig.logging?.enableMetrics,
|
|
2030
2030
|
file: process.env.MASSA_AI_LOG_FILE || fileConfig.logging?.file || path6.join(resolvedDataDir, "logs", "massa-ai.log"),
|
|
2031
2031
|
enableFileSink: envBool("MASSA_AI_LOG_ENABLE_FILE_SINK", fileConfig.logging?.enableFileSink ?? true),
|
|
@@ -7558,6 +7558,32 @@ var init_log_buffer = __esm(() => {
|
|
|
7558
7558
|
});
|
|
7559
7559
|
|
|
7560
7560
|
// ../../packages/shared/dist/utils/logger.js
|
|
7561
|
+
function formatAgo(ms) {
|
|
7562
|
+
const totalSeconds = Math.floor(ms / 1000);
|
|
7563
|
+
if (totalSeconds < 60)
|
|
7564
|
+
return `${totalSeconds}s`;
|
|
7565
|
+
return `${Math.floor(totalSeconds / 60)}m`;
|
|
7566
|
+
}
|
|
7567
|
+
function capErrorText(value) {
|
|
7568
|
+
if (value.length <= MAX_ERROR_TEXT_CHARS)
|
|
7569
|
+
return value;
|
|
7570
|
+
const truncatedChars = value.length - MAX_ERROR_TEXT_CHARS;
|
|
7571
|
+
return `${value.slice(0, MAX_ERROR_TEXT_CHARS)}\u2026(truncated ${truncatedChars} chars)`;
|
|
7572
|
+
}
|
|
7573
|
+
function pickErrorFields(err, includeStack) {
|
|
7574
|
+
const out = { name: err.name, message: capErrorText(err.message) };
|
|
7575
|
+
if (includeStack)
|
|
7576
|
+
out.stack = err.stack;
|
|
7577
|
+
const code = err.code;
|
|
7578
|
+
if (code !== undefined)
|
|
7579
|
+
out.code = code;
|
|
7580
|
+
const cause = err.cause;
|
|
7581
|
+
if (cause !== undefined) {
|
|
7582
|
+
out.cause = capErrorText(cause instanceof Error ? cause.message : String(cause));
|
|
7583
|
+
}
|
|
7584
|
+
return out;
|
|
7585
|
+
}
|
|
7586
|
+
|
|
7561
7587
|
class Logger {
|
|
7562
7588
|
_level;
|
|
7563
7589
|
_enableMetrics;
|
|
@@ -7566,6 +7592,7 @@ class Logger {
|
|
|
7566
7592
|
_maxFileSizeBytes;
|
|
7567
7593
|
_maxFiles;
|
|
7568
7594
|
_initialized = false;
|
|
7595
|
+
repeats = new Map;
|
|
7569
7596
|
constructor() {}
|
|
7570
7597
|
ensureInitialized() {
|
|
7571
7598
|
if (!this._initialized) {
|
|
@@ -7626,13 +7653,70 @@ class Logger {
|
|
|
7626
7653
|
shouldLog(level) {
|
|
7627
7654
|
return level >= this.level;
|
|
7628
7655
|
}
|
|
7656
|
+
serializeMetaErrors(meta) {
|
|
7657
|
+
if (!meta)
|
|
7658
|
+
return meta;
|
|
7659
|
+
let out;
|
|
7660
|
+
for (const [key, value] of Object.entries(meta)) {
|
|
7661
|
+
if (value instanceof Error) {
|
|
7662
|
+
if (!out)
|
|
7663
|
+
out = { ...meta };
|
|
7664
|
+
out[key] = pickErrorFields(value, false);
|
|
7665
|
+
}
|
|
7666
|
+
}
|
|
7667
|
+
return out ?? meta;
|
|
7668
|
+
}
|
|
7669
|
+
applyRepeatAccounting(level, message, meta) {
|
|
7670
|
+
if (level !== LogLevel.WARN && level !== LogLevel.ERROR)
|
|
7671
|
+
return meta;
|
|
7672
|
+
const label = typeof meta?.label === "string" ? meta.label : "";
|
|
7673
|
+
const key = `${level}|${message}|${label}`;
|
|
7674
|
+
const now = Date.now();
|
|
7675
|
+
const existing = this.repeats.get(key);
|
|
7676
|
+
if (!existing || now - existing.firstSeenAt > REPEAT_WINDOW_MS) {
|
|
7677
|
+
if (this.repeats.size >= MAX_REPEAT_KEYS)
|
|
7678
|
+
this.repeats.clear();
|
|
7679
|
+
this.repeats.set(key, { firstSeenAt: now, count: 1 });
|
|
7680
|
+
return meta;
|
|
7681
|
+
}
|
|
7682
|
+
existing.count += 1;
|
|
7683
|
+
return {
|
|
7684
|
+
...meta,
|
|
7685
|
+
occurrences: existing.count,
|
|
7686
|
+
firstSeenAgo: formatAgo(now - existing.firstSeenAt)
|
|
7687
|
+
};
|
|
7688
|
+
}
|
|
7689
|
+
_resetRepeatsForTesting() {
|
|
7690
|
+
this.repeats.clear();
|
|
7691
|
+
}
|
|
7692
|
+
safeStringifyMeta(meta) {
|
|
7693
|
+
const seen = new WeakSet;
|
|
7694
|
+
try {
|
|
7695
|
+
return JSON.stringify(meta, (_key, value) => {
|
|
7696
|
+
if (typeof value === "bigint")
|
|
7697
|
+
return value.toString();
|
|
7698
|
+
if (typeof value === "object" && value !== null) {
|
|
7699
|
+
if (seen.has(value))
|
|
7700
|
+
return "[Circular]";
|
|
7701
|
+
seen.add(value);
|
|
7702
|
+
}
|
|
7703
|
+
return value;
|
|
7704
|
+
});
|
|
7705
|
+
} catch (err) {
|
|
7706
|
+
return JSON.stringify({
|
|
7707
|
+
metaUnserializable: err instanceof Error ? err.message : String(err)
|
|
7708
|
+
});
|
|
7709
|
+
}
|
|
7710
|
+
}
|
|
7629
7711
|
formatMessage(level, message, meta, timestamp = new Date().toISOString()) {
|
|
7630
|
-
const metaStr = meta ? ` ${
|
|
7712
|
+
const metaStr = meta ? ` ${this.safeStringifyMeta(meta)}` : "";
|
|
7631
7713
|
return `[${timestamp}] [${level}] ${message}${metaStr}`;
|
|
7632
7714
|
}
|
|
7633
7715
|
emit(level, message, meta) {
|
|
7716
|
+
const serializedMeta = this.serializeMetaErrors(meta);
|
|
7717
|
+
const finalMeta = this.applyRepeatAccounting(level, message, serializedMeta);
|
|
7634
7718
|
const ts = new Date().toISOString();
|
|
7635
|
-
const line = this.formatMessage(LOG_LEVEL_LABELS[level], message,
|
|
7719
|
+
const line = this.formatMessage(LOG_LEVEL_LABELS[level], message, finalMeta, ts);
|
|
7636
7720
|
console.error(line);
|
|
7637
7721
|
if (this.enableFileSink) {
|
|
7638
7722
|
const filePath = this.logFilePath;
|
|
@@ -7644,7 +7728,7 @@ class Logger {
|
|
|
7644
7728
|
ts,
|
|
7645
7729
|
level: LOG_LEVEL_BUFFER_TAGS[level],
|
|
7646
7730
|
message,
|
|
7647
|
-
...
|
|
7731
|
+
...finalMeta ? { meta: finalMeta } : {}
|
|
7648
7732
|
});
|
|
7649
7733
|
}
|
|
7650
7734
|
debug(message, meta) {
|
|
@@ -7666,11 +7750,7 @@ class Logger {
|
|
|
7666
7750
|
if (this.shouldLog(LogLevel.ERROR)) {
|
|
7667
7751
|
const errorMeta = error ? {
|
|
7668
7752
|
...meta,
|
|
7669
|
-
error: {
|
|
7670
|
-
name: error.name,
|
|
7671
|
-
message: error.message,
|
|
7672
|
-
stack: error.stack
|
|
7673
|
-
}
|
|
7753
|
+
error: error instanceof Error ? pickErrorFields(error, true) : { message: String(error) }
|
|
7674
7754
|
} : meta;
|
|
7675
7755
|
this.emit(LogLevel.ERROR, message, errorMeta);
|
|
7676
7756
|
}
|
|
@@ -7701,7 +7781,7 @@ class Logger {
|
|
|
7701
7781
|
return childLogger;
|
|
7702
7782
|
}
|
|
7703
7783
|
}
|
|
7704
|
-
var LogLevel, LOG_LEVEL_LABELS, LOG_LEVEL_BUFFER_TAGS, logger;
|
|
7784
|
+
var LogLevel, LOG_LEVEL_LABELS, LOG_LEVEL_BUFFER_TAGS, REPEAT_WINDOW_MS, MAX_REPEAT_KEYS = 500, MAX_ERROR_TEXT_CHARS = 300, logger;
|
|
7705
7785
|
var init_logger = __esm(() => {
|
|
7706
7786
|
init_config();
|
|
7707
7787
|
init_log_sink();
|
|
@@ -7724,6 +7804,7 @@ var init_logger = __esm(() => {
|
|
|
7724
7804
|
[LogLevel.WARN]: "warn",
|
|
7725
7805
|
[LogLevel.ERROR]: "error"
|
|
7726
7806
|
};
|
|
7807
|
+
REPEAT_WINDOW_MS = 15 * 60 * 1000;
|
|
7727
7808
|
logger = new Logger;
|
|
7728
7809
|
});
|
|
7729
7810
|
|
|
@@ -7779,8 +7860,9 @@ var init_metrics = __esm(() => {
|
|
|
7779
7860
|
}
|
|
7780
7861
|
} catch (error) {
|
|
7781
7862
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
7782
|
-
logger.warn(
|
|
7783
|
-
|
|
7863
|
+
logger.warn("MetricsCollector: failed to fetch pricing", {
|
|
7864
|
+
modelId,
|
|
7865
|
+
error: err
|
|
7784
7866
|
});
|
|
7785
7867
|
}
|
|
7786
7868
|
const fallback = FALLBACK_PRICING[modelId];
|
|
@@ -7788,7 +7870,7 @@ var init_metrics = __esm(() => {
|
|
|
7788
7870
|
logger.debug(`Using fallback pricing for ${modelId}`);
|
|
7789
7871
|
return fallback;
|
|
7790
7872
|
}
|
|
7791
|
-
logger.warn(
|
|
7873
|
+
logger.warn("MetricsCollector: unknown model, using gpt-4 pricing as default", { modelId });
|
|
7792
7874
|
return FALLBACK_PRICING["gpt-4"];
|
|
7793
7875
|
}
|
|
7794
7876
|
static calculateCost(inputTokens, outputTokens, model) {
|
|
@@ -7967,7 +8049,9 @@ class SmartRateLimiter {
|
|
|
7967
8049
|
const hasRequestCapacity = this.requestLimiter.tryConsume(1);
|
|
7968
8050
|
const hasTokenCapacity = this.tokenLimiter.tryConsume(estimatedTokens);
|
|
7969
8051
|
if (!hasRequestCapacity) {
|
|
7970
|
-
logger.warn("Request rate limit exceeded"
|
|
8052
|
+
logger.warn("Request rate limit exceeded", {
|
|
8053
|
+
availableTokens: this.requestLimiter.getAvailableTokens()
|
|
8054
|
+
});
|
|
7971
8055
|
return false;
|
|
7972
8056
|
}
|
|
7973
8057
|
if (!hasTokenCapacity) {
|
|
@@ -8510,6 +8594,7 @@ function readRoles(liveRoot, activeProfile) {
|
|
|
8510
8594
|
}
|
|
8511
8595
|
function runtimeDriftReport(opts = {}) {
|
|
8512
8596
|
const targetHome = opts.targetHome ?? os6.homedir();
|
|
8597
|
+
const host = opts.host ?? "claude";
|
|
8513
8598
|
const stateFilePath = opts.stateFilePath ?? path12.join(targetHome, ".config", "massa-ai", "install-state.json");
|
|
8514
8599
|
let state = opts.state ?? null;
|
|
8515
8600
|
if (state === null) {
|
|
@@ -8519,9 +8604,24 @@ function runtimeDriftReport(opts = {}) {
|
|
|
8519
8604
|
state = null;
|
|
8520
8605
|
}
|
|
8521
8606
|
}
|
|
8522
|
-
const platform = state?.platforms?.
|
|
8607
|
+
const platform = state?.platforms?.[host];
|
|
8523
8608
|
const stateVersion = typeof platform?.plugin?.version === "string" ? platform.plugin.version : null;
|
|
8524
8609
|
const activeProfile = platform?.modelProfile?.profile ?? null;
|
|
8610
|
+
if (host !== "claude") {
|
|
8611
|
+
return {
|
|
8612
|
+
host,
|
|
8613
|
+
route: "unresolved",
|
|
8614
|
+
liveRoot: null,
|
|
8615
|
+
sourceVersion: null,
|
|
8616
|
+
stateVersion,
|
|
8617
|
+
pinnedVersion: null,
|
|
8618
|
+
activeProfile,
|
|
8619
|
+
roles: [],
|
|
8620
|
+
envOverride: detectEnvOverride(opts.env ?? process.env),
|
|
8621
|
+
versionDrift: false,
|
|
8622
|
+
profileMaterialized: false
|
|
8623
|
+
};
|
|
8624
|
+
}
|
|
8525
8625
|
const install = resolveClaudeMarketplaceInstall({ targetHome, pluginKey: opts.pluginKey });
|
|
8526
8626
|
const liveRoot = install?.root ?? null;
|
|
8527
8627
|
const sourceVersion = liveRoot === null ? null : readPluginVersion(liveRoot);
|
|
@@ -8593,7 +8693,7 @@ function listProfiles(opts = {}) {
|
|
|
8593
8693
|
installed: false,
|
|
8594
8694
|
skipped: false,
|
|
8595
8695
|
skipReason: null,
|
|
8596
|
-
activeProfile: platform2.modelProfile?.profile ??
|
|
8696
|
+
activeProfile: platform2.modelProfile?.profile ?? "balanced",
|
|
8597
8697
|
bundleVersion: platform2.plugin?.version ?? null,
|
|
8598
8698
|
availableProfiles: [],
|
|
8599
8699
|
...claudeDriftFields(host)
|
|
@@ -8620,7 +8720,7 @@ function listProfiles(opts = {}) {
|
|
|
8620
8720
|
installed,
|
|
8621
8721
|
skipped: false,
|
|
8622
8722
|
skipReason: null,
|
|
8623
|
-
activeProfile: platform?.modelProfile?.profile ??
|
|
8723
|
+
activeProfile: platform?.modelProfile?.profile ?? "balanced",
|
|
8624
8724
|
bundleVersion: platform?.plugin?.version ?? null,
|
|
8625
8725
|
availableProfiles,
|
|
8626
8726
|
...claudeDriftFields(host)
|
|
@@ -9097,6 +9197,7 @@ var init_dist = __esm(() => {
|
|
|
9097
9197
|
init_engine();
|
|
9098
9198
|
init_variant_sync();
|
|
9099
9199
|
init_repo_root();
|
|
9200
|
+
init_doctor();
|
|
9100
9201
|
init_bootstrap();
|
|
9101
9202
|
init_types();
|
|
9102
9203
|
init_interfaces();
|
|
@@ -15310,7 +15411,7 @@ class ProjectIdentityAliasResolver {
|
|
|
15310
15411
|
this.cache.set(projectId, { canonical, expiresAt: this.now() + this.ttlMs });
|
|
15311
15412
|
return canonical;
|
|
15312
15413
|
} catch (error) {
|
|
15313
|
-
logger.warn("[project-identity] alias resolution failed; using original id", safeErrorSummary(error));
|
|
15414
|
+
logger.warn("[project-identity] alias resolution failed; using original id", { projectId, ...safeErrorSummary(error) });
|
|
15314
15415
|
return projectId;
|
|
15315
15416
|
}
|
|
15316
15417
|
}
|
|
@@ -52855,7 +52956,7 @@ async function _checkJsonSchemaSupport() {
|
|
|
52855
52956
|
} catch (e) {
|
|
52856
52957
|
_jsonSchemaSupported = false;
|
|
52857
52958
|
logger.warn("json_schema: version check error \u2014 falling back to json_object", {
|
|
52858
|
-
error: e
|
|
52959
|
+
error: e
|
|
52859
52960
|
});
|
|
52860
52961
|
return false;
|
|
52861
52962
|
}
|
|
@@ -52903,7 +53004,7 @@ function hostPort(url2) {
|
|
|
52903
53004
|
return null;
|
|
52904
53005
|
}
|
|
52905
53006
|
}
|
|
52906
|
-
function
|
|
53007
|
+
function resolveMatchedProviderSpec(baseUrl) {
|
|
52907
53008
|
const target = hostPort(baseUrl);
|
|
52908
53009
|
if (target) {
|
|
52909
53010
|
const match2 = inferenceProviderList().find((spec) => hostPort(spec.defaultLlmBaseUrl) === target);
|
|
@@ -52921,7 +53022,13 @@ function resolveInferenceSpec(baseUrl) {
|
|
|
52921
53022
|
if (embeddingProvider && LOCAL_INFERENCE_IDS.includes(embeddingProvider)) {
|
|
52922
53023
|
return INFERENCE_PROVIDERS[embeddingProvider];
|
|
52923
53024
|
}
|
|
52924
|
-
return
|
|
53025
|
+
return;
|
|
53026
|
+
}
|
|
53027
|
+
function resolveInferenceSpec(baseUrl) {
|
|
53028
|
+
return resolveMatchedProviderSpec(baseUrl) ?? INFERENCE_PROVIDERS.ollama;
|
|
53029
|
+
}
|
|
53030
|
+
function resolveProviderIdForLogging(baseUrl) {
|
|
53031
|
+
return resolveMatchedProviderSpec(baseUrl)?.id ?? "unknown";
|
|
52925
53032
|
}
|
|
52926
53033
|
function _wrapFetchDisableThink(baseFetch) {
|
|
52927
53034
|
const wrapped = async (input, init) => {
|
|
@@ -53064,12 +53171,40 @@ function _isAbortOrTimeoutError(err) {
|
|
|
53064
53171
|
}
|
|
53065
53172
|
return false;
|
|
53066
53173
|
}
|
|
53067
|
-
|
|
53174
|
+
function summarizeZodIssues(error51, maxIssues = 5) {
|
|
53175
|
+
return error51.issues.slice(0, maxIssues).map((issue2) => `${issue2.path.join(".") || "(root)"}: ${issue2.message}`).join("; ");
|
|
53176
|
+
}
|
|
53177
|
+
function recordLlmFailure(label, role, model, baseUrl, timeoutMs, elapsedMs, err) {
|
|
53178
|
+
const consecutiveFailures = (llmFailureStreaks.get(label) ?? 0) + 1;
|
|
53179
|
+
llmFailureStreaks.set(label, consecutiveFailures);
|
|
53180
|
+
logger.warn("LLM call failed \u2014 using non-LLM fallback", {
|
|
53181
|
+
label,
|
|
53182
|
+
role,
|
|
53183
|
+
model,
|
|
53184
|
+
provider: resolveProviderIdForLogging(baseUrl),
|
|
53185
|
+
timeoutMs,
|
|
53186
|
+
elapsedMs,
|
|
53187
|
+
timedOut: _isAbortOrTimeoutError(err),
|
|
53188
|
+
error: err,
|
|
53189
|
+
consecutiveFailures
|
|
53190
|
+
});
|
|
53191
|
+
return consecutiveFailures;
|
|
53192
|
+
}
|
|
53193
|
+
function recordLlmSuccess(label, model) {
|
|
53194
|
+
const priorFailures = llmFailureStreaks.get(label) ?? 0;
|
|
53195
|
+
if (priorFailures > 0) {
|
|
53196
|
+
logger.info("LLM call recovered", { label, model, afterFailures: priorFailures });
|
|
53197
|
+
}
|
|
53198
|
+
llmFailureStreaks.set(label, 0);
|
|
53199
|
+
}
|
|
53200
|
+
async function llmComplete(prompt, opts) {
|
|
53068
53201
|
if (!isLlmEnabled()) {
|
|
53069
53202
|
return { ok: false, error: "llm disabled" };
|
|
53070
53203
|
}
|
|
53071
53204
|
const llm = getLlmConfig({ modelRole: opts.modelRole });
|
|
53205
|
+
const role = opts.modelRole ?? "instruct";
|
|
53072
53206
|
const timeoutMs = opts.timeoutMs ?? llm.timeoutMs;
|
|
53207
|
+
const startedAt = Date.now();
|
|
53073
53208
|
try {
|
|
53074
53209
|
const result = await generateText({
|
|
53075
53210
|
model: buildProvider(llm),
|
|
@@ -53080,14 +53215,17 @@ async function llmComplete(prompt, opts = {}) {
|
|
|
53080
53215
|
abortSignal: timeoutSignal(timeoutMs)
|
|
53081
53216
|
});
|
|
53082
53217
|
const text2 = result.text ?? "";
|
|
53083
|
-
if (text2.length > 0)
|
|
53218
|
+
if (text2.length > 0) {
|
|
53219
|
+
recordLlmSuccess(opts.label, llm.model);
|
|
53084
53220
|
return { ok: true, value: text2 };
|
|
53221
|
+
}
|
|
53085
53222
|
if (llm.disableThink) {
|
|
53086
53223
|
const reasoning = _reasoningToText(result);
|
|
53087
53224
|
if (reasoning.length > 0) {
|
|
53088
53225
|
logger.warn("llmComplete: empty content \u2014 recovered from reasoning channel", {
|
|
53089
53226
|
reasoningLen: reasoning.length
|
|
53090
53227
|
});
|
|
53228
|
+
recordLlmSuccess(opts.label, llm.model);
|
|
53091
53229
|
return { ok: true, value: reasoning };
|
|
53092
53230
|
}
|
|
53093
53231
|
logger.warn("llm reasoning-recovery empty", {
|
|
@@ -53095,21 +53233,22 @@ async function llmComplete(prompt, opts = {}) {
|
|
|
53095
53233
|
finishReason: result?.finishReason ?? null
|
|
53096
53234
|
});
|
|
53097
53235
|
}
|
|
53098
|
-
|
|
53099
|
-
|
|
53236
|
+
const emptyErr = new Error("empty content (thinking model)");
|
|
53237
|
+
recordLlmFailure(opts.label, role, llm.model, llm.baseUrl, timeoutMs, Date.now() - startedAt, emptyErr);
|
|
53238
|
+
return { ok: false, error: emptyErr.message };
|
|
53100
53239
|
} catch (e) {
|
|
53101
|
-
|
|
53102
|
-
error: e.message
|
|
53103
|
-
});
|
|
53240
|
+
recordLlmFailure(opts.label, role, llm.model, llm.baseUrl, timeoutMs, Date.now() - startedAt, e);
|
|
53104
53241
|
return { ok: false, error: e.message };
|
|
53105
53242
|
}
|
|
53106
53243
|
}
|
|
53107
|
-
async function llmObject(prompt, schema, opts
|
|
53244
|
+
async function llmObject(prompt, schema, opts) {
|
|
53108
53245
|
if (!isLlmEnabled()) {
|
|
53109
53246
|
return { ok: false, error: "llm disabled" };
|
|
53110
53247
|
}
|
|
53111
53248
|
const llm = getLlmConfig({ modelRole: opts.modelRole });
|
|
53249
|
+
const role = opts.modelRole ?? "instruct";
|
|
53112
53250
|
const timeoutMs = opts.timeoutMs ?? llm.timeoutMs;
|
|
53251
|
+
const startedAt = Date.now();
|
|
53113
53252
|
let result = null;
|
|
53114
53253
|
try {
|
|
53115
53254
|
const useJsonSchema = llm.disableThink && await _checkJsonSchemaSupport();
|
|
@@ -53124,7 +53263,8 @@ async function llmObject(prompt, schema, opts = {}) {
|
|
|
53124
53263
|
maxOutputTokens: llm.maxOutputTokens,
|
|
53125
53264
|
abortSignal: timeoutSignal(timeoutMs)
|
|
53126
53265
|
});
|
|
53127
|
-
logger.
|
|
53266
|
+
logger.debug("json_schema: constrained decoding used", { label: opts.label, model: llm.model });
|
|
53267
|
+
recordLlmSuccess(opts.label, llm.model);
|
|
53128
53268
|
return { ok: true, value: result.object };
|
|
53129
53269
|
}
|
|
53130
53270
|
result = await generateObject({
|
|
@@ -53138,7 +53278,8 @@ async function llmObject(prompt, schema, opts = {}) {
|
|
|
53138
53278
|
});
|
|
53139
53279
|
const validated = schema.safeParse(result.object);
|
|
53140
53280
|
if (validated.success) {
|
|
53141
|
-
logger.
|
|
53281
|
+
logger.debug("json_schema: fallback to json_object \u2014 validated", { label: opts.label, model: llm.model });
|
|
53282
|
+
recordLlmSuccess(opts.label, llm.model);
|
|
53142
53283
|
return { ok: true, value: validated.data };
|
|
53143
53284
|
}
|
|
53144
53285
|
if (llm.disableThink) {
|
|
@@ -53151,15 +53292,17 @@ async function llmObject(prompt, schema, opts = {}) {
|
|
|
53151
53292
|
logger.warn("llmObject: recovered object from reasoning channel (fallback path)", {
|
|
53152
53293
|
reasoningLen: reasoning.length
|
|
53153
53294
|
});
|
|
53295
|
+
recordLlmSuccess(opts.label, llm.model);
|
|
53154
53296
|
return { ok: true, value: recovered.data };
|
|
53155
53297
|
}
|
|
53156
53298
|
}
|
|
53157
53299
|
}
|
|
53158
53300
|
}
|
|
53159
|
-
|
|
53160
|
-
|
|
53301
|
+
const validationErr = new Error("schema validation failed (fallback path)", {
|
|
53302
|
+
cause: summarizeZodIssues(validated.error)
|
|
53161
53303
|
});
|
|
53162
|
-
|
|
53304
|
+
recordLlmFailure(opts.label, role, llm.model, llm.baseUrl, timeoutMs, Date.now() - startedAt, validationErr);
|
|
53305
|
+
return { ok: false, error: validationErr.message };
|
|
53163
53306
|
} catch (e) {
|
|
53164
53307
|
if (llm.disableThink && !_isAbortOrTimeoutError(e)) {
|
|
53165
53308
|
const reasoning = _reasoningToText(result).length > 0 ? _reasoningToText(result) : _reasoningToText(e);
|
|
@@ -53171,6 +53314,7 @@ async function llmObject(prompt, schema, opts = {}) {
|
|
|
53171
53314
|
logger.warn("llmObject: recovered object from reasoning channel", {
|
|
53172
53315
|
reasoningLen: reasoning.length
|
|
53173
53316
|
});
|
|
53317
|
+
recordLlmSuccess(opts.label, llm.model);
|
|
53174
53318
|
return { ok: true, value: validated.data };
|
|
53175
53319
|
}
|
|
53176
53320
|
}
|
|
@@ -53180,19 +53324,18 @@ async function llmObject(prompt, schema, opts = {}) {
|
|
|
53180
53324
|
finishReason: e?.finishReason ?? null
|
|
53181
53325
|
});
|
|
53182
53326
|
}
|
|
53183
|
-
|
|
53184
|
-
error: e.message
|
|
53185
|
-
});
|
|
53327
|
+
recordLlmFailure(opts.label, role, llm.model, llm.baseUrl, timeoutMs, Date.now() - startedAt, e);
|
|
53186
53328
|
return { ok: false, error: e.message };
|
|
53187
53329
|
}
|
|
53188
53330
|
}
|
|
53189
|
-
var _jsonSchemaSupported = null, testEnabledOverride = null, testBaseUrlOverride = null, llm;
|
|
53331
|
+
var _jsonSchemaSupported = null, testEnabledOverride = null, testBaseUrlOverride = null, llmFailureStreaks, llm;
|
|
53190
53332
|
var init_llm_client = __esm(() => {
|
|
53191
53333
|
init_dist6();
|
|
53192
53334
|
init_dist7();
|
|
53193
53335
|
init_dist();
|
|
53194
53336
|
init_config();
|
|
53195
53337
|
init_inference_providers();
|
|
53338
|
+
llmFailureStreaks = new Map;
|
|
53196
53339
|
llm = {
|
|
53197
53340
|
complete: llmComplete,
|
|
53198
53341
|
object: llmObject,
|
|
@@ -62205,7 +62348,7 @@ class MetricsCollector2 {
|
|
|
62205
62348
|
try {
|
|
62206
62349
|
writeFileSync(this.metricsPath, JSON.stringify(this.currentMetrics, null, 2));
|
|
62207
62350
|
} catch (error51) {
|
|
62208
|
-
logger.error("
|
|
62351
|
+
logger.error("Metrics: failed to save", error51, { path: this.metricsPath });
|
|
62209
62352
|
}
|
|
62210
62353
|
}
|
|
62211
62354
|
reset() {
|
|
@@ -62380,7 +62523,8 @@ class EmbeddingRateLimiter {
|
|
|
62380
62523
|
}
|
|
62381
62524
|
}
|
|
62382
62525
|
if (this.config.requestsPerDay && this.dailyRequestsWindow.length >= this.config.requestsPerDay) {
|
|
62383
|
-
logger.warn(
|
|
62526
|
+
logger.warn("EmbeddingRateLimiter: RPD limit reached, waiting 60s", {
|
|
62527
|
+
providerId: this.providerId,
|
|
62384
62528
|
rpd: this.config.requestsPerDay,
|
|
62385
62529
|
current: this.dailyRequestsWindow.length
|
|
62386
62530
|
});
|
|
@@ -95683,16 +95827,16 @@ class LocalTransformersEmbeddingProvider {
|
|
|
95683
95827
|
const out = await extractor("test", { pooling: "mean", normalize: true });
|
|
95684
95828
|
const vec = Array.from(out.data);
|
|
95685
95829
|
if (!Array.isArray(vec) || vec.length !== this.dimensions) {
|
|
95686
|
-
logger.error(
|
|
95830
|
+
logger.error("LocalTransformersProvider: invalid embedding dimensions", undefined, { providerId: this.id, expected: this.dimensions, got: vec.length });
|
|
95687
95831
|
return false;
|
|
95688
95832
|
}
|
|
95689
95833
|
if (vec.some((v) => typeof v !== "number" || isNaN(v))) {
|
|
95690
|
-
logger.error(
|
|
95834
|
+
logger.error("LocalTransformersProvider: invalid embedding values (not numbers)", undefined, { providerId: this.id });
|
|
95691
95835
|
return false;
|
|
95692
95836
|
}
|
|
95693
95837
|
return true;
|
|
95694
95838
|
} catch (error51) {
|
|
95695
|
-
logger.error(
|
|
95839
|
+
logger.error("LocalTransformersProvider: provider unavailable", error51, { providerId: this.id });
|
|
95696
95840
|
return false;
|
|
95697
95841
|
}
|
|
95698
95842
|
}
|
|
@@ -95732,7 +95876,13 @@ async function withRetry(fn, config3, context2) {
|
|
|
95732
95876
|
lastError2 = error51;
|
|
95733
95877
|
if (attempt < config3.maxRetries) {
|
|
95734
95878
|
const delay2 = getRetryDelay(attempt, config3);
|
|
95735
|
-
logger.warn(
|
|
95879
|
+
logger.warn("EmbeddingProvider: operation failed, retrying", {
|
|
95880
|
+
context: context2,
|
|
95881
|
+
attempt: attempt + 1,
|
|
95882
|
+
maxAttempts: config3.maxRetries + 1,
|
|
95883
|
+
delayMs: delay2,
|
|
95884
|
+
error: lastError2
|
|
95885
|
+
});
|
|
95736
95886
|
await sleep(delay2);
|
|
95737
95887
|
}
|
|
95738
95888
|
}
|
|
@@ -96048,7 +96198,7 @@ var init_provider = __esm(() => {
|
|
|
96048
96198
|
return output;
|
|
96049
96199
|
}, this.retryConfig, `[${this.id}] embedBatchDirect (${texts.length} texts)`), this.timeout, `[${this.id}] embedBatchDirect`);
|
|
96050
96200
|
} catch (error51) {
|
|
96051
|
-
logger.warn(
|
|
96201
|
+
logger.warn("EmbeddingProvider: Ollama batch endpoint unavailable, falling back to sequential embeds", { providerId: this.id, textCount: texts.length, error: error51 });
|
|
96052
96202
|
const embeddings = [];
|
|
96053
96203
|
let consecutiveFailures = 0;
|
|
96054
96204
|
for (const text2 of texts) {
|
|
@@ -96087,11 +96237,11 @@ var init_provider = __esm(() => {
|
|
|
96087
96237
|
});
|
|
96088
96238
|
clearTimeout(timeoutId);
|
|
96089
96239
|
if (!response.ok) {
|
|
96090
|
-
logger.error(
|
|
96240
|
+
logger.error("EmbeddingProvider: Ollama API returned non-OK status", undefined, { providerId: this.id, status: response.status });
|
|
96091
96241
|
return false;
|
|
96092
96242
|
}
|
|
96093
96243
|
} catch {
|
|
96094
|
-
logger.error(
|
|
96244
|
+
logger.error("EmbeddingProvider: Ollama service unreachable", undefined, { providerId: this.id, baseURL: this.baseURL, timeoutMs: 2000 });
|
|
96095
96245
|
return false;
|
|
96096
96246
|
}
|
|
96097
96247
|
}
|
|
@@ -96101,16 +96251,16 @@ var init_provider = __esm(() => {
|
|
|
96101
96251
|
if (Array.isArray(embedding)) {
|
|
96102
96252
|
this.lastDimensionMismatch = new DimensionMismatchError(this.id, this.dimensions, embedding.length);
|
|
96103
96253
|
}
|
|
96104
|
-
logger.error(
|
|
96254
|
+
logger.error("EmbeddingProvider: invalid embedding dimensions", undefined, { providerId: this.id, expected: this.dimensions, got: embedding.length });
|
|
96105
96255
|
return false;
|
|
96106
96256
|
}
|
|
96107
96257
|
if (!embedding.every((v) => typeof v === "number" && !isNaN(v))) {
|
|
96108
|
-
logger.error(
|
|
96258
|
+
logger.error("EmbeddingProvider: invalid embedding values (not numbers)", undefined, { providerId: this.id });
|
|
96109
96259
|
return false;
|
|
96110
96260
|
}
|
|
96111
96261
|
return true;
|
|
96112
96262
|
} catch (error51) {
|
|
96113
|
-
logger.error(
|
|
96263
|
+
logger.error("EmbeddingProvider: provider unavailable", error51, { providerId: this.id });
|
|
96114
96264
|
return false;
|
|
96115
96265
|
}
|
|
96116
96266
|
}
|
|
@@ -106967,7 +107117,7 @@ function getPrismaClient2() {
|
|
|
106967
107117
|
const pg = _adapters.loadPg();
|
|
106968
107118
|
const { PrismaPg } = _adapters.loadPrismaPg();
|
|
106969
107119
|
const pool = new pg.Pool({ connectionString: databaseUrl, max: 10, idleTimeoutMillis: 30000, connectionTimeoutMillis: 5000 });
|
|
106970
|
-
pool.on("error", (error51) => logger.error("
|
|
107120
|
+
pool.on("error", (error51) => logger.error("prisma-client: unexpected PG pool error", error51, { poolMax: 10 }));
|
|
106971
107121
|
prismaPool = pool;
|
|
106972
107122
|
prismaInstance = new import_prisma.PrismaClient({ adapter: new PrismaPg(pool) });
|
|
106973
107123
|
logger.info("Prisma Client initialized with PostgreSQL");
|
|
@@ -107276,7 +107426,10 @@ var init_config2 = __esm(() => {
|
|
|
107276
107426
|
"local"
|
|
107277
107427
|
]);
|
|
107278
107428
|
if (!SELECTABLE_PROVIDERS.has(selectedProvider)) {
|
|
107279
|
-
logger.warn(
|
|
107429
|
+
logger.warn("EmbeddingConfig: selected provider has no runtime entry, falling back to priority order", {
|
|
107430
|
+
selectedProvider,
|
|
107431
|
+
source: process.env.EMBEDDING_PROVIDER ? "EMBEDDING_PROVIDER env" : "config.json embedding.provider"
|
|
107432
|
+
});
|
|
107280
107433
|
}
|
|
107281
107434
|
embeddingProviders = {
|
|
107282
107435
|
google: (() => {
|
|
@@ -107316,7 +107469,12 @@ var init_config2 = __esm(() => {
|
|
|
107316
107469
|
const envDimensions = Number.isInteger(rawEnvDimensions) && rawEnvDimensions > 0 ? rawEnvDimensions : undefined;
|
|
107317
107470
|
const resolvedDimensions = resolveEmbeddingDimensions(model, file3?.dimensions, envDimensions);
|
|
107318
107471
|
if (resolvedDimensions.correctedFrom !== undefined) {
|
|
107319
|
-
logger.warn(
|
|
107472
|
+
logger.warn("EmbeddingConfig: ollama config.json dimensions mismatch corrected", {
|
|
107473
|
+
provider: "ollama",
|
|
107474
|
+
model,
|
|
107475
|
+
configuredDimensions: resolvedDimensions.correctedFrom,
|
|
107476
|
+
correctedDimensions: resolvedDimensions.dimensions
|
|
107477
|
+
});
|
|
107320
107478
|
}
|
|
107321
107479
|
return {
|
|
107322
107480
|
provider: "ollama",
|
|
@@ -107468,8 +107626,8 @@ class EmbeddingService {
|
|
|
107468
107626
|
dimensions: this.provider.dimensions
|
|
107469
107627
|
});
|
|
107470
107628
|
} catch (error51) {
|
|
107471
|
-
logger.error("Failed to initialize embedding service", error51);
|
|
107472
|
-
logger.warn("Embedding service will use fallback mode");
|
|
107629
|
+
logger.error("Failed to initialize embedding service", error51, { stage: "initialize" });
|
|
107630
|
+
logger.warn("Embedding service will use fallback mode", { stage: "initialize" });
|
|
107473
107631
|
}
|
|
107474
107632
|
}
|
|
107475
107633
|
async ensureInitialized() {
|
|
@@ -107551,7 +107709,7 @@ async function tryCreateProvider(config3, providerId, skipHealthCheck) {
|
|
|
107551
107709
|
return { provider };
|
|
107552
107710
|
}
|
|
107553
107711
|
function refuseOnDimensionMismatch(providerId, mismatch) {
|
|
107554
|
-
logger.error(
|
|
107712
|
+
logger.error("EmbeddingProvider: configured provider failed with a dimension mismatch, refusing to fall through", mismatch, { providerId, configuredDimensions: mismatch.expected, modelDimensions: mismatch.got });
|
|
107555
107713
|
throw mismatch;
|
|
107556
107714
|
}
|
|
107557
107715
|
async function createEmbeddingProvider(options = {}) {
|
|
@@ -107650,6 +107808,7 @@ Write the hypothetical implementation paragraph.`;
|
|
|
107650
107808
|
}
|
|
107651
107809
|
async function rewriteQuery(query, surface, opts = {}) {
|
|
107652
107810
|
const res = await surface.object(rewritePrompt(query), QueryRewriteSchema, {
|
|
107811
|
+
label: "query-rewrite",
|
|
107653
107812
|
system: REWRITE_SYSTEM,
|
|
107654
107813
|
timeoutMs: opts.timeoutMs
|
|
107655
107814
|
});
|
|
@@ -107662,6 +107821,7 @@ async function rewriteQuery(query, surface, opts = {}) {
|
|
|
107662
107821
|
}
|
|
107663
107822
|
async function hyde(query, surface, embedFn, opts = {}) {
|
|
107664
107823
|
const text2 = await surface.complete(hydePrompt(query), {
|
|
107824
|
+
label: "hyde",
|
|
107665
107825
|
system: HYDE_SYSTEM,
|
|
107666
107826
|
timeoutMs: opts.timeoutMs
|
|
107667
107827
|
});
|
|
@@ -107675,7 +107835,7 @@ async function hyde(query, surface, embedFn, opts = {}) {
|
|
|
107675
107835
|
return vec;
|
|
107676
107836
|
} catch (e) {
|
|
107677
107837
|
logger.warn("hyde embed failed \u2014 skipping HyDE stream", {
|
|
107678
|
-
error: e
|
|
107838
|
+
error: e
|
|
107679
107839
|
});
|
|
107680
107840
|
return null;
|
|
107681
107841
|
}
|
|
@@ -109403,7 +109563,7 @@ class KeywordSearchPg {
|
|
|
109403
109563
|
`);
|
|
109404
109564
|
this.trigramAvailable = true;
|
|
109405
109565
|
} catch (error51) {
|
|
109406
|
-
logger.warn("pg_trgm unavailable \u2014 trigram RRF stream disabled on PG", {
|
|
109566
|
+
logger.warn("pg_trgm unavailable \u2014 trigram RRF stream disabled on PG", { error: error51 });
|
|
109407
109567
|
this.trigramAvailable = false;
|
|
109408
109568
|
}
|
|
109409
109569
|
logger.info("PostgreSQL keyword search initialized", {
|
|
@@ -109942,7 +110102,8 @@ var init_postgres_vector_store = __esm(() => {
|
|
|
109942
110102
|
this.schemaDimensions = providerDimensions;
|
|
109943
110103
|
const { rows } = await client.query(`SELECT tablename FROM pg_tables WHERE tablename = $1`, [this.tableName]);
|
|
109944
110104
|
if (rows.length === 0) {
|
|
109945
|
-
logger.warn(
|
|
110105
|
+
logger.warn("PostgresVectorStore: table not found, creating fallback table", {
|
|
110106
|
+
tableName: this.tableName,
|
|
109946
110107
|
note: 'Run "prisma migrate deploy" to create tables via migrations'
|
|
109947
110108
|
});
|
|
109948
110109
|
await this.createFallbackTable(client, providerDimensions);
|
|
@@ -109979,10 +110140,12 @@ var init_postgres_vector_store = __esm(() => {
|
|
|
109979
110140
|
if (projects.length === 0)
|
|
109980
110141
|
continue;
|
|
109981
110142
|
const otherDim = tablename.match(/_([0-9]+)d$/)?.[1];
|
|
109982
|
-
logger.warn(
|
|
110143
|
+
logger.warn("PostgresVectorStore: orphaned chunks detected, embedding model likely changed, reindex required", {
|
|
109983
110144
|
currentTable: this.tableName,
|
|
109984
110145
|
currentCount,
|
|
110146
|
+
currentDim,
|
|
109985
110147
|
orphanedTable: tablename,
|
|
110148
|
+
orphanedDim: otherDim,
|
|
109986
110149
|
affectedProjects: projects.map((p) => ({ projectId: p.project_id, chunks: p.n }))
|
|
109987
110150
|
});
|
|
109988
110151
|
}
|
|
@@ -110126,7 +110289,7 @@ var init_postgres_vector_store = __esm(() => {
|
|
|
110126
110289
|
logger.warn("[postgres] Sub-batch embedding failed, falling back per-document", {
|
|
110127
110290
|
subBatchIndex: Math.floor(i / EMBED_SUB_BATCH_SIZE),
|
|
110128
110291
|
count: subBatch.length,
|
|
110129
|
-
error: error51
|
|
110292
|
+
error: error51
|
|
110130
110293
|
});
|
|
110131
110294
|
}
|
|
110132
110295
|
if (embeddings) {
|
|
@@ -110138,7 +110301,7 @@ var init_postgres_vector_store = __esm(() => {
|
|
|
110138
110301
|
logger.warn("[postgres] Sub-batch insert failed, falling back per-document", {
|
|
110139
110302
|
subBatchIndex: Math.floor(i / EMBED_SUB_BATCH_SIZE),
|
|
110140
110303
|
count: subBatch.length,
|
|
110141
|
-
error: error51
|
|
110304
|
+
error: error51
|
|
110142
110305
|
});
|
|
110143
110306
|
}
|
|
110144
110307
|
}
|
|
@@ -110151,7 +110314,7 @@ var init_postgres_vector_store = __esm(() => {
|
|
|
110151
110314
|
totalFailed++;
|
|
110152
110315
|
logger.warn("[postgres] Skipping document due to embedding/insert error", {
|
|
110153
110316
|
id: doc2.id,
|
|
110154
|
-
error: singleError
|
|
110317
|
+
error: singleError
|
|
110155
110318
|
});
|
|
110156
110319
|
}
|
|
110157
110320
|
}
|
|
@@ -110817,7 +110980,9 @@ class SearchAnalyticsPg {
|
|
|
110817
110980
|
}
|
|
110818
110981
|
trackSearch(event) {
|
|
110819
110982
|
this.trackSearchAsync(event).catch((err) => {
|
|
110820
|
-
logger.error("Failed to track search event", err
|
|
110983
|
+
logger.error("Failed to track search event", err, {
|
|
110984
|
+
projectId: event.projectId
|
|
110985
|
+
});
|
|
110821
110986
|
});
|
|
110822
110987
|
}
|
|
110823
110988
|
async trackSearchAsync(event) {
|
|
@@ -110842,7 +111007,9 @@ class SearchAnalyticsPg {
|
|
|
110842
111007
|
event.score || null
|
|
110843
111008
|
]);
|
|
110844
111009
|
} catch (error51) {
|
|
110845
|
-
logger.error("Failed to track search event in PostgreSQL", error51
|
|
111010
|
+
logger.error("Failed to track search event in PostgreSQL", error51, {
|
|
111011
|
+
projectId: event.projectId
|
|
111012
|
+
});
|
|
110846
111013
|
}
|
|
110847
111014
|
}
|
|
110848
111015
|
async recordQuery(query, projectId, resultsCount = 0, duration3 = 0, cacheHit = false) {
|
|
@@ -113443,7 +113610,11 @@ class GraphStorePg {
|
|
|
113443
113610
|
`;
|
|
113444
113611
|
return rows[0] ? rowToEdge(rows[0]) : null;
|
|
113445
113612
|
} catch (error51) {
|
|
113446
|
-
logger.error("Failed to create edge", error51
|
|
113613
|
+
logger.error("Failed to create edge", error51, {
|
|
113614
|
+
sourceId: edge.sourceId,
|
|
113615
|
+
targetId: edge.targetId,
|
|
113616
|
+
relationType: edge.relationType
|
|
113617
|
+
});
|
|
113447
113618
|
return null;
|
|
113448
113619
|
}
|
|
113449
113620
|
}
|
|
@@ -114039,7 +114210,7 @@ class PgSynapseSessionStore {
|
|
|
114039
114210
|
} catch (e) {
|
|
114040
114211
|
this.hydrateFailedAt = Date.now();
|
|
114041
114212
|
logger.warn("PgSynapseSessionStore hydrate failed (best-effort)", {
|
|
114042
|
-
error: e
|
|
114213
|
+
error: e
|
|
114043
114214
|
});
|
|
114044
114215
|
} finally {
|
|
114045
114216
|
this.hydrating = null;
|
|
@@ -114174,7 +114345,7 @@ class PgSynapseSessionStore {
|
|
|
114174
114345
|
const next = prev.then(fn).catch((e) => {
|
|
114175
114346
|
logger.warn("PgSynapseSessionStore write failed (best-effort)", {
|
|
114176
114347
|
key,
|
|
114177
|
-
error: e
|
|
114348
|
+
error: e
|
|
114178
114349
|
});
|
|
114179
114350
|
});
|
|
114180
114351
|
this.inflight.set(key, next);
|
|
@@ -114280,7 +114451,7 @@ class SessionRegistry {
|
|
|
114280
114451
|
try {
|
|
114281
114452
|
this.store?.save(session);
|
|
114282
114453
|
} catch (error51) {
|
|
114283
|
-
logger.warn("
|
|
114454
|
+
logger.warn("SessionRegistry: store save failed", { sessionId: session.sessionId, error: error51 });
|
|
114284
114455
|
}
|
|
114285
114456
|
return session;
|
|
114286
114457
|
}
|
|
@@ -114288,7 +114459,7 @@ class SessionRegistry {
|
|
|
114288
114459
|
try {
|
|
114289
114460
|
await this.store?.ensureReady();
|
|
114290
114461
|
} catch (error51) {
|
|
114291
|
-
logger.warn("
|
|
114462
|
+
logger.warn("SessionRegistry: store ensureReady failed", { error: error51 });
|
|
114292
114463
|
}
|
|
114293
114464
|
}
|
|
114294
114465
|
async getAsync(sessionId, now2 = Date.now()) {
|
|
@@ -114309,7 +114480,7 @@ class SessionRegistry {
|
|
|
114309
114480
|
session = loaded;
|
|
114310
114481
|
}
|
|
114311
114482
|
} catch (error51) {
|
|
114312
|
-
logger.warn("
|
|
114483
|
+
logger.warn("SessionRegistry: store load failed", { sessionId, error: error51 });
|
|
114313
114484
|
}
|
|
114314
114485
|
}
|
|
114315
114486
|
if (!session)
|
|
@@ -114319,7 +114490,7 @@ class SessionRegistry {
|
|
|
114319
114490
|
try {
|
|
114320
114491
|
this.store?.delete(sessionId);
|
|
114321
114492
|
} catch (error51) {
|
|
114322
|
-
logger.warn("
|
|
114493
|
+
logger.warn("SessionRegistry: store delete (expired) failed", { sessionId, error: error51 });
|
|
114323
114494
|
}
|
|
114324
114495
|
return null;
|
|
114325
114496
|
}
|
|
@@ -114341,7 +114512,7 @@ class SessionRegistry {
|
|
|
114341
114512
|
try {
|
|
114342
114513
|
this.store?.save(session);
|
|
114343
114514
|
} catch (error51) {
|
|
114344
|
-
logger.warn("
|
|
114515
|
+
logger.warn("SessionRegistry: store save (updateTaskContext) failed", { sessionId, error: error51 });
|
|
114345
114516
|
}
|
|
114346
114517
|
return session;
|
|
114347
114518
|
}
|
|
@@ -114368,7 +114539,7 @@ class SessionRegistry {
|
|
|
114368
114539
|
try {
|
|
114369
114540
|
this.store?.recordAccess(sessionId, memoryId, nextCount);
|
|
114370
114541
|
} catch (error51) {
|
|
114371
|
-
logger.warn("
|
|
114542
|
+
logger.warn("SessionRegistry: store recordAccess failed", { sessionId, memoryId, error: error51 });
|
|
114372
114543
|
}
|
|
114373
114544
|
}
|
|
114374
114545
|
delete(sessionId) {
|
|
@@ -114376,7 +114547,7 @@ class SessionRegistry {
|
|
|
114376
114547
|
try {
|
|
114377
114548
|
this.store?.delete(sessionId);
|
|
114378
114549
|
} catch (error51) {
|
|
114379
|
-
logger.warn("
|
|
114550
|
+
logger.warn("SessionRegistry: store delete failed", { sessionId, error: error51 });
|
|
114380
114551
|
}
|
|
114381
114552
|
return removed;
|
|
114382
114553
|
}
|
|
@@ -114404,7 +114575,7 @@ function getSessionRegistry() {
|
|
|
114404
114575
|
const { getSessionStore: getSessionStore2 } = (init_session_store(), __toCommonJS(exports_session_store));
|
|
114405
114576
|
store2 = getSessionStore2();
|
|
114406
114577
|
} catch (error51) {
|
|
114407
|
-
logger.warn("
|
|
114578
|
+
logger.warn("SessionRegistry: store init failed, falling back to MemorySessionStore", { error: error51 });
|
|
114408
114579
|
const { MemorySessionStore: MemorySessionStore2 } = (init_session_store(), __toCommonJS(exports_session_store));
|
|
114409
114580
|
store2 = new MemorySessionStore2;
|
|
114410
114581
|
}
|
|
@@ -115221,19 +115392,22 @@ class LLMJudgeReranker {
|
|
|
115221
115392
|
const tail = results.slice(k2);
|
|
115222
115393
|
const prompt = buildPrompt(query, head);
|
|
115223
115394
|
let verdict;
|
|
115395
|
+
let verdictError;
|
|
115224
115396
|
try {
|
|
115225
|
-
const res = await this.llm.object(prompt, RerankVerdictSchema, { modelRole: "code" });
|
|
115397
|
+
const res = await this.llm.object(prompt, RerankVerdictSchema, { label: "reranker", modelRole: "code" });
|
|
115226
115398
|
verdict = res.ok ? res.value ?? null : null;
|
|
115399
|
+
verdictError = res.ok ? undefined : res.error;
|
|
115227
115400
|
} catch (e) {
|
|
115228
115401
|
logger.warn("LLMJudgeReranker threw \u2014 degrading to input order", {
|
|
115229
115402
|
query,
|
|
115230
|
-
error: e
|
|
115403
|
+
error: e
|
|
115231
115404
|
});
|
|
115232
115405
|
return results;
|
|
115233
115406
|
}
|
|
115234
115407
|
if (!verdict) {
|
|
115235
115408
|
logger.warn("LLMJudgeReranker got {ok:false} \u2014 degrading to input order", {
|
|
115236
|
-
query
|
|
115409
|
+
query,
|
|
115410
|
+
error: verdictError
|
|
115237
115411
|
});
|
|
115238
115412
|
return results;
|
|
115239
115413
|
}
|
|
@@ -117079,7 +117253,7 @@ class TaskEnvelopeService {
|
|
|
117079
117253
|
errors5.push("prime");
|
|
117080
117254
|
logger.warn("synapse_task_begin: prime sub-step failed", {
|
|
117081
117255
|
sessionId,
|
|
117082
|
-
error: err
|
|
117256
|
+
error: err
|
|
117083
117257
|
});
|
|
117084
117258
|
}
|
|
117085
117259
|
}
|
|
@@ -117102,7 +117276,7 @@ class TaskEnvelopeService {
|
|
|
117102
117276
|
errors5.push("search");
|
|
117103
117277
|
logger.warn("synapse_task_begin: search sub-step failed", {
|
|
117104
117278
|
sessionId,
|
|
117105
|
-
error: err
|
|
117279
|
+
error: err
|
|
117106
117280
|
});
|
|
117107
117281
|
}
|
|
117108
117282
|
if (firstHitFile) {
|
|
@@ -117125,7 +117299,7 @@ class TaskEnvelopeService {
|
|
|
117125
117299
|
errors5.push("prefetch");
|
|
117126
117300
|
logger.warn("synapse_task_begin: prefetch sub-step failed", {
|
|
117127
117301
|
sessionId,
|
|
117128
|
-
error: err
|
|
117302
|
+
error: err
|
|
117129
117303
|
});
|
|
117130
117304
|
}
|
|
117131
117305
|
}
|
|
@@ -117136,7 +117310,7 @@ class TaskEnvelopeService {
|
|
|
117136
117310
|
errors5.push("access");
|
|
117137
117311
|
logger.warn("synapse_task_begin: access sub-step failed", {
|
|
117138
117312
|
sessionId,
|
|
117139
|
-
error: err
|
|
117313
|
+
error: err
|
|
117140
117314
|
});
|
|
117141
117315
|
}
|
|
117142
117316
|
}
|
|
@@ -117479,7 +117653,7 @@ async function applySynapseState(deps, baseResults, query, projectId, sessionId,
|
|
|
117479
117653
|
logger.warn("Synapse session lookup failed \u2014 using stateless search", {
|
|
117480
117654
|
sessionId,
|
|
117481
117655
|
projectId,
|
|
117482
|
-
error: error51
|
|
117656
|
+
error: error51
|
|
117483
117657
|
});
|
|
117484
117658
|
return baseResults;
|
|
117485
117659
|
}
|
|
@@ -117500,7 +117674,7 @@ async function applySynapseState(deps, baseResults, query, projectId, sessionId,
|
|
|
117500
117674
|
logger.warn("Synapse processing failed \u2014 using stateless search", {
|
|
117501
117675
|
sessionId,
|
|
117502
117676
|
projectId,
|
|
117503
|
-
error: error51
|
|
117677
|
+
error: error51
|
|
117504
117678
|
});
|
|
117505
117679
|
return baseResults;
|
|
117506
117680
|
}
|
|
@@ -118260,7 +118434,7 @@ class PgJobStore {
|
|
|
118260
118434
|
} catch (e) {
|
|
118261
118435
|
this.recovered = true;
|
|
118262
118436
|
logger.warn("PgJobStore markStaleRunningFailed failed (best-effort)", {
|
|
118263
|
-
error: e
|
|
118437
|
+
error: e
|
|
118264
118438
|
});
|
|
118265
118439
|
}
|
|
118266
118440
|
}
|
|
@@ -118286,7 +118460,7 @@ class PgJobStore {
|
|
|
118286
118460
|
logger.info("PgJobStore hydrated", { rows: this.mirror.size });
|
|
118287
118461
|
} catch (e) {
|
|
118288
118462
|
logger.warn("PgJobStore hydrate failed (best-effort)", {
|
|
118289
|
-
error: e
|
|
118463
|
+
error: e
|
|
118290
118464
|
});
|
|
118291
118465
|
} finally {
|
|
118292
118466
|
this.hydrating = null;
|
|
@@ -118309,7 +118483,7 @@ class PgJobStore {
|
|
|
118309
118483
|
next.catch((e) => {
|
|
118310
118484
|
logger.warn("PgJobStore.save failed (best-effort)", {
|
|
118311
118485
|
jobId: job.jobId,
|
|
118312
|
-
error: e
|
|
118486
|
+
error: e
|
|
118313
118487
|
});
|
|
118314
118488
|
});
|
|
118315
118489
|
}
|
|
@@ -118441,7 +118615,7 @@ class PgJobStore {
|
|
|
118441
118615
|
}
|
|
118442
118616
|
} catch (e) {
|
|
118443
118617
|
logger.warn("PgJobStore markStaleRunningFailed failed (best-effort)", {
|
|
118444
|
-
error: e
|
|
118618
|
+
error: e
|
|
118445
118619
|
});
|
|
118446
118620
|
}
|
|
118447
118621
|
})();
|
|
@@ -118631,7 +118805,13 @@ class IndexJobTracker {
|
|
|
118631
118805
|
const stale = hbMs != null && hbMs < cutoff || hbMs == null && startedMs != null && startedMs < cutoff;
|
|
118632
118806
|
if (!stale)
|
|
118633
118807
|
continue;
|
|
118634
|
-
logger.warn(
|
|
118808
|
+
logger.warn("indexJobTracker: reaping stale running job", {
|
|
118809
|
+
jobId: job.jobId,
|
|
118810
|
+
projectId: job.projectId,
|
|
118811
|
+
staleMs,
|
|
118812
|
+
heartbeatAt: job.heartbeatAt?.toISOString() ?? "n/a",
|
|
118813
|
+
startedAt: job.startedAt?.toISOString() ?? "n/a"
|
|
118814
|
+
});
|
|
118635
118815
|
this.jobs.set(job.jobId, job);
|
|
118636
118816
|
const reapedPrevStatus = job.status;
|
|
118637
118817
|
this.setResult(job.jobId, undefined, "heartbeat stale (possible crash/OOM)");
|
|
@@ -118656,7 +118836,7 @@ class IndexJobTracker {
|
|
|
118656
118836
|
try {
|
|
118657
118837
|
this.store?.save(job);
|
|
118658
118838
|
} catch (err) {
|
|
118659
|
-
logger.warn(
|
|
118839
|
+
logger.warn("indexJobTracker: job store write failed on setResult", { jobId, error: err });
|
|
118660
118840
|
}
|
|
118661
118841
|
if (prevStatus === "pending") {
|
|
118662
118842
|
this.publishStateChange(job, prevStatus);
|
|
@@ -118686,7 +118866,7 @@ class IndexJobTracker {
|
|
|
118686
118866
|
const survivors = remaining.slice(0, this.MAX_JOBS);
|
|
118687
118867
|
const overflow = remaining.slice(this.MAX_JOBS);
|
|
118688
118868
|
for (const job of overflow) {
|
|
118689
|
-
logger.warn(
|
|
118869
|
+
logger.warn("indexJobTracker: evicting non-terminal job to honor MAX_JOBS cap \u2014 caller may lose visibility", { jobId: job.jobId, projectId: job.projectId, status: job.status });
|
|
118690
118870
|
this.jobs.delete(job.jobId);
|
|
118691
118871
|
}
|
|
118692
118872
|
}
|
|
@@ -118840,8 +119020,9 @@ class DiscoverStage {
|
|
|
118840
119020
|
};
|
|
118841
119021
|
} catch (err) {
|
|
118842
119022
|
logger.warn("DiscoverStage: failed to stat/read file", {
|
|
119023
|
+
projectId: ctx.projectId,
|
|
118843
119024
|
relativePath,
|
|
118844
|
-
error: err
|
|
119025
|
+
error: err
|
|
118845
119026
|
});
|
|
118846
119027
|
throw new Error(`required_file_unreadable:${relativePath}:${err.message}`);
|
|
118847
119028
|
}
|
|
@@ -121366,8 +121547,9 @@ class ParseStage {
|
|
|
121366
121547
|
timestamp: Date.now()
|
|
121367
121548
|
});
|
|
121368
121549
|
logger.warn("ParseStage: failed to parse file", {
|
|
121550
|
+
projectId: ctx.projectId,
|
|
121369
121551
|
filePath: file3.relativePath,
|
|
121370
|
-
error: err
|
|
121552
|
+
error: err
|
|
121371
121553
|
});
|
|
121372
121554
|
if (err instanceof StructuralEtlParseError)
|
|
121373
121555
|
throw err;
|
|
@@ -122603,7 +122785,7 @@ class ResolveStage {
|
|
|
122603
122785
|
throw new Error("structural_repository_seed_failed", { cause: err });
|
|
122604
122786
|
logger.warn("buildSymbolIndex: repo seed failed, in-batch only", {
|
|
122605
122787
|
projectId,
|
|
122606
|
-
error: err
|
|
122788
|
+
error: err
|
|
122607
122789
|
});
|
|
122608
122790
|
}
|
|
122609
122791
|
const inBatch = new Map;
|
|
@@ -122766,7 +122948,7 @@ async function withDeadlockRetry(operation, options = {}) {
|
|
|
122766
122948
|
attempt,
|
|
122767
122949
|
maxAttempts,
|
|
122768
122950
|
delayMs,
|
|
122769
|
-
error: error51
|
|
122951
|
+
error: error51
|
|
122770
122952
|
});
|
|
122771
122953
|
await new Promise((resolve5) => setTimeout(resolve5, delayMs));
|
|
122772
122954
|
}
|
|
@@ -123896,7 +124078,7 @@ var init_pipeline = __esm(() => {
|
|
|
123896
124078
|
logger.warn("EtlPipeline: search-admission marker write failed", {
|
|
123897
124079
|
projectId,
|
|
123898
124080
|
jobId,
|
|
123899
|
-
error: markerError
|
|
124081
|
+
error: markerError
|
|
123900
124082
|
});
|
|
123901
124083
|
}
|
|
123902
124084
|
if (forceReindex) {
|
|
@@ -123908,7 +124090,7 @@ var init_pipeline = __esm(() => {
|
|
|
123908
124090
|
logger.warn("EtlPipeline: embedding fingerprint stamp failed", {
|
|
123909
124091
|
projectId,
|
|
123910
124092
|
jobId,
|
|
123911
|
-
error: stampError
|
|
124093
|
+
error: stampError
|
|
123912
124094
|
});
|
|
123913
124095
|
}
|
|
123914
124096
|
}
|
|
@@ -125140,9 +125322,9 @@ class SymbolGraphService {
|
|
|
125140
125322
|
return null;
|
|
125141
125323
|
const workspace = graphSnapshot.workspace;
|
|
125142
125324
|
const arch = await this.computeArchitectureMapSafe(graphSnapshot.architecture).catch((err) => {
|
|
125143
|
-
logger.warn("
|
|
125325
|
+
logger.warn("SymbolGraphService: getProjectMap architecture map failed, skipping", {
|
|
125144
125326
|
projectId,
|
|
125145
|
-
error: err
|
|
125327
|
+
error: err
|
|
125146
125328
|
});
|
|
125147
125329
|
return null;
|
|
125148
125330
|
});
|
|
@@ -125684,7 +125866,7 @@ class RelationExtractor {
|
|
|
125684
125866
|
} catch (error51) {
|
|
125685
125867
|
logger.warn("RelationExtractor: extraction failed", {
|
|
125686
125868
|
memoryId,
|
|
125687
|
-
error: error51
|
|
125869
|
+
error: error51
|
|
125688
125870
|
});
|
|
125689
125871
|
}
|
|
125690
125872
|
return edgesCreated;
|
|
@@ -126131,7 +126313,7 @@ class MemoryGraphService {
|
|
|
126131
126313
|
} catch (error51) {
|
|
126132
126314
|
logger.warn("Graph update failed after memory store", {
|
|
126133
126315
|
memoryId,
|
|
126134
|
-
error: error51
|
|
126316
|
+
error: error51
|
|
126135
126317
|
});
|
|
126136
126318
|
}
|
|
126137
126319
|
}
|
|
@@ -126147,7 +126329,7 @@ class MemoryGraphService {
|
|
|
126147
126329
|
} catch (error51) {
|
|
126148
126330
|
logger.warn("Graph cleanup failed after memory delete", {
|
|
126149
126331
|
memoryId,
|
|
126150
|
-
error: error51
|
|
126332
|
+
error: error51
|
|
126151
126333
|
});
|
|
126152
126334
|
}
|
|
126153
126335
|
}
|
|
@@ -126296,7 +126478,7 @@ async function consolidateWindow(candidates2, llm2, opts = {}) {
|
|
|
126296
126478
|
if (!llm2.isEnabled())
|
|
126297
126479
|
return null;
|
|
126298
126480
|
const prompt = buildPrompt2(window2);
|
|
126299
|
-
const result = await llm2.object(prompt, ConsolidatedBatchSchema);
|
|
126481
|
+
const result = await llm2.object(prompt, ConsolidatedBatchSchema, { label: "memory-consolidation" });
|
|
126300
126482
|
if (!result.ok || !result.value)
|
|
126301
126483
|
return null;
|
|
126302
126484
|
const batch = {
|
|
@@ -126397,7 +126579,7 @@ class MemoryConsolidationJob {
|
|
|
126397
126579
|
} catch (error51) {
|
|
126398
126580
|
logger.warn("Memory consolidation skipped", {
|
|
126399
126581
|
trigger,
|
|
126400
|
-
error: error51
|
|
126582
|
+
error: error51
|
|
126401
126583
|
});
|
|
126402
126584
|
} finally {
|
|
126403
126585
|
this.running = false;
|
|
@@ -126420,7 +126602,7 @@ class MemoryConsolidationJob {
|
|
|
126420
126602
|
candidates2 = await Promise.resolve(repo.listConsolidationCandidates(staleSinceMs, 500));
|
|
126421
126603
|
} catch (e) {
|
|
126422
126604
|
logger.warn("consolidation: candidate list failed (decay)", {
|
|
126423
|
-
error: e
|
|
126605
|
+
error: e
|
|
126424
126606
|
});
|
|
126425
126607
|
return 0;
|
|
126426
126608
|
}
|
|
@@ -126442,7 +126624,7 @@ class MemoryConsolidationJob {
|
|
|
126442
126624
|
} catch (e) {
|
|
126443
126625
|
logger.warn("consolidation: decay write failed", {
|
|
126444
126626
|
id: row.id,
|
|
126445
|
-
error: e
|
|
126627
|
+
error: e
|
|
126446
126628
|
});
|
|
126447
126629
|
}
|
|
126448
126630
|
}
|
|
@@ -126471,14 +126653,14 @@ class MemoryConsolidationJob {
|
|
|
126471
126653
|
} catch (e) {
|
|
126472
126654
|
logger.warn("consolidation: soft-delete failed", {
|
|
126473
126655
|
id: row.id,
|
|
126474
|
-
error: e
|
|
126656
|
+
error: e
|
|
126475
126657
|
});
|
|
126476
126658
|
}
|
|
126477
126659
|
}
|
|
126478
126660
|
}
|
|
126479
126661
|
} catch (e) {
|
|
126480
126662
|
logger.warn("consolidation: prune scan failed", {
|
|
126481
|
-
error: e
|
|
126663
|
+
error: e
|
|
126482
126664
|
});
|
|
126483
126665
|
}
|
|
126484
126666
|
return pruned;
|
|
@@ -126489,7 +126671,7 @@ class MemoryConsolidationJob {
|
|
|
126489
126671
|
candidates2 = await Promise.resolve(repo.listConsolidationCandidates(staleSinceMs, 200));
|
|
126490
126672
|
} catch (e) {
|
|
126491
126673
|
logger.warn("consolidation: candidate list failed (merge)", {
|
|
126492
|
-
error: e
|
|
126674
|
+
error: e
|
|
126493
126675
|
});
|
|
126494
126676
|
return { merged: 0, batchesCreated: 0 };
|
|
126495
126677
|
}
|
|
@@ -126515,7 +126697,7 @@ class MemoryConsolidationJob {
|
|
|
126515
126697
|
} catch (e) {
|
|
126516
126698
|
logger.warn("consolidation: merge insert failed", {
|
|
126517
126699
|
batchId: batch.id,
|
|
126518
|
-
error: e
|
|
126700
|
+
error: e
|
|
126519
126701
|
});
|
|
126520
126702
|
return { merged: 0, batchesCreated: 0 };
|
|
126521
126703
|
}
|
|
@@ -126528,7 +126710,7 @@ class MemoryConsolidationJob {
|
|
|
126528
126710
|
logger.warn("consolidation: addSupercedesEdge failed", {
|
|
126529
126711
|
newId,
|
|
126530
126712
|
sourceId,
|
|
126531
|
-
error: e
|
|
126713
|
+
error: e
|
|
126532
126714
|
});
|
|
126533
126715
|
}
|
|
126534
126716
|
}
|
|
@@ -126568,7 +126750,7 @@ class MemoryConsolidationJob {
|
|
|
126568
126750
|
return result;
|
|
126569
126751
|
} catch (e) {
|
|
126570
126752
|
logger.warn("consolidation: promote (PG) failed", {
|
|
126571
|
-
error: e
|
|
126753
|
+
error: e
|
|
126572
126754
|
});
|
|
126573
126755
|
return 0;
|
|
126574
126756
|
}
|
|
@@ -126607,19 +126789,22 @@ class SalienceJudge {
|
|
|
126607
126789
|
}
|
|
126608
126790
|
const prompt = buildPrompt3(trimmed, type);
|
|
126609
126791
|
let verdict;
|
|
126792
|
+
let verdictError;
|
|
126610
126793
|
try {
|
|
126611
|
-
const res = await this.llm.object(prompt, SalienceSchema);
|
|
126794
|
+
const res = await this.llm.object(prompt, SalienceSchema, { label: "salience-judge" });
|
|
126612
126795
|
verdict = res.ok ? res.value ?? null : null;
|
|
126796
|
+
verdictError = res.ok ? undefined : res.error;
|
|
126613
126797
|
} catch (e) {
|
|
126614
126798
|
logger.warn("SalienceJudge threw \u2014 degrading to neutral default", {
|
|
126615
126799
|
type,
|
|
126616
|
-
error: e
|
|
126800
|
+
error: e
|
|
126617
126801
|
});
|
|
126618
126802
|
return { salience: NEUTRAL_SALIENCE, source: "default" };
|
|
126619
126803
|
}
|
|
126620
126804
|
if (!verdict) {
|
|
126621
126805
|
logger.warn("SalienceJudge got {ok:false} \u2014 degrading to neutral default", {
|
|
126622
|
-
type
|
|
126806
|
+
type,
|
|
126807
|
+
error: verdictError
|
|
126623
126808
|
});
|
|
126624
126809
|
return { salience: NEUTRAL_SALIENCE, source: "default" };
|
|
126625
126810
|
}
|
|
@@ -126834,7 +127019,8 @@ class MemoryController {
|
|
|
126834
127019
|
}
|
|
126835
127020
|
} catch (err) {
|
|
126836
127021
|
logger.warn("Graph enrichment failed", {
|
|
126837
|
-
|
|
127022
|
+
projectId,
|
|
127023
|
+
error: err
|
|
126838
127024
|
});
|
|
126839
127025
|
}
|
|
126840
127026
|
}
|
|
@@ -127036,7 +127222,7 @@ class CodeCompressor {
|
|
|
127036
127222
|
}
|
|
127037
127223
|
const prompt = buildLlmCompressPrompt(content, language3, targetRatio, preservedElements);
|
|
127038
127224
|
try {
|
|
127039
|
-
const res = await this.llmCompleteFn(prompt, { timeoutMs, modelRole: "code" });
|
|
127225
|
+
const res = await this.llmCompleteFn(prompt, { label: "code-compressor", timeoutMs, modelRole: "code" });
|
|
127040
127226
|
if (res.ok && typeof res.value === "string" && res.value.trim().length > 0 && res.value.length <= content.length) {
|
|
127041
127227
|
compressed = res.value;
|
|
127042
127228
|
compressionSource = "llm";
|
|
@@ -127076,7 +127262,10 @@ class CodeCompressor {
|
|
|
127076
127262
|
});
|
|
127077
127263
|
return compressedContent;
|
|
127078
127264
|
} catch (error51) {
|
|
127079
|
-
logger.error("Code compression failed", error51
|
|
127265
|
+
logger.error("Code compression failed", error51, {
|
|
127266
|
+
strategy: useStrategy,
|
|
127267
|
+
originalLength: content.length
|
|
127268
|
+
});
|
|
127080
127269
|
return CompressedContent.identity(content);
|
|
127081
127270
|
}
|
|
127082
127271
|
}
|
|
@@ -127386,9 +127575,9 @@ class TokenMetrics {
|
|
|
127386
127575
|
}
|
|
127387
127576
|
throw new Error("Model not found in models.dev");
|
|
127388
127577
|
} catch (error51) {
|
|
127389
|
-
logger.warn("
|
|
127578
|
+
logger.warn("TokenMetrics: failed to fetch pricing from models.dev, using fallback", {
|
|
127390
127579
|
modelId,
|
|
127391
|
-
error: error51
|
|
127580
|
+
error: error51
|
|
127392
127581
|
});
|
|
127393
127582
|
const fallback = FALLBACK_PRICING2[modelId] || FALLBACK_PRICING2["gpt-4"];
|
|
127394
127583
|
this.pricingCache.set(modelId, {
|
|
@@ -127726,7 +127915,7 @@ class ContextController {
|
|
|
127726
127915
|
});
|
|
127727
127916
|
}
|
|
127728
127917
|
} catch (err) {
|
|
127729
|
-
logger.warn("
|
|
127918
|
+
logger.warn("ContextController: graph prefilter failed", { projectId, query, error: err });
|
|
127730
127919
|
}
|
|
127731
127920
|
}
|
|
127732
127921
|
const [searchResult, memories] = await Promise.all([
|
|
@@ -127880,9 +128069,11 @@ class ContextController {
|
|
|
127880
128069
|
});
|
|
127881
128070
|
return result.memories;
|
|
127882
128071
|
} catch (error51) {
|
|
127883
|
-
logger.warn("
|
|
127884
|
-
|
|
127885
|
-
|
|
128072
|
+
logger.warn("ContextController: memory search failed, continuing without memories", {
|
|
128073
|
+
projectId: opts.projectId,
|
|
128074
|
+
sessionId: opts.sessionId,
|
|
128075
|
+
query: query.slice(0, 30),
|
|
128076
|
+
error: error51
|
|
127886
128077
|
});
|
|
127887
128078
|
return [];
|
|
127888
128079
|
}
|
|
@@ -128063,7 +128254,7 @@ class PgCheckpointStore {
|
|
|
128063
128254
|
} catch (e) {
|
|
128064
128255
|
this.hydrateFailedAt = Date.now();
|
|
128065
128256
|
logger.warn("PgCheckpointStore hydrate failed (best-effort)", {
|
|
128066
|
-
error: e
|
|
128257
|
+
error: e
|
|
128067
128258
|
});
|
|
128068
128259
|
} finally {
|
|
128069
128260
|
this.hydrating = null;
|
|
@@ -128257,8 +128448,9 @@ class PgCheckpointStore {
|
|
|
128257
128448
|
}
|
|
128258
128449
|
return existing;
|
|
128259
128450
|
} catch (e) {
|
|
128260
|
-
logger.warn("countExistingMemoryIds failed (best-effort
|
|
128261
|
-
|
|
128451
|
+
logger.warn("PgCheckpointStore: countExistingMemoryIds failed (best-effort, assuming all exist)", {
|
|
128452
|
+
memoryIdCount: memoryIds.length,
|
|
128453
|
+
error: e
|
|
128262
128454
|
});
|
|
128263
128455
|
return memoryIds;
|
|
128264
128456
|
}
|
|
@@ -128325,7 +128517,7 @@ class PgCheckpointStore {
|
|
|
128325
128517
|
const next = prev.then(fn).catch((e) => {
|
|
128326
128518
|
logger.warn("PgCheckpointStore write failed (best-effort)", {
|
|
128327
128519
|
key,
|
|
128328
|
-
error: e
|
|
128520
|
+
error: e
|
|
128329
128521
|
});
|
|
128330
128522
|
});
|
|
128331
128523
|
this.inflight.set(key, next);
|
|
@@ -128464,7 +128656,7 @@ class PgObservationStore {
|
|
|
128464
128656
|
} catch (e) {
|
|
128465
128657
|
this.hydrateFailedAt = Date.now();
|
|
128466
128658
|
logger.warn("PgObservationStore hydrate failed (best-effort)", {
|
|
128467
|
-
error: e
|
|
128659
|
+
error: e
|
|
128468
128660
|
});
|
|
128469
128661
|
} finally {
|
|
128470
128662
|
this.hydrating = null;
|
|
@@ -128515,7 +128707,7 @@ class PgObservationStore {
|
|
|
128515
128707
|
const next = prev.then(fn).catch((e) => {
|
|
128516
128708
|
logger.warn("PgObservationStore.insert failed (best-effort)", {
|
|
128517
128709
|
id: key,
|
|
128518
|
-
error: e
|
|
128710
|
+
error: e
|
|
128519
128711
|
});
|
|
128520
128712
|
});
|
|
128521
128713
|
this.inflight.set(key, next);
|
|
@@ -129995,7 +130187,7 @@ function warnSandboxUnavailable() {
|
|
|
129995
130187
|
return;
|
|
129996
130188
|
_warnedAboutNoSandbox = true;
|
|
129997
130189
|
const missingTool = process.platform === "darwin" ? "sandbox-exec" : "docker";
|
|
129998
|
-
logger.warn(
|
|
130190
|
+
logger.warn("Sandbox: no sandbox tool found for auto mode, falling back to best-effort containment", { missingTool, platform: process.platform, effectiveMode: "none" });
|
|
129999
130191
|
}
|
|
130000
130192
|
function getSandboxMode() {
|
|
130001
130193
|
const env6 = process.env.MASSA_AI_EXECUTOR_SANDBOX ?? "auto";
|
|
@@ -130910,7 +131102,10 @@ class ExecutorController {
|
|
|
130910
131102
|
}
|
|
130911
131103
|
};
|
|
130912
131104
|
} catch (error51) {
|
|
130913
|
-
logger.error("batch_execute failed", error51
|
|
131105
|
+
logger.error("batch_execute failed", error51, {
|
|
131106
|
+
commandCount: commands.length,
|
|
131107
|
+
concurrency: effectiveConcurrency
|
|
131108
|
+
});
|
|
130914
131109
|
return {
|
|
130915
131110
|
success: false,
|
|
130916
131111
|
error: `batch_execute failed: ${error51.message}`
|
|
@@ -132852,7 +133047,7 @@ class PgScheduledJobStore {
|
|
|
132852
133047
|
logger.info("PgScheduledJobStore hydrated", { rows: this.mirror.size });
|
|
132853
133048
|
} catch (e) {
|
|
132854
133049
|
logger.warn("PgScheduledJobStore hydrate failed (best-effort)", {
|
|
132855
|
-
error: e
|
|
133050
|
+
error: e
|
|
132856
133051
|
});
|
|
132857
133052
|
} finally {
|
|
132858
133053
|
this.hydrating = null;
|
|
@@ -132866,9 +133061,10 @@ class PgScheduledJobStore {
|
|
|
132866
133061
|
try {
|
|
132867
133062
|
await action();
|
|
132868
133063
|
} catch (e) {
|
|
132869
|
-
logger.warn(
|
|
133064
|
+
logger.warn("PgScheduledJobStore mutation failed (best-effort)", {
|
|
132870
133065
|
id,
|
|
132871
|
-
|
|
133066
|
+
operation,
|
|
133067
|
+
error: e
|
|
132872
133068
|
});
|
|
132873
133069
|
}
|
|
132874
133070
|
};
|
|
@@ -133121,7 +133317,7 @@ class Scheduler {
|
|
|
133121
133317
|
this.timer = setInterval(() => {
|
|
133122
133318
|
this.tick().catch((e) => {
|
|
133123
133319
|
logger.warn("Scheduler tick failed (swallowed)", {
|
|
133124
|
-
error: e
|
|
133320
|
+
error: e
|
|
133125
133321
|
});
|
|
133126
133322
|
});
|
|
133127
133323
|
}, this.tickIntervalMs);
|
|
@@ -133236,7 +133432,7 @@ class Scheduler {
|
|
|
133236
133432
|
logger.warn("Scheduler: job handler threw (caught)", {
|
|
133237
133433
|
id: job.id,
|
|
133238
133434
|
jobKind: job.jobKind,
|
|
133239
|
-
error:
|
|
133435
|
+
error: e
|
|
133240
133436
|
});
|
|
133241
133437
|
} finally {
|
|
133242
133438
|
if (succeeded) {
|
|
@@ -133255,7 +133451,7 @@ class Scheduler {
|
|
|
133255
133451
|
} catch (e) {
|
|
133256
133452
|
logger.warn("Scheduler: persist after fire failed", {
|
|
133257
133453
|
id: job.id,
|
|
133258
|
-
error: e
|
|
133454
|
+
error: e
|
|
133259
133455
|
});
|
|
133260
133456
|
}
|
|
133261
133457
|
this.running.delete(job.jobKind);
|
|
@@ -133275,6 +133471,8 @@ class Scheduler {
|
|
|
133275
133471
|
enabled: j.enabled,
|
|
133276
133472
|
nextRunAt: j.nextRunAt,
|
|
133277
133473
|
lastRunAt: j.lastRunAt,
|
|
133474
|
+
lastSuccessAt: j.lastSuccessAt ?? null,
|
|
133475
|
+
consecutiveFailures: j.consecutiveFailures ?? 0,
|
|
133278
133476
|
due: j.enabled && j.nextRunAt <= now2,
|
|
133279
133477
|
currentlyRunning: this.running.has(j.jobKind)
|
|
133280
133478
|
}))
|
|
@@ -133857,7 +134055,7 @@ async function enrichWithLlm(candidates2, observations, surface) {
|
|
|
133857
134055
|
const prompt = buildEnrichmentPrompt(candidates2, observations);
|
|
133858
134056
|
let enrichment = null;
|
|
133859
134057
|
try {
|
|
133860
|
-
const res = await surface.object(prompt, ProposalEnrichmentSchema);
|
|
134058
|
+
const res = await surface.object(prompt, ProposalEnrichmentSchema, { label: "auto-improve" });
|
|
133861
134059
|
if (!res.ok || !res.value || !Array.isArray(res.value.items)) {
|
|
133862
134060
|
return { candidates: candidates2, used: false };
|
|
133863
134061
|
}
|
|
@@ -134053,7 +134251,7 @@ async function runOnce(job, projectId) {
|
|
|
134053
134251
|
try {
|
|
134054
134252
|
observations = job.observationStore.listRecent(projectId, job.maxWindow);
|
|
134055
134253
|
} catch (e) {
|
|
134056
|
-
logger.warn("auto-improve: listRecent failed", { projectId, error: e
|
|
134254
|
+
logger.warn("auto-improve: listRecent failed", { projectId, error: e });
|
|
134057
134255
|
return noop2;
|
|
134058
134256
|
}
|
|
134059
134257
|
if (observations.length < 2)
|
|
@@ -134068,7 +134266,7 @@ async function runOnce(job, projectId) {
|
|
|
134068
134266
|
if (res.used)
|
|
134069
134267
|
source = "llm";
|
|
134070
134268
|
} catch (e) {
|
|
134071
|
-
logger.warn("auto-improve: enrichWithLlm threw (silent)", { projectId, error: e
|
|
134269
|
+
logger.warn("auto-improve: enrichWithLlm threw (silent)", { projectId, error: e });
|
|
134072
134270
|
}
|
|
134073
134271
|
const seen = new Set;
|
|
134074
134272
|
const unique = candidates2.filter((c) => {
|
|
@@ -134116,7 +134314,7 @@ async function runOnce(job, projectId) {
|
|
|
134116
134314
|
} catch (e) {
|
|
134117
134315
|
if (e instanceof SearchServiceError)
|
|
134118
134316
|
throw e;
|
|
134119
|
-
logger.warn("proposal:auto-approved:threw", { id: r2.id, projectId, error: e
|
|
134317
|
+
logger.warn("proposal:auto-approved:threw", { id: r2.id, projectId, error: e });
|
|
134120
134318
|
}
|
|
134121
134319
|
}
|
|
134122
134320
|
result.proposalsApplied = applied;
|
|
@@ -134145,7 +134343,7 @@ async function approve(job, id, projectId, source = "rule-based") {
|
|
|
134145
134343
|
appliedMemoryId = await applyProposal(job, row);
|
|
134146
134344
|
} catch (e) {
|
|
134147
134345
|
const reason = e instanceof ApplyRejection ? e.reason : "apply-failed";
|
|
134148
|
-
logger.warn("proposal:apply-failed", { id, projectId: row.projectId, reason, error: e
|
|
134346
|
+
logger.warn("proposal:apply-failed", { id, projectId: row.projectId, reason, error: e });
|
|
134149
134347
|
return { ok: false, reason };
|
|
134150
134348
|
}
|
|
134151
134349
|
let updated;
|
|
@@ -134280,9 +134478,9 @@ class AutoImproveJob {
|
|
|
134280
134478
|
return;
|
|
134281
134479
|
this.newSinceRun = 0;
|
|
134282
134480
|
this.lastRunAt = now2;
|
|
134283
|
-
this.runOnce(projectId).catch((e) => logger.warn("auto-improve: runOnce failed (silent)", { projectId, error: e
|
|
134481
|
+
this.runOnce(projectId).catch((e) => logger.warn("auto-improve: runOnce failed (silent)", { projectId, error: e }));
|
|
134284
134482
|
} catch (e) {
|
|
134285
|
-
logger.warn("auto-improve: maybeRun swallowed", { projectId, error: e
|
|
134483
|
+
logger.warn("auto-improve: maybeRun swallowed", { projectId, error: e });
|
|
134286
134484
|
}
|
|
134287
134485
|
}
|
|
134288
134486
|
async runOnce(projectId) {
|
|
@@ -134382,13 +134580,13 @@ class ObservationConsolidationJob {
|
|
|
134382
134580
|
this.runOnce(projectId).catch((e) => {
|
|
134383
134581
|
logger.warn("observation consolidation: runOnce failed (silent)", {
|
|
134384
134582
|
projectId,
|
|
134385
|
-
error: e
|
|
134583
|
+
error: e
|
|
134386
134584
|
});
|
|
134387
134585
|
});
|
|
134388
134586
|
} catch (e) {
|
|
134389
134587
|
logger.warn("observation consolidation: maybeRun swallowed", {
|
|
134390
134588
|
projectId,
|
|
134391
|
-
error: e
|
|
134589
|
+
error: e
|
|
134392
134590
|
});
|
|
134393
134591
|
}
|
|
134394
134592
|
}
|
|
@@ -134412,7 +134610,7 @@ class ObservationConsolidationJob {
|
|
|
134412
134610
|
} catch (e) {
|
|
134413
134611
|
logger.warn("observation consolidation: listRecent failed", {
|
|
134414
134612
|
projectId,
|
|
134415
|
-
error: e
|
|
134613
|
+
error: e
|
|
134416
134614
|
});
|
|
134417
134615
|
return noop2;
|
|
134418
134616
|
}
|
|
@@ -134423,7 +134621,7 @@ class ObservationConsolidationJob {
|
|
|
134423
134621
|
const prompt = buildObservationPrompt(window2);
|
|
134424
134622
|
let batch;
|
|
134425
134623
|
try {
|
|
134426
|
-
const res = await this.llm.object(prompt, ConsolidatedBatchSchema);
|
|
134624
|
+
const res = await this.llm.object(prompt, ConsolidatedBatchSchema, { label: "observation-consolidation" });
|
|
134427
134625
|
if (!res.ok || !res.value) {
|
|
134428
134626
|
return noop2;
|
|
134429
134627
|
}
|
|
@@ -134439,7 +134637,7 @@ class ObservationConsolidationJob {
|
|
|
134439
134637
|
} catch (e) {
|
|
134440
134638
|
logger.warn("observation consolidation: llm.object threw (silent)", {
|
|
134441
134639
|
projectId,
|
|
134442
|
-
error: e
|
|
134640
|
+
error: e
|
|
134443
134641
|
});
|
|
134444
134642
|
return noop2;
|
|
134445
134643
|
}
|
|
@@ -134468,7 +134666,7 @@ class ObservationConsolidationJob {
|
|
|
134468
134666
|
} catch (e) {
|
|
134469
134667
|
logger.warn("observation consolidation: summary insert failed", {
|
|
134470
134668
|
batchId: batch.id,
|
|
134471
|
-
error: e
|
|
134669
|
+
error: e
|
|
134472
134670
|
});
|
|
134473
134671
|
return noop2;
|
|
134474
134672
|
}
|
|
@@ -134745,8 +134943,9 @@ var init_models_dev_client = __esm(() => {
|
|
|
134745
134943
|
path: cachePath
|
|
134746
134944
|
});
|
|
134747
134945
|
} catch (error51) {
|
|
134748
|
-
logger.warn("
|
|
134749
|
-
|
|
134946
|
+
logger.warn("ModelsDevClient: failed to save local pricing cache", {
|
|
134947
|
+
path: cachePath,
|
|
134948
|
+
error: error51
|
|
134750
134949
|
});
|
|
134751
134950
|
}
|
|
134752
134951
|
}
|
|
@@ -134968,7 +135167,7 @@ var init_models_dev_client = __esm(() => {
|
|
|
134968
135167
|
return value;
|
|
134969
135168
|
}
|
|
134970
135169
|
}
|
|
134971
|
-
logger.warn(
|
|
135170
|
+
logger.warn("ModelsDevClient: model pricing not found", { modelId });
|
|
134972
135171
|
return null;
|
|
134973
135172
|
}
|
|
134974
135173
|
async searchModels(query) {
|
|
@@ -135072,8 +135271,9 @@ var init_models_dev_client = __esm(() => {
|
|
|
135072
135271
|
logger.debug("Local pricing cache file deleted");
|
|
135073
135272
|
}
|
|
135074
135273
|
} catch (error51) {
|
|
135075
|
-
logger.warn("
|
|
135076
|
-
|
|
135274
|
+
logger.warn("ModelsDevClient: failed to delete local pricing cache", {
|
|
135275
|
+
path: cachePath,
|
|
135276
|
+
error: error51
|
|
135077
135277
|
});
|
|
135078
135278
|
}
|
|
135079
135279
|
}
|
|
@@ -135729,9 +135929,10 @@ class SearchSessionHook {
|
|
|
135729
135929
|
});
|
|
135730
135930
|
} catch (err) {
|
|
135731
135931
|
logger.warn("SearchSessionHook: store failed (best-effort)", {
|
|
135732
|
-
error: err.message,
|
|
135733
135932
|
projectId,
|
|
135734
|
-
|
|
135933
|
+
sessionId,
|
|
135934
|
+
query: query.slice(0, 60),
|
|
135935
|
+
error: err
|
|
135735
135936
|
});
|
|
135736
135937
|
}
|
|
135737
135938
|
}
|
|
@@ -135807,8 +136008,10 @@ class CoRetrievalHook {
|
|
|
135807
136008
|
peers = await this.findPeers(memoryId, projectId, sessionId);
|
|
135808
136009
|
} catch (err) {
|
|
135809
136010
|
logger.warn("CoRetrievalHook: peer lookup failed", {
|
|
135810
|
-
|
|
135811
|
-
|
|
136011
|
+
projectId,
|
|
136012
|
+
sessionId,
|
|
136013
|
+
memoryId,
|
|
136014
|
+
error: err
|
|
135812
136015
|
});
|
|
135813
136016
|
return;
|
|
135814
136017
|
}
|
|
@@ -152854,6 +153057,7 @@ async function fetchAndConvertOne(url2, deps, opts = {}) {
|
|
|
152854
153057
|
} catch (err) {
|
|
152855
153058
|
const msg = err instanceof Error ? err.message : String(err);
|
|
152856
153059
|
logger.error("fetch_and_index indexChunk failed", err, {
|
|
153060
|
+
projectId,
|
|
152857
153061
|
url: url2,
|
|
152858
153062
|
chunkId: chunk.id
|
|
152859
153063
|
});
|
|
@@ -153044,6 +153248,7 @@ class WebController {
|
|
|
153044
153248
|
return s.value;
|
|
153045
153249
|
const msg = s.reason instanceof Error ? s.reason.message : String(s.reason);
|
|
153046
153250
|
logger.error("fetch_and_index job rejected", s.reason, {
|
|
153251
|
+
projectId,
|
|
153047
153252
|
url: batch[i].url
|
|
153048
153253
|
});
|
|
153049
153254
|
return { kind: "error", url: batch[i].url, error: msg };
|
|
@@ -177750,7 +177955,7 @@ class ListCheckpointsTool {
|
|
|
177750
177955
|
};
|
|
177751
177956
|
return serializeToolResponse(responseData, { format, fields });
|
|
177752
177957
|
} catch (error51) {
|
|
177753
|
-
logger.error("Failed to list checkpoints", error51);
|
|
177958
|
+
logger.error("Failed to list checkpoints", error51, { taskId, projectId });
|
|
177754
177959
|
return {
|
|
177755
177960
|
success: false,
|
|
177756
177961
|
error: `Failed to list checkpoints: ${error51.message}`
|
|
@@ -178053,7 +178258,8 @@ class CompactSnapshotTool {
|
|
|
178053
178258
|
});
|
|
178054
178259
|
} catch (e) {
|
|
178055
178260
|
logger.warn("compact_snapshot: persist failed (non-fatal)", {
|
|
178056
|
-
|
|
178261
|
+
sessionId,
|
|
178262
|
+
error: e
|
|
178057
178263
|
});
|
|
178058
178264
|
persistedId = undefined;
|
|
178059
178265
|
}
|
|
@@ -178778,7 +178984,7 @@ class ProjectRootCache {
|
|
|
178778
178984
|
return workspace.project_path;
|
|
178779
178985
|
}
|
|
178780
178986
|
} catch (error51) {
|
|
178781
|
-
logger.warn("
|
|
178987
|
+
logger.warn("ProjectRootCache: failed to look up project root", { projectId, error: error51 });
|
|
178782
178988
|
}
|
|
178783
178989
|
return null;
|
|
178784
178990
|
}
|
|
@@ -179285,7 +179491,7 @@ class OperationLogRepositoryPg {
|
|
|
179285
179491
|
op: input.op,
|
|
179286
179492
|
projectId,
|
|
179287
179493
|
result: input.result,
|
|
179288
|
-
error: err
|
|
179494
|
+
error: err
|
|
179289
179495
|
});
|
|
179290
179496
|
}
|
|
179291
179497
|
}
|
|
@@ -179500,9 +179706,11 @@ class HookService {
|
|
|
179500
179706
|
});
|
|
179501
179707
|
this.bridge.maybeRun(obs.projectId);
|
|
179502
179708
|
} catch (e) {
|
|
179503
|
-
logger.warn("observation persist failed", {
|
|
179709
|
+
logger.warn("HookService: observation persist failed", {
|
|
179504
179710
|
id: obs.id,
|
|
179505
|
-
|
|
179711
|
+
projectId: obs.projectId,
|
|
179712
|
+
sessionId: obs.sessionId,
|
|
179713
|
+
error: e
|
|
179506
179714
|
});
|
|
179507
179715
|
}
|
|
179508
179716
|
});
|
|
@@ -179650,7 +179858,7 @@ class BootstrapService {
|
|
|
179650
179858
|
} catch (e) {
|
|
179651
179859
|
logger.warn("bootstrap: marker check threw (continuing)", {
|
|
179652
179860
|
projectId,
|
|
179653
|
-
error: e
|
|
179861
|
+
error: e
|
|
179654
179862
|
});
|
|
179655
179863
|
}
|
|
179656
179864
|
} else if (!cfg.refreshEnabled) {
|
|
@@ -179698,7 +179906,7 @@ class BootstrapService {
|
|
|
179698
179906
|
} catch (e) {
|
|
179699
179907
|
logger.warn("bootstrap: storeSeeds failed (silent)", {
|
|
179700
179908
|
projectId,
|
|
179701
|
-
error: e
|
|
179909
|
+
error: e
|
|
179702
179910
|
});
|
|
179703
179911
|
return { ...noopResult("insert-failed"), signalCount, source };
|
|
179704
179912
|
}
|
|
@@ -179851,7 +180059,7 @@ async function summarizeWithLlm(signals, surface, maxSeedMemories) {
|
|
|
179851
180059
|
return { ok: false, reason: "llm disabled" };
|
|
179852
180060
|
const prompt = buildSummarizePrompt(signals, maxSeedMemories);
|
|
179853
180061
|
try {
|
|
179854
|
-
const res = await surface.object(prompt, SeedMemoriesSchema, { modelRole: "code" });
|
|
180062
|
+
const res = await surface.object(prompt, SeedMemoriesSchema, { label: "bootstrap-seed", modelRole: "code" });
|
|
179855
180063
|
if (!res.ok || !res.value) {
|
|
179856
180064
|
return { ok: false, reason: res.error || "llm returned no value" };
|
|
179857
180065
|
}
|
|
@@ -180454,7 +180662,7 @@ function formatMemoryContent(record2) {
|
|
|
180454
180662
|
}
|
|
180455
180663
|
async function polishSummary(surface, input) {
|
|
180456
180664
|
const prompt = buildPolishPrompt(input);
|
|
180457
|
-
const res = await surface.object(prompt, HandoffSummarySchema);
|
|
180665
|
+
const res = await surface.object(prompt, HandoffSummarySchema, { label: "handoff-summary" });
|
|
180458
180666
|
if (!res.ok || !res.value || !res.value.summary)
|
|
180459
180667
|
return null;
|
|
180460
180668
|
return res.value.summary;
|
|
@@ -180664,7 +180872,10 @@ var memoryRoutes = new Elysia({ prefix: "/api/v1/memory" }).post("/store", async
|
|
|
180664
180872
|
try {
|
|
180665
180873
|
return await getStoreMemoryTool().handle(body);
|
|
180666
180874
|
} catch (error51) {
|
|
180667
|
-
logger.error("Failed to initialize StoreMemoryTool", error51
|
|
180875
|
+
logger.error("Failed to initialize StoreMemoryTool", error51, {
|
|
180876
|
+
projectId: body.projectId,
|
|
180877
|
+
sessionId: body.sessionId
|
|
180878
|
+
});
|
|
180668
180879
|
return {
|
|
180669
180880
|
success: false,
|
|
180670
180881
|
error: `Memory service unavailable: ${error51.message}`
|
|
@@ -180701,7 +180912,10 @@ var memoryRoutes = new Elysia({ prefix: "/api/v1/memory" }).post("/store", async
|
|
|
180701
180912
|
try {
|
|
180702
180913
|
return await getSearchMemoriesTool().handle(body);
|
|
180703
180914
|
} catch (error51) {
|
|
180704
|
-
logger.error("Failed to initialize SearchMemoriesTool", error51
|
|
180915
|
+
logger.error("Failed to initialize SearchMemoriesTool", error51, {
|
|
180916
|
+
projectId: body.projectId,
|
|
180917
|
+
sessionId: body.sessionId
|
|
180918
|
+
});
|
|
180705
180919
|
return {
|
|
180706
180920
|
success: false,
|
|
180707
180921
|
error: `Memory service unavailable: ${error51.message}`
|
|
@@ -180736,7 +180950,9 @@ var memoryRoutes = new Elysia({ prefix: "/api/v1/memory" }).post("/store", async
|
|
|
180736
180950
|
try {
|
|
180737
180951
|
return await getUpdateMemoryTool().handle(body);
|
|
180738
180952
|
} catch (error51) {
|
|
180739
|
-
logger.error("Failed to initialize UpdateMemoryTool", error51
|
|
180953
|
+
logger.error("Failed to initialize UpdateMemoryTool", error51, {
|
|
180954
|
+
id: body.id
|
|
180955
|
+
});
|
|
180740
180956
|
return {
|
|
180741
180957
|
success: false,
|
|
180742
180958
|
error: `Memory service unavailable: ${error51.message}`
|
|
@@ -180762,7 +180978,9 @@ var memoryRoutes = new Elysia({ prefix: "/api/v1/memory" }).post("/store", async
|
|
|
180762
180978
|
try {
|
|
180763
180979
|
return await getDeleteMemoryTool().handle(body);
|
|
180764
180980
|
} catch (error51) {
|
|
180765
|
-
logger.error("Failed to initialize DeleteMemoryTool", error51
|
|
180981
|
+
logger.error("Failed to initialize DeleteMemoryTool", error51, {
|
|
180982
|
+
id: body.id
|
|
180983
|
+
});
|
|
180766
180984
|
return {
|
|
180767
180985
|
success: false,
|
|
180768
180986
|
error: `Memory service unavailable: ${error51.message}`
|
|
@@ -180803,7 +181021,10 @@ var memoryRoutes = new Elysia({ prefix: "/api/v1/memory" }).post("/store", async
|
|
|
180803
181021
|
data: { memories: rows.map(formatRow), total, limit, offset }
|
|
180804
181022
|
};
|
|
180805
181023
|
} catch (error51) {
|
|
180806
|
-
logger.error("Failed to list memories", error51
|
|
181024
|
+
logger.error("Failed to list memories", error51, {
|
|
181025
|
+
projectId: body.projectId,
|
|
181026
|
+
sessionId: body.sessionId
|
|
181027
|
+
});
|
|
180807
181028
|
return {
|
|
180808
181029
|
success: false,
|
|
180809
181030
|
error: `Failed to list memories: ${error51.message}`
|
|
@@ -180873,7 +181094,10 @@ var checkpointRoutes = new Elysia({ prefix: "/api/v1/checkpoints" }).post("/list
|
|
|
180873
181094
|
try {
|
|
180874
181095
|
return await getListCheckpointsTool().handle(body);
|
|
180875
181096
|
} catch (error51) {
|
|
180876
|
-
logger.error("Failed to list checkpoints", error51
|
|
181097
|
+
logger.error("Failed to list checkpoints", error51, {
|
|
181098
|
+
taskId: body.taskId,
|
|
181099
|
+
projectId: body.projectId
|
|
181100
|
+
});
|
|
180877
181101
|
return {
|
|
180878
181102
|
success: false,
|
|
180879
181103
|
error: `Checkpoint service unavailable: ${error51.message}`
|
|
@@ -180897,7 +181121,10 @@ var checkpointRoutes = new Elysia({ prefix: "/api/v1/checkpoints" }).post("/list
|
|
|
180897
181121
|
try {
|
|
180898
181122
|
return await getCreateCheckpointTool().handle(body);
|
|
180899
181123
|
} catch (error51) {
|
|
180900
|
-
logger.error("Failed to create checkpoint", error51
|
|
181124
|
+
logger.error("Failed to create checkpoint", error51, {
|
|
181125
|
+
taskId: body.taskId,
|
|
181126
|
+
projectId: body.projectId
|
|
181127
|
+
});
|
|
180901
181128
|
return {
|
|
180902
181129
|
success: false,
|
|
180903
181130
|
error: `Checkpoint service unavailable: ${error51.message}`
|
|
@@ -180938,7 +181165,10 @@ var checkpointRoutes = new Elysia({ prefix: "/api/v1/checkpoints" }).post("/list
|
|
|
180938
181165
|
try {
|
|
180939
181166
|
return await getRestoreCheckpointTool().handle(body);
|
|
180940
181167
|
} catch (error51) {
|
|
180941
|
-
logger.error("Failed to restore checkpoint", error51
|
|
181168
|
+
logger.error("Failed to restore checkpoint", error51, {
|
|
181169
|
+
checkpointId: body.checkpointId,
|
|
181170
|
+
taskId: body.taskId
|
|
181171
|
+
});
|
|
180942
181172
|
return {
|
|
180943
181173
|
success: false,
|
|
180944
181174
|
error: `Checkpoint service unavailable: ${error51.message}`
|
|
@@ -180958,8 +181188,10 @@ var checkpointRoutes = new Elysia({ prefix: "/api/v1/checkpoints" }).post("/list
|
|
|
180958
181188
|
description: "Restore a saved checkpoint and return its state plus integrity checks."
|
|
180959
181189
|
}
|
|
180960
181190
|
}).post("/delete", ({ body, set: set3 }) => {
|
|
181191
|
+
let checkpointId;
|
|
180961
181192
|
try {
|
|
180962
181193
|
const { id } = body;
|
|
181194
|
+
checkpointId = id;
|
|
180963
181195
|
const existed = getCheckpointManager().deleteCheckpoint(id);
|
|
180964
181196
|
if (!existed) {
|
|
180965
181197
|
set3.status = 404;
|
|
@@ -180968,7 +181200,7 @@ var checkpointRoutes = new Elysia({ prefix: "/api/v1/checkpoints" }).post("/list
|
|
|
180968
181200
|
set3.status = 200;
|
|
180969
181201
|
return { success: true, data: { ok: true } };
|
|
180970
181202
|
} catch (error51) {
|
|
180971
|
-
logger.error("Failed to delete checkpoint", error51);
|
|
181203
|
+
logger.error("Failed to delete checkpoint", error51, { checkpointId });
|
|
180972
181204
|
set3.status = 500;
|
|
180973
181205
|
return {
|
|
180974
181206
|
success: false,
|
|
@@ -182566,7 +182798,10 @@ var hookRoutes = new Elysia({ prefix: "/api/v1/hook" }).post("/", async ({ body,
|
|
|
182566
182798
|
return { status: e.code, error: e.message };
|
|
182567
182799
|
}
|
|
182568
182800
|
const err = e;
|
|
182569
|
-
logger.error("hook ingestion failed", err
|
|
182801
|
+
logger.error("hook ingestion failed", err, {
|
|
182802
|
+
projectId: body.projectId,
|
|
182803
|
+
event: body.event
|
|
182804
|
+
});
|
|
182570
182805
|
set3.status = 500;
|
|
182571
182806
|
return { status: 500, error: `hook service unavailable: ${err.message}` };
|
|
182572
182807
|
}
|
|
@@ -182605,7 +182840,9 @@ var hookRoutes = new Elysia({ prefix: "/api/v1/hook" }).post("/", async ({ body,
|
|
|
182605
182840
|
return { status: e.code, error: e.message };
|
|
182606
182841
|
}
|
|
182607
182842
|
const err = e;
|
|
182608
|
-
logger.error("hook batch ingestion failed", err
|
|
182843
|
+
logger.error("hook batch ingestion failed", err, {
|
|
182844
|
+
count: (body.events ?? []).length
|
|
182845
|
+
});
|
|
182609
182846
|
set3.status = 500;
|
|
182610
182847
|
return { status: 500, error: `hook service unavailable: ${err.message}` };
|
|
182611
182848
|
}
|
|
@@ -182684,7 +182921,7 @@ var bootstrapRoutes = new Elysia({ prefix: "/api/v1/bootstrap" }).post("/", asyn
|
|
|
182684
182921
|
return { success: true, data: result };
|
|
182685
182922
|
} catch (e) {
|
|
182686
182923
|
const err = e;
|
|
182687
|
-
logger.error("bootstrap failed", err);
|
|
182924
|
+
logger.error("bootstrap failed", err, { projectId, projectPath: projectPath2 });
|
|
182688
182925
|
set3.status = 500;
|
|
182689
182926
|
return { success: false, error: `bootstrap failed: ${err.message}` };
|
|
182690
182927
|
}
|
|
@@ -182758,7 +182995,7 @@ var handoffRoutes = new Elysia({ prefix: "/api/v1/handoff" }).post("/begin", asy
|
|
|
182758
182995
|
} catch (e) {
|
|
182759
182996
|
rethrowCanonicalHandoffError(e);
|
|
182760
182997
|
const err = e;
|
|
182761
|
-
logger.error("handoff begin failed", err);
|
|
182998
|
+
logger.error("handoff begin failed", err, { projectId: b.projectId });
|
|
182762
182999
|
set3.status = 500;
|
|
182763
183000
|
return { success: false, error: `handoff begin failed: ${err.message}` };
|
|
182764
183001
|
}
|
|
@@ -182794,7 +183031,7 @@ var handoffRoutes = new Elysia({ prefix: "/api/v1/handoff" }).post("/begin", asy
|
|
|
182794
183031
|
} catch (e) {
|
|
182795
183032
|
rethrowCanonicalHandoffError(e);
|
|
182796
183033
|
const err = e;
|
|
182797
|
-
logger.error("handoff accept failed", err);
|
|
183034
|
+
logger.error("handoff accept failed", err, { id: b.id, projectId: b.projectId });
|
|
182798
183035
|
set3.status = 500;
|
|
182799
183036
|
return { success: false, error: `handoff accept failed: ${err.message}` };
|
|
182800
183037
|
}
|
|
@@ -182825,7 +183062,7 @@ var handoffRoutes = new Elysia({ prefix: "/api/v1/handoff" }).post("/begin", asy
|
|
|
182825
183062
|
} catch (e) {
|
|
182826
183063
|
rethrowCanonicalHandoffError(e);
|
|
182827
183064
|
const err = e;
|
|
182828
|
-
logger.error("handoff cancel failed", err);
|
|
183065
|
+
logger.error("handoff cancel failed", err, { id: b.id, projectId: b.projectId });
|
|
182829
183066
|
set3.status = 500;
|
|
182830
183067
|
return { success: false, error: `handoff cancel failed: ${err.message}` };
|
|
182831
183068
|
}
|
|
@@ -182859,7 +183096,7 @@ var handoffRoutes = new Elysia({ prefix: "/api/v1/handoff" }).post("/begin", asy
|
|
|
182859
183096
|
} catch (e) {
|
|
182860
183097
|
rethrowCanonicalHandoffError(e);
|
|
182861
183098
|
const err = e;
|
|
182862
|
-
logger.error("handoff list failed", err);
|
|
183099
|
+
logger.error("handoff list failed", err, { projectId: b.projectId, targetAgent: b.targetAgent });
|
|
182863
183100
|
set3.status = 500;
|
|
182864
183101
|
return { success: false, error: `handoff list failed: ${err.message}` };
|
|
182865
183102
|
}
|
|
@@ -182941,7 +183178,7 @@ var handoffRoutes = new Elysia({ prefix: "/api/v1/handoff" }).post("/begin", asy
|
|
|
182941
183178
|
} catch (e) {
|
|
182942
183179
|
rethrowCanonicalHandoffError(e);
|
|
182943
183180
|
const err = e;
|
|
182944
|
-
logger.error("handoff update failed", err);
|
|
183181
|
+
logger.error("handoff update failed", err, { id: params.id, projectId: query.projectId });
|
|
182945
183182
|
set3.status = 500;
|
|
182946
183183
|
return { success: false, error: `handoff update failed: ${err.message}` };
|
|
182947
183184
|
}
|
|
@@ -182974,7 +183211,7 @@ var handoffRoutes = new Elysia({ prefix: "/api/v1/handoff" }).post("/begin", asy
|
|
|
182974
183211
|
} catch (e) {
|
|
182975
183212
|
rethrowCanonicalHandoffError(e);
|
|
182976
183213
|
const err = e;
|
|
182977
|
-
logger.error("handoff delete failed", err);
|
|
183214
|
+
logger.error("handoff delete failed", err, { id: params.id, projectId: query.projectId });
|
|
182978
183215
|
set3.status = 500;
|
|
182979
183216
|
return { success: false, error: `handoff delete failed: ${err.message}` };
|
|
182980
183217
|
}
|
|
@@ -183045,7 +183282,7 @@ var proposalRoutes = new Elysia({ prefix: "/api/v1/proposal" }).post("/list", as
|
|
|
183045
183282
|
if (e instanceof SearchServiceError)
|
|
183046
183283
|
throw e;
|
|
183047
183284
|
const err = e;
|
|
183048
|
-
logger.error("proposal list failed", err);
|
|
183285
|
+
logger.error("proposal list failed", err, { projectId: b.projectId });
|
|
183049
183286
|
set3.status = 500;
|
|
183050
183287
|
return { success: false, error: `proposal list failed: ${err.message}` };
|
|
183051
183288
|
}
|
|
@@ -183076,7 +183313,7 @@ var proposalRoutes = new Elysia({ prefix: "/api/v1/proposal" }).post("/list", as
|
|
|
183076
183313
|
if (e instanceof SearchServiceError)
|
|
183077
183314
|
throw e;
|
|
183078
183315
|
const err = e;
|
|
183079
|
-
logger.error("proposal approve failed", err);
|
|
183316
|
+
logger.error("proposal approve failed", err, { id: b.id, projectId: b.projectId });
|
|
183080
183317
|
set3.status = 500;
|
|
183081
183318
|
return { success: false, error: `proposal approve failed: ${err.message}` };
|
|
183082
183319
|
}
|
|
@@ -183109,7 +183346,7 @@ var proposalRoutes = new Elysia({ prefix: "/api/v1/proposal" }).post("/list", as
|
|
|
183109
183346
|
if (e instanceof SearchServiceError)
|
|
183110
183347
|
throw e;
|
|
183111
183348
|
const err = e;
|
|
183112
|
-
logger.error("proposal reject failed", err);
|
|
183349
|
+
logger.error("proposal reject failed", err, { id: b.id, projectId: b.projectId });
|
|
183113
183350
|
set3.status = 500;
|
|
183114
183351
|
return { success: false, error: `proposal reject failed: ${err.message}` };
|
|
183115
183352
|
}
|
|
@@ -183173,7 +183410,7 @@ var proposalRoutes = new Elysia({ prefix: "/api/v1/proposal" }).post("/list", as
|
|
|
183173
183410
|
return { status: validationStatus, error: e.message };
|
|
183174
183411
|
}
|
|
183175
183412
|
const err = e;
|
|
183176
|
-
logger.error("proposal create failed", err);
|
|
183413
|
+
logger.error("proposal create failed", err, { projectId, kind });
|
|
183177
183414
|
set3.status = 500;
|
|
183178
183415
|
return { success: false, error: `proposal create failed: ${err.message}` };
|
|
183179
183416
|
}
|
|
@@ -183246,7 +183483,7 @@ var proposalRoutes = new Elysia({ prefix: "/api/v1/proposal" }).post("/list", as
|
|
|
183246
183483
|
return { status: validationStatus, error: e.message };
|
|
183247
183484
|
}
|
|
183248
183485
|
const err = e;
|
|
183249
|
-
logger.error("proposal update failed", err);
|
|
183486
|
+
logger.error("proposal update failed", err, { id: params.id, projectId: query.projectId });
|
|
183250
183487
|
set3.status = 500;
|
|
183251
183488
|
return { success: false, error: `proposal update failed: ${err.message}` };
|
|
183252
183489
|
}
|
|
@@ -183295,7 +183532,7 @@ var proposalRoutes = new Elysia({ prefix: "/api/v1/proposal" }).post("/list", as
|
|
|
183295
183532
|
if (e instanceof SearchServiceError)
|
|
183296
183533
|
throw e;
|
|
183297
183534
|
const err = e;
|
|
183298
|
-
logger.error("proposal delete failed", err);
|
|
183535
|
+
logger.error("proposal delete failed", err, { id: params.id, projectId: query.projectId });
|
|
183299
183536
|
set3.status = 500;
|
|
183300
183537
|
return { success: false, error: `proposal delete failed: ${err.message}` };
|
|
183301
183538
|
}
|
|
@@ -183707,8 +183944,8 @@ var dashboardRoutes = new Elysia({ prefix: "/api/v1" }).get("/scheduler/status",
|
|
|
183707
183944
|
enabled: j.enabled,
|
|
183708
183945
|
nextRunAt: j.nextRunAt,
|
|
183709
183946
|
lastRunAt: j.lastRunAt,
|
|
183710
|
-
lastSuccessAt:
|
|
183711
|
-
consecutiveFailures:
|
|
183947
|
+
lastSuccessAt: j.lastSuccessAt,
|
|
183948
|
+
consecutiveFailures: j.consecutiveFailures,
|
|
183712
183949
|
due: j.due,
|
|
183713
183950
|
currentlyRunning: j.currentlyRunning
|
|
183714
183951
|
}))
|
|
@@ -183778,6 +184015,198 @@ function deploymentUnavailableMessage(what) {
|
|
|
183778
184015
|
return `model-registry is unavailable in this deployment: ${what} was not found under ` + `${import.meta.dirname} (searched up ${MAX_LEVELS2} levels). This route requires a ` + `massa-ai source checkout.`;
|
|
183779
184016
|
}
|
|
183780
184017
|
|
|
184018
|
+
// src/routes/profiles.ts
|
|
184019
|
+
var PROFILE_DETAIL = {
|
|
184020
|
+
tags: ["profiles"]
|
|
184021
|
+
};
|
|
184022
|
+
function isNamedError(e) {
|
|
184023
|
+
return e instanceof Error && typeof e.name === "string";
|
|
184024
|
+
}
|
|
184025
|
+
function statusFor(err) {
|
|
184026
|
+
switch (err.name) {
|
|
184027
|
+
case "UnknownProfileError":
|
|
184028
|
+
return 400;
|
|
184029
|
+
case "NoHostsDetectedError":
|
|
184030
|
+
return 404;
|
|
184031
|
+
default:
|
|
184032
|
+
break;
|
|
184033
|
+
}
|
|
184034
|
+
if (err instanceof LockError)
|
|
184035
|
+
return 409;
|
|
184036
|
+
if (err instanceof InstallStateError)
|
|
184037
|
+
return 500;
|
|
184038
|
+
return 500;
|
|
184039
|
+
}
|
|
184040
|
+
function errorBody(err) {
|
|
184041
|
+
return { success: false, error: { code: err.name, message: err.message } };
|
|
184042
|
+
}
|
|
184043
|
+
function validHost(value) {
|
|
184044
|
+
if (value === undefined)
|
|
184045
|
+
return;
|
|
184046
|
+
if (typeof value === "string" && isHost(value))
|
|
184047
|
+
return value;
|
|
184048
|
+
return;
|
|
184049
|
+
}
|
|
184050
|
+
var profileRoutes = new Elysia({ prefix: "/api/v1/profiles" }).get("/", ({ query, set: set3 }) => {
|
|
184051
|
+
const hostParam = query.host;
|
|
184052
|
+
if (hostParam !== undefined && !isHost(hostParam)) {
|
|
184053
|
+
set3.status = 400;
|
|
184054
|
+
return { success: false, error: { code: "InvalidHostError", message: `unknown host "${hostParam}"` } };
|
|
184055
|
+
}
|
|
184056
|
+
try {
|
|
184057
|
+
const inventory = listProfiles(hostParam ? { hosts: [hostParam] } : {});
|
|
184058
|
+
set3.status = 200;
|
|
184059
|
+
return { success: true, data: inventory };
|
|
184060
|
+
} catch (e) {
|
|
184061
|
+
const err = isNamedError(e) ? e : { name: "Error", message: String(e) };
|
|
184062
|
+
set3.status = statusFor(err);
|
|
184063
|
+
return errorBody(err);
|
|
184064
|
+
}
|
|
184065
|
+
}, {
|
|
184066
|
+
query: t.Object({ host: t.Optional(t.String()) }),
|
|
184067
|
+
detail: {
|
|
184068
|
+
...PROFILE_DETAIL,
|
|
184069
|
+
summary: "List shipped profiles + per-host active profile",
|
|
184070
|
+
description: "Returns the shipped profile names, per-host active profile (from recorded install-state, falling back to 'balanced' when unrecorded), and per-host bundle version. Available profile names come from on-disk variant directories only; the registry is never consulted."
|
|
184071
|
+
}
|
|
184072
|
+
}).post("/switch", ({ body, set: set3 }) => {
|
|
184073
|
+
const { profile, host, dryRun } = body;
|
|
184074
|
+
if (host !== undefined && !isHost(host)) {
|
|
184075
|
+
set3.status = 400;
|
|
184076
|
+
return { success: false, error: { code: "InvalidHostError", message: `unknown host "${host}"` } };
|
|
184077
|
+
}
|
|
184078
|
+
try {
|
|
184079
|
+
syncGeneratedVariants({ sourceRoot: getDeploymentRoot() });
|
|
184080
|
+
const report = switchProfile({ profile, host: validHost(host), dryRun });
|
|
184081
|
+
set3.status = 200;
|
|
184082
|
+
return { success: true, data: report };
|
|
184083
|
+
} catch (e) {
|
|
184084
|
+
const err = isNamedError(e) ? e : { name: "Error", message: String(e) };
|
|
184085
|
+
set3.status = statusFor(err);
|
|
184086
|
+
return errorBody(err);
|
|
184087
|
+
}
|
|
184088
|
+
}, {
|
|
184089
|
+
body: t.Object({
|
|
184090
|
+
profile: t.String({ description: "Target profile name" }),
|
|
184091
|
+
host: t.Optional(t.String({ description: "Limit the switch to a single host" })),
|
|
184092
|
+
dryRun: t.Optional(t.Boolean({ description: "Print the per-host plan; change nothing" }))
|
|
184093
|
+
}),
|
|
184094
|
+
detail: {
|
|
184095
|
+
...PROFILE_DETAIL,
|
|
184096
|
+
summary: "Switch installed agents to a profile",
|
|
184097
|
+
description: "Mutates the machine this server runs on: replaces the active installed agent files for every detected, supported host with the chosen profile's variant, and reports per host: switched / skipped (reason) / failed (reason). A session restart is required for the change to take effect. Local trust model \u2014 same as the executor routes."
|
|
184098
|
+
}
|
|
184099
|
+
});
|
|
184100
|
+
|
|
184101
|
+
// src/routes/config.ts
|
|
184102
|
+
init_dist();
|
|
184103
|
+
init_inference_providers();
|
|
184104
|
+
var CONFIG_DETAIL = {
|
|
184105
|
+
tags: ["config"]
|
|
184106
|
+
};
|
|
184107
|
+
function defaultEmbedBatchSize(provider) {
|
|
184108
|
+
const spec = typeof provider === "string" && LOCAL_INFERENCE_IDS.includes(provider) ? INFERENCE_PROVIDERS[provider] : INFERENCE_PROVIDERS.ollama;
|
|
184109
|
+
return spec.embedBatchSize;
|
|
184110
|
+
}
|
|
184111
|
+
var SENSITIVE_FIELDS = {
|
|
184112
|
+
database: ["url"],
|
|
184113
|
+
embedding: ["apiKey"],
|
|
184114
|
+
llm: ["apiKey"],
|
|
184115
|
+
security: ["apiKey"]
|
|
184116
|
+
};
|
|
184117
|
+
function getFieldByPath(config3, section, field3) {
|
|
184118
|
+
const sec = config3[section];
|
|
184119
|
+
if (!sec || typeof sec !== "object")
|
|
184120
|
+
return;
|
|
184121
|
+
const parts = field3.split(".");
|
|
184122
|
+
let val = sec;
|
|
184123
|
+
for (const p of parts) {
|
|
184124
|
+
if (val && typeof val === "object")
|
|
184125
|
+
val = val[p];
|
|
184126
|
+
else
|
|
184127
|
+
return;
|
|
184128
|
+
}
|
|
184129
|
+
return val;
|
|
184130
|
+
}
|
|
184131
|
+
var configRoutes = new Elysia({ prefix: "/api/v1/config" }).get("/", ({ set: set3 }) => {
|
|
184132
|
+
const config3 = loadConfig();
|
|
184133
|
+
const masked = maskSensitive(config3);
|
|
184134
|
+
const restart = restartNeededSections(config3);
|
|
184135
|
+
const shipped = maskSensitive(defaultMassaAiConfig);
|
|
184136
|
+
const defaults2 = {
|
|
184137
|
+
...shipped,
|
|
184138
|
+
embedding: {
|
|
184139
|
+
...shipped.embedding,
|
|
184140
|
+
contextWindow: INFERENCE_ROLE_DEFAULTS.embedding.contextWindow,
|
|
184141
|
+
batchSize: defaultEmbedBatchSize(config3.embedding?.provider)
|
|
184142
|
+
}
|
|
184143
|
+
};
|
|
184144
|
+
set3.status = 200;
|
|
184145
|
+
return {
|
|
184146
|
+
success: true,
|
|
184147
|
+
data: { config: masked, restartNeededSections: restart, defaults: defaults2 }
|
|
184148
|
+
};
|
|
184149
|
+
}, {
|
|
184150
|
+
detail: {
|
|
184151
|
+
...CONFIG_DETAIL,
|
|
184152
|
+
summary: "Get current config with sensitive fields masked",
|
|
184153
|
+
description: "Returns the current config.json with security.apiKey, llm.apiKey, embedding.apiKey, and database.url masked to '***'. Includes restartNeededSections \u2014 the subset of [database, embedding, llm, security] present in the config \u2014 and defaults, the shipped default config (also masked) the Config tab falls back to for any field the persisted file omits. defaults.embedding.contextWindow and defaults.embedding.batchSize are derived rather than shipped: they come from the role table and the resolved provider's seam entry, because defaultMassaAiConfig deliberately leaves both unset (PDM-12)."
|
|
184154
|
+
}
|
|
184155
|
+
}).get("/reveal", ({ query, set: set3 }) => {
|
|
184156
|
+
const section = query.section;
|
|
184157
|
+
const field3 = query.field;
|
|
184158
|
+
if (!section || !field3) {
|
|
184159
|
+
set3.status = 400;
|
|
184160
|
+
return { success: false, error: "section and field query params are required" };
|
|
184161
|
+
}
|
|
184162
|
+
const allowed = SENSITIVE_FIELDS[section];
|
|
184163
|
+
if (!allowed || !allowed.includes(field3)) {
|
|
184164
|
+
set3.status = 400;
|
|
184165
|
+
return { success: false, error: `field "${section}.${field3}" is not a sensitive field` };
|
|
184166
|
+
}
|
|
184167
|
+
const config3 = loadConfig();
|
|
184168
|
+
const value = getFieldByPath(config3, section, field3);
|
|
184169
|
+
set3.status = 200;
|
|
184170
|
+
return { success: true, data: { section, field: field3, value: value ?? "" } };
|
|
184171
|
+
}, {
|
|
184172
|
+
query: t.Object({
|
|
184173
|
+
section: t.String(),
|
|
184174
|
+
field: t.String()
|
|
184175
|
+
}),
|
|
184176
|
+
detail: {
|
|
184177
|
+
...CONFIG_DETAIL,
|
|
184178
|
+
summary: "Reveal a single sensitive config field (unmasked)",
|
|
184179
|
+
description: "Returns the unmasked value for one sensitive field (database.url, embedding.apiKey, llm.apiKey, security.apiKey). Requires API key. Only sensitive fields can be revealed."
|
|
184180
|
+
}
|
|
184181
|
+
}).put("/", ({ body, set: set3 }) => {
|
|
184182
|
+
const result = savePartialConfig(body);
|
|
184183
|
+
if (!result.success) {
|
|
184184
|
+
set3.status = 400;
|
|
184185
|
+
return {
|
|
184186
|
+
success: false,
|
|
184187
|
+
error: "validation failed",
|
|
184188
|
+
details: result.details
|
|
184189
|
+
};
|
|
184190
|
+
}
|
|
184191
|
+
const masked = maskSensitive(result.config);
|
|
184192
|
+
set3.status = 200;
|
|
184193
|
+
return {
|
|
184194
|
+
success: true,
|
|
184195
|
+
data: {
|
|
184196
|
+
config: masked,
|
|
184197
|
+
restartNeededSections: result.restartNeededSections,
|
|
184198
|
+
changedRestartSections: result.changedRestartSections
|
|
184199
|
+
}
|
|
184200
|
+
};
|
|
184201
|
+
}, {
|
|
184202
|
+
body: t.Object({}, { additionalProperties: true }),
|
|
184203
|
+
detail: {
|
|
184204
|
+
...CONFIG_DETAIL,
|
|
184205
|
+
summary: "Update config sections (partial, validated, atomic)",
|
|
184206
|
+
description: "Accepts one or more top-level config sections. Validates each provided section, backs up to config.json.bak.<timestamp>, merges shallowly per top-level key, writes atomically. Returns the updated masked config + restartNeededSections. A sensitive field equal to '***' preserves the existing value."
|
|
184207
|
+
}
|
|
184208
|
+
});
|
|
184209
|
+
|
|
183781
184210
|
// src/routes/model-registry.ts
|
|
183782
184211
|
init_config();
|
|
183783
184212
|
import fs28 from "fs";
|
|
@@ -183795,19 +184224,6 @@ function profilesLib() {
|
|
|
183795
184224
|
}
|
|
183796
184225
|
return _profilesLib;
|
|
183797
184226
|
}
|
|
183798
|
-
function getRegistryHostDefaults() {
|
|
183799
|
-
try {
|
|
183800
|
-
const root2 = getDeploymentRoot();
|
|
183801
|
-
if (!root2)
|
|
183802
|
-
return;
|
|
183803
|
-
const lib = profilesLib();
|
|
183804
|
-
const result = lib.loadEffectiveRegistry({ overlayPath: OVERLAY_PATH });
|
|
183805
|
-
const hostDefaults = result?.registry?.hostDefaults;
|
|
183806
|
-
return hostDefaults && typeof hostDefaults === "object" ? hostDefaults : undefined;
|
|
183807
|
-
} catch {
|
|
183808
|
-
return;
|
|
183809
|
-
}
|
|
183810
|
-
}
|
|
183811
184227
|
var _generatorLib = null;
|
|
183812
184228
|
function generatorLib() {
|
|
183813
184229
|
if (!_generatorLib) {
|
|
@@ -183823,21 +184239,46 @@ function generatorLib() {
|
|
|
183823
184239
|
async function loadAgentsInventory() {
|
|
183824
184240
|
try {
|
|
183825
184241
|
const gen = generatorLib();
|
|
183826
|
-
const
|
|
183827
|
-
return { agents:
|
|
184242
|
+
const names = await gen.scanCharterNames();
|
|
184243
|
+
return { agents: names.map((name26) => ({ name: name26 })) };
|
|
183828
184244
|
} catch (e) {
|
|
183829
184245
|
return { agents: [], agentsError: e.message };
|
|
183830
184246
|
}
|
|
183831
184247
|
}
|
|
184248
|
+
var ALLOWED_OVERLAY_KEYS = new Set(["models", "profiles"]);
|
|
184249
|
+
var LEGACY_OVERLAY_KEYS = new Set(["tiers", "hostDefaults", "workflowTiers", "agentTiers"]);
|
|
184250
|
+
function isPlainObj(v) {
|
|
184251
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
184252
|
+
}
|
|
184253
|
+
function overlayShapeViolations(overlay) {
|
|
184254
|
+
const violations = [];
|
|
184255
|
+
for (const key of Object.keys(overlay)) {
|
|
184256
|
+
if (ALLOWED_OVERLAY_KEYS.has(key))
|
|
184257
|
+
continue;
|
|
184258
|
+
violations.push(LEGACY_OVERLAY_KEYS.has(key) ? `overlay key "${key}" is a v1 registry key removed in v2 \u2014 only "models" and "profiles" are supported overlay sections` : `overlay has unknown top-level key "${key}" \u2014 only "models" and "profiles" are supported`);
|
|
184259
|
+
}
|
|
184260
|
+
if (isPlainObj(overlay.profiles)) {
|
|
184261
|
+
for (const [name26, val] of Object.entries(overlay.profiles)) {
|
|
184262
|
+
if (!isPlainObj(val)) {
|
|
184263
|
+
violations.push(`overlay.profiles.${name26} must be an object, got ${JSON.stringify(val)}`);
|
|
184264
|
+
}
|
|
184265
|
+
}
|
|
184266
|
+
}
|
|
184267
|
+
if (isPlainObj(overlay.models)) {
|
|
184268
|
+
for (const [id, val] of Object.entries(overlay.models)) {
|
|
184269
|
+
if (val !== null && !isPlainObj(val)) {
|
|
184270
|
+
violations.push(`overlay.models.${id} must be an object or null (tombstone), got ${JSON.stringify(val)}`);
|
|
184271
|
+
}
|
|
184272
|
+
}
|
|
184273
|
+
}
|
|
184274
|
+
return violations;
|
|
184275
|
+
}
|
|
183832
184276
|
var REGISTRY_DETAIL = {
|
|
183833
184277
|
tags: ["model-registry"]
|
|
183834
184278
|
};
|
|
183835
184279
|
var OVERLAY_PATH = path42.join(configDir("massa-ai"), "model-profiles.json");
|
|
183836
184280
|
var ZERO_OVERLAY_OVERRIDE_BREAKDOWN = {
|
|
183837
|
-
|
|
183838
|
-
workflowTiers: 0,
|
|
183839
|
-
agentTiers: 0,
|
|
183840
|
-
tiers: 0,
|
|
184281
|
+
models: 0,
|
|
183841
184282
|
profiles: 0
|
|
183842
184283
|
};
|
|
183843
184284
|
var modelRegistryRoutes = new Elysia({ prefix: "/api/v1/model-registry" }).get("/", async ({ set: set3 }) => {
|
|
@@ -183858,6 +184299,7 @@ var modelRegistryRoutes = new Elysia({ prefix: "/api/v1/model-registry" }).get("
|
|
|
183858
184299
|
overlayOverrideCount: result.overlayOverrideCount ?? 0,
|
|
183859
184300
|
overlayOverrideBreakdown: result.overlayOverrideBreakdown ?? ZERO_OVERLAY_OVERRIDE_BREAKDOWN,
|
|
183860
184301
|
...result.overlayError ? { overlayError: result.overlayError } : {},
|
|
184302
|
+
...result.v1BackupPath ? { v1BackupPath: result.v1BackupPath } : {},
|
|
183861
184303
|
agents,
|
|
183862
184304
|
...agentsError ? { agentsError } : {}
|
|
183863
184305
|
}
|
|
@@ -183866,7 +184308,7 @@ var modelRegistryRoutes = new Elysia({ prefix: "/api/v1/model-registry" }).get("
|
|
|
183866
184308
|
detail: {
|
|
183867
184309
|
...REGISTRY_DETAIL,
|
|
183868
184310
|
summary: "Get effective registry (builtin + overlay) with source attribution",
|
|
183869
|
-
description: "Returns the merged registry (builtin + overlay), source attribution (builtin, overlay, tombstoned), overlayOverrideCount (
|
|
184311
|
+
description: "Returns the merged v2 registry (builtin + overlay: models catalog + profiles, each profile carrying a per-host default cell and optional per-agent overrides), source attribution (builtin, overlay, tombstoned), overlayOverrideCount (count of overlay entries surviving normalization, so an operator can see how much of the registry their overlay is overriding), overlayOverrideBreakdown (the same count broken down per category: models, profiles), overlayError if the overlay is corrupted, and agents (spec AC6 \u2014 {name} for every charter under skills/agents/, from a directory scan, best-effort with agentsError on failure) (200 status, never fails)."
|
|
183870
184312
|
}
|
|
183871
184313
|
}).put("/", ({ body, set: set3 }) => {
|
|
183872
184314
|
const root2 = getDeploymentRoot();
|
|
@@ -183876,6 +184318,15 @@ var modelRegistryRoutes = new Elysia({ prefix: "/api/v1/model-registry" }).get("
|
|
|
183876
184318
|
}
|
|
183877
184319
|
const lib = profilesLib();
|
|
183878
184320
|
const overlay = body;
|
|
184321
|
+
const shapeViolations = overlayShapeViolations(overlay);
|
|
184322
|
+
if (shapeViolations.length > 0) {
|
|
184323
|
+
set3.status = 400;
|
|
184324
|
+
return {
|
|
184325
|
+
success: false,
|
|
184326
|
+
error: "validation failed",
|
|
184327
|
+
details: shapeViolations
|
|
184328
|
+
};
|
|
184329
|
+
}
|
|
183879
184330
|
const builtin = lib.loadRegistry(lib.DEFAULT_REGISTRY_PATH);
|
|
183880
184331
|
const merged = lib.mergeOverlay(builtin, overlay);
|
|
183881
184332
|
try {
|
|
@@ -183916,7 +184367,7 @@ var modelRegistryRoutes = new Elysia({ prefix: "/api/v1/model-registry" }).get("
|
|
|
183916
184367
|
detail: {
|
|
183917
184368
|
...REGISTRY_DETAIL,
|
|
183918
184369
|
summary: "Write overlay (full-replace, validated, atomic)",
|
|
183919
|
-
description: "Accepts the full overlay object. Validates the merged result (builtin + overlay) via validateRegistry(). On success, writes atomically to ~/.config/massa-ai/model-profiles.json and returns the updated effective registry, including overlayOverrideCount
|
|
184370
|
+
description: "Accepts the full v2 overlay object ({models?, profiles?} only \u2014 a v1 top-level key (tiers/hostDefaults/workflowTiers/agentTiers) or any other unknown key is rejected outright with 400 before merging). Validates the merged result (builtin + overlay) via validateRegistry(). On success, writes atomically to ~/.config/massa-ai/model-profiles.json and returns the updated effective registry, including overlayOverrideCount and overlayOverrideBreakdown (per-category: models, profiles). On failure, returns 400 with all violations."
|
|
183920
184371
|
}
|
|
183921
184372
|
}).post("/regenerate", ({ set: set3 }) => {
|
|
183922
184373
|
const root2 = getDeploymentRoot();
|
|
@@ -184006,201 +184457,6 @@ function writeOverlayAtomically(overlayPath, data) {
|
|
|
184006
184457
|
}
|
|
184007
184458
|
}
|
|
184008
184459
|
|
|
184009
|
-
// src/routes/profiles.ts
|
|
184010
|
-
var PROFILE_DETAIL = {
|
|
184011
|
-
tags: ["profiles"]
|
|
184012
|
-
};
|
|
184013
|
-
function isNamedError(e) {
|
|
184014
|
-
return e instanceof Error && typeof e.name === "string";
|
|
184015
|
-
}
|
|
184016
|
-
function statusFor(err) {
|
|
184017
|
-
switch (err.name) {
|
|
184018
|
-
case "UnknownProfileError":
|
|
184019
|
-
return 400;
|
|
184020
|
-
case "NoHostsDetectedError":
|
|
184021
|
-
return 404;
|
|
184022
|
-
default:
|
|
184023
|
-
break;
|
|
184024
|
-
}
|
|
184025
|
-
if (err instanceof LockError)
|
|
184026
|
-
return 409;
|
|
184027
|
-
if (err instanceof InstallStateError)
|
|
184028
|
-
return 500;
|
|
184029
|
-
return 500;
|
|
184030
|
-
}
|
|
184031
|
-
function errorBody(err) {
|
|
184032
|
-
return { success: false, error: { code: err.name, message: err.message } };
|
|
184033
|
-
}
|
|
184034
|
-
function validHost(value) {
|
|
184035
|
-
if (value === undefined)
|
|
184036
|
-
return;
|
|
184037
|
-
if (typeof value === "string" && isHost(value))
|
|
184038
|
-
return value;
|
|
184039
|
-
return;
|
|
184040
|
-
}
|
|
184041
|
-
var profileRoutes = new Elysia({ prefix: "/api/v1/profiles" }).get("/", ({ query, set: set3 }) => {
|
|
184042
|
-
const hostParam = query.host;
|
|
184043
|
-
if (hostParam !== undefined && !isHost(hostParam)) {
|
|
184044
|
-
set3.status = 400;
|
|
184045
|
-
return { success: false, error: { code: "InvalidHostError", message: `unknown host "${hostParam}"` } };
|
|
184046
|
-
}
|
|
184047
|
-
try {
|
|
184048
|
-
const inventory = listProfiles({
|
|
184049
|
-
...hostParam ? { hosts: [hostParam] } : {},
|
|
184050
|
-
hostDefaults: getRegistryHostDefaults()
|
|
184051
|
-
});
|
|
184052
|
-
set3.status = 200;
|
|
184053
|
-
return { success: true, data: inventory };
|
|
184054
|
-
} catch (e) {
|
|
184055
|
-
const err = isNamedError(e) ? e : { name: "Error", message: String(e) };
|
|
184056
|
-
set3.status = statusFor(err);
|
|
184057
|
-
return errorBody(err);
|
|
184058
|
-
}
|
|
184059
|
-
}, {
|
|
184060
|
-
query: t.Object({ host: t.Optional(t.String()) }),
|
|
184061
|
-
detail: {
|
|
184062
|
-
...PROFILE_DETAIL,
|
|
184063
|
-
summary: "List shipped profiles + per-host active profile",
|
|
184064
|
-
description: "Returns the shipped profile names, per-host active profile (from recorded state; the registry's declared per-host default shown when unrecorded, falling back to 'balanced' when the registry is unreachable), and per-host bundle version. Available profile names come from on-disk variant directories only; the registry is consulted only for that unrecorded-host default."
|
|
184065
|
-
}
|
|
184066
|
-
}).post("/switch", ({ body, set: set3 }) => {
|
|
184067
|
-
const { profile, host, dryRun } = body;
|
|
184068
|
-
if (host !== undefined && !isHost(host)) {
|
|
184069
|
-
set3.status = 400;
|
|
184070
|
-
return { success: false, error: { code: "InvalidHostError", message: `unknown host "${host}"` } };
|
|
184071
|
-
}
|
|
184072
|
-
try {
|
|
184073
|
-
syncGeneratedVariants({ sourceRoot: getDeploymentRoot() });
|
|
184074
|
-
const report = switchProfile({ profile, host: validHost(host), dryRun });
|
|
184075
|
-
set3.status = 200;
|
|
184076
|
-
return { success: true, data: report };
|
|
184077
|
-
} catch (e) {
|
|
184078
|
-
const err = isNamedError(e) ? e : { name: "Error", message: String(e) };
|
|
184079
|
-
set3.status = statusFor(err);
|
|
184080
|
-
return errorBody(err);
|
|
184081
|
-
}
|
|
184082
|
-
}, {
|
|
184083
|
-
body: t.Object({
|
|
184084
|
-
profile: t.String({ description: "Target profile name" }),
|
|
184085
|
-
host: t.Optional(t.String({ description: "Limit the switch to a single host" })),
|
|
184086
|
-
dryRun: t.Optional(t.Boolean({ description: "Print the per-host plan; change nothing" }))
|
|
184087
|
-
}),
|
|
184088
|
-
detail: {
|
|
184089
|
-
...PROFILE_DETAIL,
|
|
184090
|
-
summary: "Switch installed agents to a profile",
|
|
184091
|
-
description: "Mutates the machine this server runs on: replaces the active installed agent files for every detected, supported host with the chosen profile's variant, and reports per host: switched / skipped (reason) / failed (reason). A session restart is required for the change to take effect. Local trust model \u2014 same as the executor routes."
|
|
184092
|
-
}
|
|
184093
|
-
});
|
|
184094
|
-
|
|
184095
|
-
// src/routes/config.ts
|
|
184096
|
-
init_dist();
|
|
184097
|
-
init_inference_providers();
|
|
184098
|
-
var CONFIG_DETAIL = {
|
|
184099
|
-
tags: ["config"]
|
|
184100
|
-
};
|
|
184101
|
-
function defaultEmbedBatchSize(provider) {
|
|
184102
|
-
const spec = typeof provider === "string" && LOCAL_INFERENCE_IDS.includes(provider) ? INFERENCE_PROVIDERS[provider] : INFERENCE_PROVIDERS.ollama;
|
|
184103
|
-
return spec.embedBatchSize;
|
|
184104
|
-
}
|
|
184105
|
-
var SENSITIVE_FIELDS = {
|
|
184106
|
-
database: ["url"],
|
|
184107
|
-
embedding: ["apiKey"],
|
|
184108
|
-
llm: ["apiKey"],
|
|
184109
|
-
security: ["apiKey"]
|
|
184110
|
-
};
|
|
184111
|
-
function getFieldByPath(config3, section, field3) {
|
|
184112
|
-
const sec = config3[section];
|
|
184113
|
-
if (!sec || typeof sec !== "object")
|
|
184114
|
-
return;
|
|
184115
|
-
const parts = field3.split(".");
|
|
184116
|
-
let val = sec;
|
|
184117
|
-
for (const p of parts) {
|
|
184118
|
-
if (val && typeof val === "object")
|
|
184119
|
-
val = val[p];
|
|
184120
|
-
else
|
|
184121
|
-
return;
|
|
184122
|
-
}
|
|
184123
|
-
return val;
|
|
184124
|
-
}
|
|
184125
|
-
var configRoutes = new Elysia({ prefix: "/api/v1/config" }).get("/", ({ set: set3 }) => {
|
|
184126
|
-
const config3 = loadConfig();
|
|
184127
|
-
const masked = maskSensitive(config3);
|
|
184128
|
-
const restart = restartNeededSections(config3);
|
|
184129
|
-
const shipped = maskSensitive(defaultMassaAiConfig);
|
|
184130
|
-
const defaults2 = {
|
|
184131
|
-
...shipped,
|
|
184132
|
-
embedding: {
|
|
184133
|
-
...shipped.embedding,
|
|
184134
|
-
contextWindow: INFERENCE_ROLE_DEFAULTS.embedding.contextWindow,
|
|
184135
|
-
batchSize: defaultEmbedBatchSize(config3.embedding?.provider)
|
|
184136
|
-
}
|
|
184137
|
-
};
|
|
184138
|
-
set3.status = 200;
|
|
184139
|
-
return {
|
|
184140
|
-
success: true,
|
|
184141
|
-
data: { config: masked, restartNeededSections: restart, defaults: defaults2 }
|
|
184142
|
-
};
|
|
184143
|
-
}, {
|
|
184144
|
-
detail: {
|
|
184145
|
-
...CONFIG_DETAIL,
|
|
184146
|
-
summary: "Get current config with sensitive fields masked",
|
|
184147
|
-
description: "Returns the current config.json with security.apiKey, llm.apiKey, embedding.apiKey, and database.url masked to '***'. Includes restartNeededSections \u2014 the subset of [database, embedding, llm, security] present in the config \u2014 and defaults, the shipped default config (also masked) the Config tab falls back to for any field the persisted file omits. defaults.embedding.contextWindow and defaults.embedding.batchSize are derived rather than shipped: they come from the role table and the resolved provider's seam entry, because defaultMassaAiConfig deliberately leaves both unset (PDM-12)."
|
|
184148
|
-
}
|
|
184149
|
-
}).get("/reveal", ({ query, set: set3 }) => {
|
|
184150
|
-
const section = query.section;
|
|
184151
|
-
const field3 = query.field;
|
|
184152
|
-
if (!section || !field3) {
|
|
184153
|
-
set3.status = 400;
|
|
184154
|
-
return { success: false, error: "section and field query params are required" };
|
|
184155
|
-
}
|
|
184156
|
-
const allowed = SENSITIVE_FIELDS[section];
|
|
184157
|
-
if (!allowed || !allowed.includes(field3)) {
|
|
184158
|
-
set3.status = 400;
|
|
184159
|
-
return { success: false, error: `field "${section}.${field3}" is not a sensitive field` };
|
|
184160
|
-
}
|
|
184161
|
-
const config3 = loadConfig();
|
|
184162
|
-
const value = getFieldByPath(config3, section, field3);
|
|
184163
|
-
set3.status = 200;
|
|
184164
|
-
return { success: true, data: { section, field: field3, value: value ?? "" } };
|
|
184165
|
-
}, {
|
|
184166
|
-
query: t.Object({
|
|
184167
|
-
section: t.String(),
|
|
184168
|
-
field: t.String()
|
|
184169
|
-
}),
|
|
184170
|
-
detail: {
|
|
184171
|
-
...CONFIG_DETAIL,
|
|
184172
|
-
summary: "Reveal a single sensitive config field (unmasked)",
|
|
184173
|
-
description: "Returns the unmasked value for one sensitive field (database.url, embedding.apiKey, llm.apiKey, security.apiKey). Requires API key. Only sensitive fields can be revealed."
|
|
184174
|
-
}
|
|
184175
|
-
}).put("/", ({ body, set: set3 }) => {
|
|
184176
|
-
const result = savePartialConfig(body);
|
|
184177
|
-
if (!result.success) {
|
|
184178
|
-
set3.status = 400;
|
|
184179
|
-
return {
|
|
184180
|
-
success: false,
|
|
184181
|
-
error: "validation failed",
|
|
184182
|
-
details: result.details
|
|
184183
|
-
};
|
|
184184
|
-
}
|
|
184185
|
-
const masked = maskSensitive(result.config);
|
|
184186
|
-
set3.status = 200;
|
|
184187
|
-
return {
|
|
184188
|
-
success: true,
|
|
184189
|
-
data: {
|
|
184190
|
-
config: masked,
|
|
184191
|
-
restartNeededSections: result.restartNeededSections,
|
|
184192
|
-
changedRestartSections: result.changedRestartSections
|
|
184193
|
-
}
|
|
184194
|
-
};
|
|
184195
|
-
}, {
|
|
184196
|
-
body: t.Object({}, { additionalProperties: true }),
|
|
184197
|
-
detail: {
|
|
184198
|
-
...CONFIG_DETAIL,
|
|
184199
|
-
summary: "Update config sections (partial, validated, atomic)",
|
|
184200
|
-
description: "Accepts one or more top-level config sections. Validates each provided section, backs up to config.json.bak.<timestamp>, merges shallowly per top-level key, writes atomically. Returns the updated masked config + restartNeededSections. A sensitive field equal to '***' preserves the existing value."
|
|
184201
|
-
}
|
|
184202
|
-
});
|
|
184203
|
-
|
|
184204
184460
|
// src/routes/model-registry-stream.ts
|
|
184205
184461
|
init_config();
|
|
184206
184462
|
init_dist();
|
|
@@ -184293,7 +184549,7 @@ function installActiveProfiles(controller2, closedRef) {
|
|
|
184293
184549
|
...r2.error ? { error: r2.error } : {}
|
|
184294
184550
|
}));
|
|
184295
184551
|
}
|
|
184296
|
-
const inventory = listProfiles(
|
|
184552
|
+
const inventory = listProfiles();
|
|
184297
184553
|
for (const hostEntry of inventory.hosts) {
|
|
184298
184554
|
if (closedRef.closed)
|
|
184299
184555
|
return;
|