tracer-sh 0.3.4 → 0.3.6
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/README.md +76 -81
- package/package.json +1 -1
- package/packages/server/dist/{chunk-XFJVNMJI.js → chunk-LDYGR5S3.js} +5 -5
- package/packages/server/dist/{domain-knowledge-6MEHHDWL.js → domain-knowledge-KF3XTKCK.js} +1 -1
- package/packages/server/dist/index.js +118 -42
- package/packages/web/dist/assets/{SearchableSelect-CN8LoaWs.js → SearchableSelect-VoTpUxSB.js} +1 -1
- package/packages/web/dist/assets/{Settings-CFRIDe39.js → Settings-CgEySEhC.js} +1 -1
- package/packages/web/dist/assets/{highlighted-body-OFNGDK62-BfZzzZ78.js → highlighted-body-OFNGDK62-GpbSyT-_.js} +1 -1
- package/packages/web/dist/assets/{index-CDazY975.js → index-BsLO7f3R.js} +9 -9
- package/packages/web/dist/assets/{mermaid-GHXKKRXX-BsXccgqR.js → mermaid-GHXKKRXX-CiyDBVIR.js} +3 -3
- package/packages/web/dist/index.html +1 -1
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
NR_AUTH_STOP_RULE,
|
|
14
14
|
NR_DOMAIN_KNOWLEDGE,
|
|
15
15
|
NR_INSIDE_OUT_DEBUGGING
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-LDYGR5S3.js";
|
|
17
17
|
import {
|
|
18
18
|
GCP_AUTH_STOP_RULE,
|
|
19
19
|
GCP_CROSS_SIGNAL,
|
|
@@ -1445,10 +1445,10 @@ var require_retry = __commonJS({
|
|
|
1445
1445
|
if (!await shouldRetryFn(err)) {
|
|
1446
1446
|
return { shouldRetry: false, config: err.config };
|
|
1447
1447
|
}
|
|
1448
|
-
const
|
|
1448
|
+
const delay4 = getNextRetryDelay(config2);
|
|
1449
1449
|
err.config.retryConfig.currentRetryAttempt += 1;
|
|
1450
|
-
const backoff = config2.retryBackoff ? config2.retryBackoff(err,
|
|
1451
|
-
setTimeout(resolve5,
|
|
1450
|
+
const backoff = config2.retryBackoff ? config2.retryBackoff(err, delay4) : new Promise((resolve5) => {
|
|
1451
|
+
setTimeout(resolve5, delay4);
|
|
1452
1452
|
});
|
|
1453
1453
|
if (config2.onRetryAttempt) {
|
|
1454
1454
|
await config2.onRetryAttempt(err);
|
|
@@ -28202,6 +28202,12 @@ var CONFIG = {
|
|
|
28202
28202
|
/** Buffer cap for `npm install -g` output; well above the 1MB default so a noisy
|
|
28203
28203
|
* but successful install (native rebuild logs) isn't misreported as a failure. */
|
|
28204
28204
|
npmInstallMaxBufferBytes: 16 * 1024 * 1024,
|
|
28205
|
+
/** Transient download truncation (e.g. "Content-Length header ... exceeds response Body")
|
|
28206
|
+
* is not retried inside npm, so the whole install is retried instead. */
|
|
28207
|
+
npmInstallAttempts: 3,
|
|
28208
|
+
npmInstallRetryDelayMs: 3e3,
|
|
28209
|
+
/** Re-run the background version check when the cached result is older than this. */
|
|
28210
|
+
updateCheckTtlMs: 6 * 60 * 60 * 1e3,
|
|
28205
28211
|
// ── Dashboard defaults ──
|
|
28206
28212
|
widgetDefaultWidth: 6,
|
|
28207
28213
|
widgetDefaultHeight: 6,
|
|
@@ -28233,6 +28239,9 @@ import { join, dirname, sep } from "path";
|
|
|
28233
28239
|
import { fileURLToPath } from "url";
|
|
28234
28240
|
var RESTART_EXIT_CODE = CONFIG.restartExitCode;
|
|
28235
28241
|
var cachedStatus = null;
|
|
28242
|
+
var lastCheckAtMs = 0;
|
|
28243
|
+
var checkInFlight = false;
|
|
28244
|
+
var installInFlight = false;
|
|
28236
28245
|
var cachedPackageInfo = null;
|
|
28237
28246
|
function resolvePackage() {
|
|
28238
28247
|
if (cachedPackageInfo) return cachedPackageInfo;
|
|
@@ -28271,7 +28280,7 @@ function getInstallMethod() {
|
|
|
28271
28280
|
return detectInstallMethod(resolvePackage().root);
|
|
28272
28281
|
}
|
|
28273
28282
|
function isNewerVersion(latest, current) {
|
|
28274
|
-
const parse4 = (v) => v.replace(/^v/, "").split(".").map(Number);
|
|
28283
|
+
const parse4 = (v) => v.replace(/^v/, "").split(".").map((n) => Number.parseInt(n, 10) || 0);
|
|
28275
28284
|
const [la, lb, lc] = parse4(latest);
|
|
28276
28285
|
const [ca, cb, cc] = parse4(current);
|
|
28277
28286
|
if (la !== ca) return la > ca;
|
|
@@ -28291,6 +28300,9 @@ function fetchLatestNpmVersion() {
|
|
|
28291
28300
|
});
|
|
28292
28301
|
}
|
|
28293
28302
|
function getUpdateStatus() {
|
|
28303
|
+
if (!installInFlight && Date.now() - lastCheckAtMs > CONFIG.updateCheckTtlMs) {
|
|
28304
|
+
checkForUpdateBackground();
|
|
28305
|
+
}
|
|
28294
28306
|
if (cachedStatus) return cachedStatus;
|
|
28295
28307
|
return {
|
|
28296
28308
|
available: false,
|
|
@@ -28300,11 +28312,15 @@ function getUpdateStatus() {
|
|
|
28300
28312
|
};
|
|
28301
28313
|
}
|
|
28302
28314
|
function checkForUpdateBackground() {
|
|
28315
|
+
if (checkInFlight) return;
|
|
28316
|
+
checkInFlight = true;
|
|
28317
|
+
lastCheckAtMs = Date.now();
|
|
28303
28318
|
const current = readCurrentVersion();
|
|
28304
28319
|
const method = getInstallMethod();
|
|
28305
28320
|
const unavailable = () => ({ available: false, currentVersion: current, latestVersion: null, method });
|
|
28306
28321
|
if (current === "unknown") {
|
|
28307
28322
|
cachedStatus = unavailable();
|
|
28323
|
+
checkInFlight = false;
|
|
28308
28324
|
return;
|
|
28309
28325
|
}
|
|
28310
28326
|
fetchLatestNpmVersion().then((latest) => {
|
|
@@ -28315,39 +28331,76 @@ function checkForUpdateBackground() {
|
|
|
28315
28331
|
const available = isNewerVersion(latest, current);
|
|
28316
28332
|
cachedStatus = { available, currentVersion: current, latestVersion: latest, method };
|
|
28317
28333
|
if (available) {
|
|
28318
|
-
const hint = method === "
|
|
28334
|
+
const hint = method === "dev" ? "git pull, then restart tracer-sh \u2014 the launcher rebuilds automatically" : "click the version in the sidebar to update from the app";
|
|
28319
28335
|
console.log(`Update available: v${current} \u2192 v${latest} (${hint})`);
|
|
28320
28336
|
}
|
|
28321
28337
|
}).catch(() => {
|
|
28322
28338
|
cachedStatus = unavailable();
|
|
28339
|
+
}).finally(() => {
|
|
28340
|
+
checkInFlight = false;
|
|
28323
28341
|
});
|
|
28324
28342
|
}
|
|
28325
|
-
function
|
|
28326
|
-
|
|
28327
|
-
|
|
28328
|
-
|
|
28329
|
-
ok: false,
|
|
28330
|
-
method,
|
|
28331
|
-
error: method === "npx" ? "Running via npx, which can't be updated in place. Re-run `npx tracer-sh@latest` to get the latest version." : "Running from a local source checkout, so in-app update is disabled."
|
|
28332
|
-
});
|
|
28333
|
-
}
|
|
28343
|
+
function npxPrefixDir(root) {
|
|
28344
|
+
return dirname(dirname(root));
|
|
28345
|
+
}
|
|
28346
|
+
function runNpmInstall(install) {
|
|
28334
28347
|
return new Promise((resolve5) => {
|
|
28335
28348
|
exec(
|
|
28336
28349
|
// Quiet flags keep output small (a verbose install can otherwise overflow
|
|
28337
28350
|
// the stdout buffer and look like a failure); maxBuffer adds headroom for
|
|
28338
28351
|
// native rebuild logs so a successful install is never misreported.
|
|
28339
|
-
|
|
28352
|
+
`${install} --no-fund --no-audit --loglevel=error --fetch-retries=5`,
|
|
28340
28353
|
{ encoding: "utf-8", timeout: CONFIG.npmInstallTimeoutMs, maxBuffer: CONFIG.npmInstallMaxBufferBytes },
|
|
28341
28354
|
(err, _stdout, stderr) => {
|
|
28342
28355
|
if (err) {
|
|
28343
|
-
|
|
28356
|
+
const full = (stderr || "").trim() || err.message;
|
|
28357
|
+
resolve5({ ok: false, error: full.length > 2e3 ? `\u2026${full.slice(-2e3)}` : full });
|
|
28344
28358
|
return;
|
|
28345
28359
|
}
|
|
28346
|
-
resolve5({ ok: true
|
|
28360
|
+
resolve5({ ok: true });
|
|
28347
28361
|
}
|
|
28348
28362
|
);
|
|
28349
28363
|
});
|
|
28350
28364
|
}
|
|
28365
|
+
var delay = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
28366
|
+
var PERMANENT_NPM_ERROR = /EACCES|EPERM|ENOSPC|E404|ETARGET/;
|
|
28367
|
+
async function withRetries(run3, attempts, delayMs) {
|
|
28368
|
+
let last = { ok: false };
|
|
28369
|
+
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
28370
|
+
last = await run3();
|
|
28371
|
+
if (last.ok) return last;
|
|
28372
|
+
console.warn(`[updater] install attempt ${attempt}/${attempts} failed: ${last.error}`);
|
|
28373
|
+
if (PERMANENT_NPM_ERROR.test(last.error ?? "")) return last;
|
|
28374
|
+
if (attempt < attempts) await delay(delayMs);
|
|
28375
|
+
}
|
|
28376
|
+
return last;
|
|
28377
|
+
}
|
|
28378
|
+
async function performSelfUpdate() {
|
|
28379
|
+
const { root } = resolvePackage();
|
|
28380
|
+
const method = detectInstallMethod(root);
|
|
28381
|
+
if (method === "dev" || !root) {
|
|
28382
|
+
return {
|
|
28383
|
+
ok: false,
|
|
28384
|
+
method,
|
|
28385
|
+
error: "Running from a local source checkout, so in-app update is disabled."
|
|
28386
|
+
};
|
|
28387
|
+
}
|
|
28388
|
+
if (installInFlight) {
|
|
28389
|
+
return { ok: false, method, error: "An update is already in progress." };
|
|
28390
|
+
}
|
|
28391
|
+
const install = method === "global" ? "npm install -g tracer-sh@latest" : `npm install --prefix "${npxPrefixDir(root)}" tracer-sh@latest`;
|
|
28392
|
+
installInFlight = true;
|
|
28393
|
+
try {
|
|
28394
|
+
const result = await withRetries(
|
|
28395
|
+
() => runNpmInstall(install),
|
|
28396
|
+
CONFIG.npmInstallAttempts,
|
|
28397
|
+
CONFIG.npmInstallRetryDelayMs
|
|
28398
|
+
);
|
|
28399
|
+
return { ...result, method };
|
|
28400
|
+
} finally {
|
|
28401
|
+
installInFlight = false;
|
|
28402
|
+
}
|
|
28403
|
+
}
|
|
28351
28404
|
var restartHandler = null;
|
|
28352
28405
|
function setRestartHandler(fn) {
|
|
28353
28406
|
restartHandler = fn;
|
|
@@ -37032,7 +37085,7 @@ function createToolNameMapping({
|
|
|
37032
37085
|
}
|
|
37033
37086
|
};
|
|
37034
37087
|
}
|
|
37035
|
-
async function
|
|
37088
|
+
async function delay2(delayInMs, options) {
|
|
37036
37089
|
if (delayInMs == null) {
|
|
37037
37090
|
return Promise.resolve();
|
|
37038
37091
|
}
|
|
@@ -43648,7 +43701,7 @@ async function _retryWithExponentialBackoff(f, {
|
|
|
43648
43701
|
});
|
|
43649
43702
|
}
|
|
43650
43703
|
if (error48 instanceof Error && APICallError.isInstance(error48) && error48.isRetryable === true && tryNumber <= maxRetries) {
|
|
43651
|
-
await
|
|
43704
|
+
await delay2(
|
|
43652
43705
|
getRetryDelayInMs({
|
|
43653
43706
|
error: error48,
|
|
43654
43707
|
exponentialBackoffDelay: delayInMs
|
|
@@ -49580,7 +49633,7 @@ var CHUNKING_REGEXPS = {
|
|
|
49580
49633
|
function smoothStream({
|
|
49581
49634
|
delayInMs = 10,
|
|
49582
49635
|
chunking = "word",
|
|
49583
|
-
_internal: { delay: delay22 =
|
|
49636
|
+
_internal: { delay: delay22 = delay2 } = {}
|
|
49584
49637
|
} = {}) {
|
|
49585
49638
|
let detectChunk;
|
|
49586
49639
|
if (chunking != null && typeof chunking === "object" && "segment" in chunking && typeof chunking.segment === "function") {
|
|
@@ -57554,7 +57607,7 @@ var GoogleGenerativeAIVideoModel = class {
|
|
|
57554
57607
|
message: `Video generation timed out after ${pollTimeoutMs}ms`
|
|
57555
57608
|
});
|
|
57556
57609
|
}
|
|
57557
|
-
await
|
|
57610
|
+
await delay2(pollIntervalMs);
|
|
57558
57611
|
if ((_f = options.abortSignal) == null ? void 0 : _f.aborted) {
|
|
57559
57612
|
throw new AISDKError({
|
|
57560
57613
|
name: "GOOGLE_VIDEO_GENERATION_ABORTED",
|
|
@@ -58105,7 +58158,7 @@ function combineHeaders2(...headers) {
|
|
|
58105
58158
|
{}
|
|
58106
58159
|
);
|
|
58107
58160
|
}
|
|
58108
|
-
async function
|
|
58161
|
+
async function delay3(delayInMs, options) {
|
|
58109
58162
|
if (delayInMs == null) {
|
|
58110
58163
|
return Promise.resolve();
|
|
58111
58164
|
}
|
|
@@ -62967,7 +63020,7 @@ var GoogleVertexVideoModel = class {
|
|
|
62967
63020
|
message: `Video generation timed out after ${pollTimeoutMs}ms`
|
|
62968
63021
|
});
|
|
62969
63022
|
}
|
|
62970
|
-
await
|
|
63023
|
+
await delay3(pollIntervalMs);
|
|
62971
63024
|
if ((_f = options.abortSignal) == null ? void 0 : _f.aborted) {
|
|
62972
63025
|
throw new AISDKError2({
|
|
62973
63026
|
name: "VERTEX_VIDEO_GENERATION_ABORTED",
|
|
@@ -63435,7 +63488,7 @@ function createDeleteMemoryTool(memoryExecute, opts) {
|
|
|
63435
63488
|
|
|
63436
63489
|
// src/agents/utility/memory-domain-knowledge.ts
|
|
63437
63490
|
var DOMAIN_LOADERS = {
|
|
63438
|
-
newrelic: async () => (await import("./domain-knowledge-
|
|
63491
|
+
newrelic: async () => (await import("./domain-knowledge-KF3XTKCK.js")).NR_DOMAIN_KNOWLEDGE,
|
|
63439
63492
|
gcp: async () => (await import("./domain-knowledge-HC2HKQB3.js")).GCP_DOMAIN_KNOWLEDGE,
|
|
63440
63493
|
posthog: async () => (await import("./domain-knowledge-RET7XGI5.js")).POSTHOG_DOMAIN_KNOWLEDGE
|
|
63441
63494
|
};
|
|
@@ -63449,7 +63502,7 @@ async function getDomainKnowledge(providerType) {
|
|
|
63449
63502
|
var SYSTEM_PROMPT = `You are a Memory Manager. Review completed sessions and extract lessons from FAILURES and STRUGGLE PATTERNS.
|
|
63450
63503
|
|
|
63451
63504
|
## MANDATORY RULE
|
|
63452
|
-
If the session contains ANY failed queries, you MUST address each failure \u2014 either create_memory if no similar memory exists, or update_memory if an existing memory covers the same topic but could be improved. Every failure MUST result in a tool call
|
|
63505
|
+
If the session contains ANY failed queries, you MUST address each failure \u2014 either create_memory if no similar memory exists, or update_memory if an existing memory covers the same topic but could be improved. Every failure MUST result in a tool call, with ONE exception: transient infrastructure failures (timeout, rate limit, 5xx/server error, network blip) teach nothing about the query language \u2014 for those, state you are skipping them and why instead of saving a memory. A false lesson is worse than none, because memories override future instructions.
|
|
63453
63506
|
|
|
63454
63507
|
## Purpose of memories
|
|
63455
63508
|
Memories capture corrections from real failures and discoveries in the user's specific environment. Each user's system has unique event types, field names, and naming conventions that differ from generic documentation. When the agent tries something and it fails or struggles, the correction is extremely valuable for future sessions.
|
|
@@ -63479,6 +63532,7 @@ If the agent failed then corrected itself, capture the MISTAKE \u2192 CORRECTION
|
|
|
63479
63532
|
If the agent failed but never found a correction, still save the mistake: "Don't use [wrong syntax/field] in NRQL"
|
|
63480
63533
|
|
|
63481
63534
|
## When NOT to save
|
|
63535
|
+
- Transient failures \u2014 timeouts, rate limits, 5xx/server errors, network blips. Not query-language lessons; saving them poisons future sessions.
|
|
63482
63536
|
- General best practices that aren't tied to a specific failure or struggle
|
|
63483
63537
|
- Successful patterns that didn't involve a prior failure or struggle
|
|
63484
63538
|
- User-specific data (IDs, account names, endpoints)
|
|
@@ -63545,18 +63599,18 @@ ${domainKnowledge}
|
|
|
63545
63599
|
` : "";
|
|
63546
63600
|
let tailInstruction;
|
|
63547
63601
|
if (failures.length > 0) {
|
|
63548
|
-
tailInstruction = `This session had ${failures.length} failed queries. You MUST address each failure with create_memory or update_memory \u2014
|
|
63602
|
+
tailInstruction = `This session had ${failures.length} failed queries. You MUST address each failure with create_memory or update_memory \u2014 the only exception is transient infrastructure failures, which you skip with a stated reason.`;
|
|
63549
63603
|
if (emptyCount > 0) tailInstruction += ` Additionally, ${emptyCount} queries returned empty results \u2014 review the session for struggle patterns.`;
|
|
63550
63604
|
} else if (emptyCount > 0) {
|
|
63551
63605
|
tailInstruction = `This session had no errors but ${emptyCount} queries returned empty results. Review the full session timeline for struggle patterns \u2014 repeated attempts, name variations, trial-and-error discovery. If there is a generalized learning, save it. If results were legitimately empty, respond with "No changes needed."`;
|
|
63552
63606
|
} else {
|
|
63553
63607
|
tailInstruction = `If the session was clean, respond with "No changes needed." and make no tool calls.`;
|
|
63554
63608
|
}
|
|
63555
|
-
const failuresSection = failures.length > 0 ? `##
|
|
63609
|
+
const failuresSection = failures.length > 0 ? `## FAILURES DETECTED (${failures.length}) \u2014 each MUST be addressed
|
|
63556
63610
|
${failures.map((f) => `- Query #${f.idx}: \`${f.query}\`
|
|
63557
63611
|
Error: ${f.error}`).join("\n")}
|
|
63558
63612
|
|
|
63559
|
-
For each failure above, call create_memory (or update_memory if a similar memory already exists).
|
|
63613
|
+
For each failure above, call create_memory (or update_memory if a similar memory already exists), unless it is a transient infrastructure failure \u2014 then say so and skip it.
|
|
63560
63614
|
|
|
63561
63615
|
` : "";
|
|
63562
63616
|
const prompt = `Review this completed ${providerType} session and decide what to remember.
|
|
@@ -63833,6 +63887,8 @@ ${DETECTIVE_MINDSET}
|
|
|
63833
63887
|
|
|
63834
63888
|
${EVIDENCE_GROUNDING}
|
|
63835
63889
|
|
|
63890
|
+
${ROOT_CAUSE_DISCIPLINE}
|
|
63891
|
+
|
|
63836
63892
|
${EXECUTION_DISCIPLINE}
|
|
63837
63893
|
|
|
63838
63894
|
${providerFragments.join("\n\n---\n\n")}
|
|
@@ -63842,7 +63898,7 @@ ${buildAnalysisSection(maxSteps)}`;
|
|
|
63842
63898
|
function buildRules(opts) {
|
|
63843
63899
|
const rules = [
|
|
63844
63900
|
`1. **ONE tool call per step.** After each tool result, write a brief summary, then make the next call.`,
|
|
63845
|
-
`2. **Empty results
|
|
63901
|
+
`2. **Empty results: suspect the query first, then prove absence.** Check field name, case, quoting, and time range; fix and retry differently. If a deliberately broadened probe (wider window, fewer filters) is also empty, the absence IS the finding \u2014 report it. Never keep reshaping the same query hoping data appears.`,
|
|
63846
63902
|
`3. **NEVER repeat a failed query.** Read the error, fix the cause. Same error twice \u2192 completely different approach.`,
|
|
63847
63903
|
`4. **Use discovered identifiers exactly.** If the actual name differs from the task, use the exact discovered value.`,
|
|
63848
63904
|
`5. You MUST write a non-empty text response when done \u2014 the user sees your text as the analysis.`,
|
|
@@ -63880,12 +63936,25 @@ Your only sources of truth are the literal text of tool results from this sessio
|
|
|
63880
63936
|
|
|
63881
63937
|
1. **Field names and values are opaque labels.** Never translate or assign meaning to a field name, enum value, code, or flag beyond its literal text \u2014 systems attach internal meanings you cannot know. Report the raw value; if its meaning matters and is undocumented, say so.
|
|
63882
63938
|
2. **Absence requires an empty probe.** Only claim something is missing, absent, or "not on file" if a query that would have returned it came back empty. Not having looked is not evidence of absence.
|
|
63883
|
-
3. **Separate facts, deductions, and gaps.** Facts restate query results. Deductions must follow from stated facts alone \u2014 present them as deductions and name the supporting results; correlation across results is not causation. Gaps are reported as "the data does not show X" \u2014 never filled with a plausible story
|
|
63939
|
+
3. **Separate facts, deductions, and gaps.** Facts restate query results. Deductions must follow from stated facts alone \u2014 present them as deductions and name the supporting results; correlation across results is not causation. Gaps are reported as "the data does not show X" \u2014 never filled with a plausible story.
|
|
63940
|
+
4. **Exact values only.** Every number, identifier, timestamp, and quoted error message in your response must appear literally in a tool result. Values you compute from results must be labeled as computed, with their inputs shown. A name you inferred (service, field, event) must be confirmed by a query before it appears in a finding.
|
|
63941
|
+
5. **Scope claims to what you queried.** "No errors" means "no errors matching my filter in my window" \u2014 state the window. Never generalize a claim beyond the time range, filter, or service actually queried.
|
|
63942
|
+
6. **Label confidence.** State each conclusion as confirmed (a result directly shows it), likely (converging evidence, no direct proof), or unverified (plausible, untested). Only a query result upgrades a claim \u2014 more prose does not. Never present likely or unverified as confirmed.`;
|
|
63943
|
+
var ROOT_CAUSE_DISCIPLINE = `## Root-Cause Discipline
|
|
63944
|
+
|
|
63945
|
+
For "why is X happening" investigations; skip for simple lookups. Steps 1-2 are usually a single time-bucketed query; steps 3-6 are reasoning applied to results you already have \u2014 they cost thought, not extra steps.
|
|
63946
|
+
|
|
63947
|
+
1. **Verify the symptom before explaining it.** The user's description is a claim, not a fact. Your first query confirms the problem actually appears in the data \u2014 right service, right window, roughly the reported magnitude. If it doesn't, report exactly that (with the probe you ran) instead of hunting for causes of something the data does not show.
|
|
63948
|
+
2. **Anchor the timeline.** Establish when the symptom started with a time-bucketed query. A cause must precede the onset \u2014 anything that began after it is a consequence or a coincidence. Ask what changed at onset: deployment, config, traffic shape, a dependency's errors.
|
|
63949
|
+
3. **Name the hypothesis each query tests.** Prefer queries that could DISPROVE it \u2014 a query that can only agree with you proves nothing. One matching correlation is never, by itself, a root cause.
|
|
63950
|
+
4. **Follow the chain to the earliest anomaly.** Timeouts, retries, and 5xx responses are usually symptoms. Keep asking "what made THAT happen" until you reach the earliest anomalous signal visible in the data. If the chain leaves the data you can query (application code, third-party internals), that boundary itself is the finding \u2014 never bridge it with a plausible story.
|
|
63951
|
+
5. **Rule out the strongest alternative.** Before declaring a root cause, name the best competing explanation and the evidence that eliminates it. If you cannot eliminate it, present both candidates and what distinguishes them.
|
|
63952
|
+
6. **Check magnitudes against a baseline.** Compare to the same window a day or week earlier before calling anything a spike or drop. Keep your own numbers consistent \u2014 if two of your results disagree (sampling, different windows), reconcile the disagreement before building on either.`;
|
|
63884
63953
|
var NO_FIXES_RULE = `**NEVER suggest fixes, remediation, next steps, or actions.** Forbidden phrasings include: "consider," "you should," "try," "might want to," "recommend," "could help," "suggests [action]," "would resolve," "to fix this." Any sentence about what to DO about the problem is forbidden, regardless of phrasing. Your job ends at "here is what happened and the evidence." The developer decides what to do.`;
|
|
63885
63954
|
var EXECUTION_DISCIPLINE = `## Execution Discipline
|
|
63886
63955
|
|
|
63887
63956
|
For multi-step investigations:
|
|
63888
|
-
1. **Step N: [Goal]** \u2014 state
|
|
63957
|
+
1. **Step N: [Goal]** \u2014 state the hypothesis this tests or the gap it fills
|
|
63889
63958
|
2. **Tool call** \u2192 ONE query
|
|
63890
63959
|
3. **\u2192 Found:** [data] **\u2192 So what:** [only what this data supports \u2014 if it needs an assumption, it's a gap, not a finding]
|
|
63891
63960
|
4. **\u2192 Can I answer now?** \u2014 If YES: respond. If NO: state what's missing.
|
|
@@ -63906,7 +63975,7 @@ function analysisBlock() {
|
|
|
63906
63975
|
- Do not start writing until you have a clear chain and a concrete list of visuals to run.
|
|
63907
63976
|
2. ${markerStep}
|
|
63908
63977
|
3. **Visual-first narrative.** Walk through what happened and back EVERY substantive finding with a tool call that displays the supporting data (chart or table in the UI). Weave tool calls between narrative paragraphs \u2014 do not cluster them all at the top or bottom. Short connecting text explains each visual; the visuals carry the evidence.
|
|
63909
|
-
4. **End with a concise conclusion** \u2014 the root cause, or the specific gap that prevents naming one, phrased as a deduction from the visuals above.
|
|
63978
|
+
4. **End with a concise conclusion** \u2014 the root cause with its confidence label (confirmed / likely / unverified), or the specific gap that prevents naming one, phrased as a deduction from the visuals above. If the conclusion is not confirmed, name the single piece of evidence that would settle it.
|
|
63910
63979
|
|
|
63911
63980
|
**Rules:**
|
|
63912
63981
|
- **Tool calls are mandatory, not optional.** Every substantive claim needs a tool call showing the data. Narrative without visuals is not acceptable. Cite investigation steps inline with \`[step N]\` only when it adds auditability \u2014 do not substitute citations for visuals.
|
|
@@ -63927,7 +63996,7 @@ You have a maximum of ${maxSteps} steps. Most investigations should finish in 3-
|
|
|
63927
63996
|
|
|
63928
63997
|
## Final Reminders
|
|
63929
63998
|
- **Tool calls are the evidence.** Every substantive claim in your response needs a visual \u2014 even if the same query already ran during investigation, re-run it here. The analysis section must be self-contained.
|
|
63930
|
-
- **Stay Grounded in Evidence:** every claim maps to a specific tool result; values mean only what their literal text says; absence claims need an empty probe; gaps are stated as "the data does not show". No fixes.`;
|
|
63999
|
+
- **Stay Grounded in Evidence:** every claim maps to a specific tool result; values mean only what their literal text says; absence claims need an empty probe; claims stay scoped to the window actually queried; conclusions carry confidence labels; gaps are stated as "the data does not show". No fixes.`;
|
|
63931
64000
|
}
|
|
63932
64001
|
|
|
63933
64002
|
// src/lib/prompt-builder.ts
|
|
@@ -63958,6 +64027,8 @@ ${DETECTIVE_MINDSET}
|
|
|
63958
64027
|
|
|
63959
64028
|
${EVIDENCE_GROUNDING}
|
|
63960
64029
|
|
|
64030
|
+
${ROOT_CAUSE_DISCIPLINE}
|
|
64031
|
+
|
|
63961
64032
|
${config2.insideOutDebugging}
|
|
63962
64033
|
|
|
63963
64034
|
${EXECUTION_DISCIPLINE}
|
|
@@ -65598,13 +65669,13 @@ var HttpMCPTransport = class {
|
|
|
65598
65669
|
);
|
|
65599
65670
|
return;
|
|
65600
65671
|
}
|
|
65601
|
-
const
|
|
65672
|
+
const delay4 = this.getNextReconnectionDelay(this.inboundReconnectAttempts);
|
|
65602
65673
|
this.inboundReconnectAttempts += 1;
|
|
65603
65674
|
setTimeout(async () => {
|
|
65604
65675
|
var _a45;
|
|
65605
65676
|
if ((_a45 = this.abortController) == null ? void 0 : _a45.signal.aborted) return;
|
|
65606
65677
|
await this.openInboundSse(false, this.lastInboundEventId);
|
|
65607
|
-
},
|
|
65678
|
+
}, delay4);
|
|
65608
65679
|
}
|
|
65609
65680
|
// Open optional inbound SSE stream; best-effort and resumable
|
|
65610
65681
|
async openInboundSse(triedAuth = false, resumeToken) {
|
|
@@ -73994,7 +74065,7 @@ Only after reviewing all memories, perform any needed updates or deletes.
|
|
|
73994
74065
|
- **Default to KEEP.** Only delete when you are 100% certain the memory is harmful or an exact duplicate.
|
|
73995
74066
|
- Merge duplicates: UPDATE the better one, DELETE the other.
|
|
73996
74067
|
- Rewrite vague notes to be specific and actionable (max 15 words).
|
|
73997
|
-
- Delete memories that teach
|
|
74068
|
+
- Delete memories that teach syntax invalid for THIS provider's query language \u2014 judge against the provider domain knowledge in the prompt, never against another provider's dialect (e.g. GROUP BY is invalid NRQL but valid HogQL).`;
|
|
73998
74069
|
async function runMemoryOptimizer(db2, toolName) {
|
|
73999
74070
|
const memories = db2.select().from(toolMemories).where(eq(toolMemories.toolName, toolName)).all();
|
|
74000
74071
|
const emptyStats = { kept: 0, updated: 0, deleted: 0 };
|
|
@@ -74606,8 +74677,8 @@ var updateRouter = router({
|
|
|
74606
74677
|
currentVersion: status.currentVersion,
|
|
74607
74678
|
latestVersion: status.latestVersion,
|
|
74608
74679
|
method: status.method,
|
|
74609
|
-
//
|
|
74610
|
-
canSelfUpdate: status.method
|
|
74680
|
+
// Global and npx installs upgrade in place; only source checkouts can't.
|
|
74681
|
+
canSelfUpdate: status.method !== "dev"
|
|
74611
74682
|
};
|
|
74612
74683
|
}),
|
|
74613
74684
|
// Upgrade a global install in place, then trigger a graceful restart so the
|
|
@@ -75281,6 +75352,8 @@ When the user's question spans multiple providers, query each relevant provider
|
|
|
75281
75352
|
const fragments = collected.promptFragments ?? [];
|
|
75282
75353
|
systemPrompt = fragments.length > 0 ? `${basePrompt}
|
|
75283
75354
|
|
|
75355
|
+
${EVIDENCE_GROUNDING}
|
|
75356
|
+
|
|
75284
75357
|
${fragments.join("\n\n")}` : `${basePrompt}
|
|
75285
75358
|
|
|
75286
75359
|
No observability providers are currently configured. If the user asks about observability data, let them know they can connect providers in the Settings page.`;
|
|
@@ -75735,10 +75808,10 @@ If a tool call fails, retry with a corrected approach. If you fail the same tool
|
|
|
75735
75808
|
|
|
75736
75809
|
## Chart Type Selection
|
|
75737
75810
|
- "auto" \u2014 let the frontend auto-detect based on query shape
|
|
75738
|
-
- "timeseries" \u2014 for
|
|
75739
|
-
- "table" \u2014 for
|
|
75811
|
+
- "timeseries" \u2014 for time-bucketed queries (NRQL TIMESERIES, HogQL GROUP BY time bucket) \u2014 line charts
|
|
75812
|
+
- "table" \u2014 for grouped/top-N results without a time axis (NRQL FACET, SQL GROUP BY)
|
|
75740
75813
|
- "scalar" \u2014 for single-value aggregations
|
|
75741
|
-
- "histogram" \u2014 for histogram()
|
|
75814
|
+
- "histogram" \u2014 for distribution queries (e.g. NRQL histogram())
|
|
75742
75815
|
|
|
75743
75816
|
## Widget Sizing
|
|
75744
75817
|
The dashboard uses a ${CONFIG.gridColumns}\xD7${CONFIG.gridColumns} grid (${CONFIG.gridColumns} columns, ${CONFIG.gridColumns} rows fill the viewport). Both axes are responsive to screen size.
|
|
@@ -76217,6 +76290,9 @@ The condition is a JS expression evaluated against the query \`result\` array. E
|
|
|
76217
76290
|
- \`result[0].average > 2\` \u2014 alert when average exceeds 2 seconds
|
|
76218
76291
|
- \`result[0].errorRate > 0.05\` \u2014 alert when error rate exceeds 5%
|
|
76219
76292
|
|
|
76293
|
+
## Threshold Grounding
|
|
76294
|
+
Never invent a threshold. Unless the user gave an explicit number, run the monitor's query over recent data FIRST and pick the threshold relative to the observed values. When proposing a condition, state the observed baseline it is based on (e.g. "normal is 5-10/min, alerting above 50"). A threshold chosen without looking at the data either never fires or fires constantly.
|
|
76295
|
+
|
|
76220
76296
|
## Frequency Recommendations
|
|
76221
76297
|
- 30s \u2014 critical real-time checks
|
|
76222
76298
|
- 60s \u2014 standard monitoring (default)
|
package/packages/web/dist/assets/{SearchableSelect-CN8LoaWs.js → SearchableSelect-VoTpUxSB.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as q,r as s,j as r}from"./index-
|
|
1
|
+
import{a as q,r as s,j as r}from"./index-BsLO7f3R.js";var P=q();function $(c){const n=c?`tracer:starred:${c}`:null,[i,S]=s.useState(()=>{if(!n)return new Set;try{const a=localStorage.getItem(n);return a?new Set(JSON.parse(a)):new Set}catch{return new Set}});return[i,a=>{S(u=>{const t=new Set(u);return t.has(a)?t.delete(a):t.add(a),n&&localStorage.setItem(n,JSON.stringify([...t])),t})}]}function I({options:c,value:n,onChange:i,placeholder:S="Select...",storageKey:v,fitContent:a,disabled:u}){const[t,l]=s.useState(!1),[w,y]=s.useState(""),f=s.useRef(null),j=s.useRef(null),N=s.useRef(null),g=s.useRef(null),[x,C]=$(v),[m,L]=s.useState({top:0,left:0,minWidth:0});s.useEffect(()=>{if(!t)return;const e=d=>{f.current?.contains(d.target)||j.current?.contains(d.target)||l(!1)};return document.addEventListener("mousedown",e),()=>document.removeEventListener("mousedown",e)},[t]);const R=s.useCallback(()=>{if(!f.current)return;const e=f.current.getBoundingClientRect();L({top:e.bottom+4,left:e.left,minWidth:e.width})},[]);s.useEffect(()=>{t&&(R(),y(""),requestAnimationFrame(()=>N.current?.focus()))},[t,R]);const h=c.find(e=>e.value===n),p=s.useMemo(()=>{const e=w.toLowerCase();return[...e?c.filter(o=>o.label.toLowerCase().includes(e)||o.value.toLowerCase().includes(e)):c].sort((o,b)=>{const k=x.has(o.value)?0:1,E=x.has(b.value)?0:1;return k!==E?k-E:o.label.localeCompare(b.label)})},[c,w,x]);s.useEffect(()=>{if(t&&n&&g.current){const e=g.current.querySelector(`[data-value="${CSS.escape(n)}"]`);e&&e.scrollIntoView({block:"nearest"})}},[t,n]);const W=t?P.createPortal(r.jsxs("div",{ref:j,className:"fixed z-[100] bg-white border border-[#d4d2cd] rounded shadow-lg",style:{top:m.top,left:m.left,minWidth:m.minWidth,width:a?"max-content":m.minWidth},children:[r.jsx("div",{className:"p-1.5 border-b border-[#e8e6e1]",children:r.jsx("input",{ref:N,type:"text",value:w,onChange:e=>y(e.target.value),placeholder:"Search...",className:"w-full px-2 py-1.5 text-xs text-[#2c2c2c] font-sans bg-[#f5f4f0] border border-[#e8e6e1] rounded focus:outline-none focus:border-[#2b5ea7] placeholder:text-[#9c9890]",onKeyDown:e=>{e.key==="Escape"&&l(!1),e.key==="Enter"&&p.length>0&&(i(p[0].value),l(!1))}})}),r.jsx("div",{ref:g,className:"max-h-[280px] overflow-y-auto",children:p.length===0?r.jsx("div",{className:"px-3 py-3 text-xs text-[#9c9890] text-center",children:"No projects found"}):p.map(e=>{const d=e.value===n,o=x.has(e.value);return r.jsxs("div",{"data-value":e.value,className:`flex items-center gap-1.5 px-2 py-1.5 text-xs font-sans cursor-pointer transition-colors ${d?"bg-[#2b5ea7]/10 text-[#2b5ea7]":"text-[#2c2c2c] hover:bg-[#f5f4f0]"}`,onClick:()=>{i(e.value),l(!1)},children:[r.jsx("button",{type:"button",onClick:b=>{b.stopPropagation(),C(e.value)},className:`shrink-0 w-4 h-4 flex items-center justify-center text-[10px] transition-colors ${o?"text-[#d4a017]":"text-[#d4d2cd] hover:text-[#9c9890]"}`,title:o?"Unstar":"Star to pin to top",children:o?"★":"☆"}),r.jsx("span",{className:a?"whitespace-nowrap":"truncate flex-1",children:e.label})]},e.value)})})]}),document.body):null;return r.jsxs(r.Fragment,{children:[r.jsxs("button",{ref:f,type:"button",onClick:()=>!u&&l(!t),disabled:u,className:"w-full bg-white border border-[#d4d2cd] rounded px-3 py-2 text-xs text-[#2c2c2c] font-sans text-left flex items-center justify-between focus:outline-none focus:border-[#2b5ea7] hover:border-[#b0ada6] transition-colors disabled:opacity-50 disabled:cursor-not-allowed",children:[r.jsx("span",{className:h?"text-[#2c2c2c] truncate":"text-[#9c9890]",children:h?h.displayLabel??h.label:S}),r.jsx("span",{className:"text-[#9c9890] text-[10px] ml-2 shrink-0 transition-transform duration-200",style:{transform:t?"rotate(180deg)":"rotate(0deg)"},children:"▾"})]}),W]})}export{I as S,P as r,$ as u};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as m,r as f,j as e,S as I,c as _,b as a,C as E,u as X,W as V,A as ee,d as de,g as ue,m as O,p as G,e as se,M as me}from"./index-CDazY975.js";import{S as te}from"./SearchableSelect-CN8LoaWs.js";function W({type:s,label:t,note:l}){const i=m.useUtils(),{data:o,isLoading:x}=m.settings.getApiKey.useQuery(s),p=m.settings.saveApiKey.useMutation({onSuccess:()=>i.settings.getApiKey.invalidate(s)}),d=m.settings.removeApiKey.useMutation({onSuccess:()=>i.settings.getApiKey.invalidate(s)}),[h,r]=f.useState(!1),[g,u]=f.useState(""),[v,b]=f.useState(!1);async function C(){await p.mutateAsync({type:s,apiKey:g}),u(""),r(!1)}async function c(){await d.mutateAsync(s),r(!1),b(!1)}return x?e.jsx("div",{className:"px-4 py-3",children:e.jsx(I,{size:"sm"})}):e.jsxs("div",{className:"px-4 py-3",children:[e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx("span",{className:"text-sm font-medium w-24 shrink-0",children:t}),e.jsx("span",{className:a.maskedKey+" flex-1 truncate",style:o?{color:_.success}:void 0,children:o?o.maskedApiKey:"Not configured"}),!h&&e.jsx("button",{onClick:()=>{u(""),r(!0)},className:a.secondaryBtn+" text-xs px-3 py-1",children:o?"Edit":"Add"})]}),h&&e.jsxs("div",{className:"mt-3 pt-3 border-t border-[#e8e6e1] space-y-2",children:[l&&e.jsx("div",{children:l}),e.jsx("input",{type:g?"password":"text",value:g,onChange:N=>u(N.target.value),placeholder:o?.maskedApiKey??"Enter API key",className:a.input}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{onClick:C,disabled:!g||p.isPending,className:a.primaryBtn+" text-xs px-3 py-1",children:p.isPending?e.jsxs("span",{className:"flex items-center gap-2",children:[e.jsx(I,{size:"sm"})," Saving..."]}):"Save"}),e.jsx("button",{onClick:()=>r(!1),disabled:p.isPending,className:a.secondaryBtn+" text-xs px-3 py-1",children:"Cancel"}),o&&e.jsx("button",{onClick:()=>b(!0),disabled:d.isPending,className:a.dangerBtn+" text-xs px-3 py-1",children:"Remove"})]})]}),e.jsx(E,{open:v,title:"Remove API key",message:`Remove the ${t} API key?`,confirmLabel:"Remove",onConfirm:c,onCancel:()=>b(!1)})]})}function J({checked:s,onChange:t,disabled:l,"aria-label":i}){return e.jsx("button",{type:"button",role:"switch","aria-checked":s,"aria-label":i,disabled:l,onClick:()=>t(!s),className:`relative inline-flex h-5 w-9 items-center rounded-full transition-colors ${s?"bg-[#2b5ea7]":"bg-[#d4d2cd]"} ${l?"opacity-50 cursor-not-allowed":"cursor-pointer"}`,children:e.jsx("span",{className:`inline-block h-3.5 w-3.5 rounded-full bg-white transition-transform ${s?"translate-x-[18px]":"translate-x-[3px]"}`})})}function H({status:s,label:t}){return e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:`inline-block h-2 w-2 rounded-full ${a.statusDot[s]}`}),t&&e.jsx("span",{className:a.statusLabel,children:t})]})}function xe(){const s=m.useUtils(),{data:t,isLoading:l}=m.settings.getVertexConfig.useQuery(),i=X(),o=!!t,x=i.data,p=x?.ok??!1,d=o&&p,h=()=>{s.settings.getVertexConfig.invalidate(),s.provider.listVertexModels.invalidate()},r=m.settings.saveVertexConfig.useMutation({onSuccess:h}),g=m.settings.removeVertexConfig.useMutation({onSuccess:h}),u=r.isPending||g.isPending,[v,b]=f.useState(!1),{data:C,isLoading:c}=m.provider.listGcpProjects.useQuery(void 0,{staleTime:V.updateCheckStaleTimeMs,enabled:d}),N=f.useMemo(()=>(C??[]).map(y=>({value:y.projectId,label:y.name?`${y.name} (${y.projectId})`:y.projectId,displayLabel:y.name||y.projectId})),[C]);function S(y){y?r.mutate({}):b(!0)}function k(){g.mutate(),b(!1)}function j(y){y!==t?.projectId&&r.mutate({projectId:y})}return l?e.jsx("div",{className:"px-4 py-3",children:e.jsx(I,{size:"sm"})}):e.jsxs("div",{className:"px-4 py-3",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(J,{checked:o,onChange:S,disabled:u,"aria-label":"Enable Vertex AI"}),e.jsx("span",{className:"text-sm font-medium",children:"Vertex AI"}),o?e.jsx(H,{status:d?"connected":"disconnected"}):e.jsx("span",{className:"text-xs opacity-40",children:"Not configured"})]}),o&&e.jsx("div",{className:"mt-3 pt-3 border-t border-[#e8e6e1]",children:i.isLoading?e.jsxs("div",{className:"flex items-center gap-2 text-xs text-[#666666]",children:[e.jsx(I,{size:"sm"})," Checking authentication…"]}):p?e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("span",{className:"text-xs text-[#666666] whitespace-nowrap w-14",children:"Project"}),e.jsx("div",{className:"flex-1",children:e.jsx(te,{options:N,value:t?.projectId??"",onChange:j,placeholder:c?"Loading...":"Select project...",storageKey:"gcp-projectId",fitContent:!0,disabled:c||u})})]}),e.jsx(pe,{value:t?.location??"global",onCommit:y=>{const P=y.trim()||"global";P!==t?.location&&r.mutate({location:P})},disabled:u})]}):e.jsx("p",{className:a.warnText,children:x&&!x.ok?x.message:"Not authenticated. Run: gcloud auth application-default login"})}),e.jsx(E,{open:v,title:"Disable Vertex AI",message:"Disable Vertex AI? Your project selection will be removed.",confirmLabel:"Disable",onConfirm:k,onCancel:()=>b(!1)})]})}function pe({value:s,onCommit:t,disabled:l}){const[i,o]=f.useState(s);return f.useEffect(()=>o(s),[s]),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("span",{className:"text-xs text-[#666666] whitespace-nowrap w-14",children:"Location"}),e.jsx("input",{type:"text",value:i,onChange:x=>o(x.target.value),onBlur:()=>t(i),onKeyDown:x=>{x.key==="Enter"&&x.currentTarget.blur()},placeholder:"global",disabled:l,className:a.input})]})}function ge({configuredProviders:s}){return e.jsx("div",{className:"border-t border-[#e8e6e1]",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{children:e.jsxs("tr",{className:a.tableHeaderRow,children:[e.jsx("th",{className:a.tableHeaderCell+" text-xs py-2",children:"Model"}),e.jsx("th",{className:a.tableHeaderCell+" text-xs py-2",children:"Provider"}),e.jsx("th",{className:a.tableHeaderCell+" text-xs py-2 text-right",children:"Input ($/M)"}),e.jsx("th",{className:a.tableHeaderCell+" text-xs py-2 text-right",children:"Output ($/M)"})]})}),e.jsx("tbody",{className:"divide-y divide-[#e8e6e1]",children:ee.map(t=>{const l=s.has(t.provider);return e.jsxs("tr",{style:l?{color:_.success}:{color:_.inkFaint},children:[e.jsx("td",{className:"px-4 py-2 font-mono text-xs",children:t.modelId}),e.jsx("td",{className:"px-4 py-2 capitalize",children:t.provider}),e.jsxs("td",{className:"px-4 py-2 text-right font-mono text-xs",children:["$",t.inputPrice.toFixed(2)]}),e.jsxs("td",{className:"px-4 py-2 text-right font-mono text-xs",children:["$",t.outputPrice.toFixed(2)]})]},t.modelId)})})]})})}function $({children:s}){return e.jsx("div",{className:"text-xs leading-relaxed rounded border border-[#d4d2cd] bg-[#f5f4f1] p-3 space-y-2",children:s})}const Z="underline break-all text-[#0052cc]",he=e.jsxs($,{children:[e.jsxs("div",{children:["Create a Gemini API key at:",e.jsx("br",{}),e.jsx("a",{href:"https://aistudio.google.com/api-keys",target:"_blank",rel:"noopener noreferrer",className:Z,children:"https://aistudio.google.com/api-keys"})]}),e.jsx("div",{className:"opacity-80",children:"This key powers the Gemini models Tracer uses to run chats and analyze your data — it is the model provider, not a data source. Tracer sends your prompts and the data it has already fetched to Google's Gemini API for inference; it grants no access back into your Google account."})]});function fe(){const[s,t]=f.useState(!1),l=de();return e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"max-w-lg bg-white border border-[#d4d2cd] rounded divide-y divide-[#e8e6e1] overflow-hidden",children:[e.jsx(W,{type:"anthropic",label:"Anthropic"}),e.jsx(W,{type:"google",label:"Google AI",note:he}),e.jsx(xe,{})]}),e.jsxs("div",{className:"bg-white border border-[#d4d2cd] rounded overflow-hidden",children:[e.jsxs("button",{onClick:()=>t(!s),className:"w-full flex items-center justify-between px-4 py-3 text-sm text-[#666666] hover:bg-[#f5f4f0] transition-colors font-sans",children:[e.jsx("span",{className:"font-medium",children:"Model Pricing"}),e.jsx("span",{className:"text-xs transition-transform duration-200",style:{transform:s?"rotate(180deg)":"rotate(0deg)"},children:"▾"})]}),s&&e.jsx(ge,{configuredProviders:l})]})]})}function ne({value:s,models:t,onChange:l,loading:i,disabled:o,label:x="Model"}){const p=ue(t),d=O(s),r=!t.some(u=>O(u)===d)&&!i;function g(u){const v=u.indexOf(":");l({provider:u.slice(0,v),modelId:u.slice(v+1)})}return e.jsxs("div",{className:"flex items-start gap-3 mt-3 pt-3 border-t border-[#d4d2cd]",children:[e.jsx("span",{className:"text-xs text-[#666666] whitespace-nowrap w-14 mt-2",children:x}),e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"shrink-0 inline-flex items-center rounded px-1.5 py-0.5 text-[10px] font-medium bg-[#f0eee9] text-[#666666] border border-[#d4d2cd]",children:G(s.provider)}),e.jsxs("div",{className:"relative flex-1",children:[e.jsxs("select",{value:d,onChange:u=>g(u.target.value),disabled:o,className:"w-full appearance-none bg-white border border-[#d4d2cd] rounded px-3 py-2 pr-7 text-xs text-[#2c2c2c] focus:outline-none focus:border-[#2b5ea7] font-sans disabled:opacity-50 disabled:cursor-not-allowed",children:[r&&e.jsx("optgroup",{label:"Unavailable",children:e.jsxs("option",{value:d,children:[G(s.provider)," · ",s.modelId]})}),p.map(u=>e.jsx("optgroup",{label:u.label,children:u.models.map(v=>e.jsx("option",{value:O(v),children:v.modelId},O(v)))},u.provider))]}),e.jsx("span",{className:"pointer-events-none absolute right-2 top-1/2 -translate-y-1/2 text-[#9c9890] text-[10px]",children:"▾"})]})]}),r&&e.jsxs("p",{className:a.warnText+" mt-1.5",children:[G(s.provider)," · ",s.modelId," isn’t available. Configure its provider or pick another model."]})]})]})}const je=ee[0];function ve({providerType:s}){const t=m.useUtils(),{data:l,isLoading:i}=m.settings.getSubAgentModel.useQuery(s),o=m.settings.saveSubAgentModel.useMutation({onSuccess:()=>t.settings.getSubAgentModel.invalidate(s)}),{models:x,isLoading:p}=se();if(i)return null;const d=l??je;return e.jsx(ne,{value:d,models:x,loading:p,disabled:o.isPending,onChange:h=>o.mutate({providerType:s,model:{provider:h.provider,modelId:h.modelId}})})}function be({existingConfig:s}){const t=m.useUtils(),l=X(),{data:i,isLoading:o}=m.provider.listGcpProjects.useQuery(void 0,{staleTime:V.updateCheckStaleTimeMs}),x=m.provider.saveConfig.useMutation({onSuccess:()=>{t.provider.getConfigs.invalidate(),t.provider.list.invalidate()}}),p=f.useMemo(()=>(i??[]).map(r=>({value:r.projectId,label:r.name?`${r.name} (${r.projectId})`:r.projectId,displayLabel:r.name||r.projectId})),[i]),d=s.projectId??"";if(l.data&&!l.data.ok)return null;function h(r){r!==d&&x.mutate({type:"gcp",config:{...s,projectId:r}})}return e.jsxs("div",{className:"flex items-center gap-3 mt-3 pt-3 border-t border-[#d4d2cd]",children:[e.jsx("span",{className:"text-xs text-[#666666] whitespace-nowrap w-14",children:"Project"}),e.jsx("div",{className:"flex-1",children:e.jsx(te,{options:p,value:d,onChange:h,placeholder:o?"Loading...":"Select project...",storageKey:"gcp-projectId",fitContent:!0,disabled:o||x.isPending})})]})}function ye({type:s,label:t,connected:l,configured:i,onConfigure:o,onToggle:x,togglePending:p,toggleError:d,pingError:h,hasConfigFields:r,existingConfig:g}){const u=i||l;return e.jsxs("div",{className:a.settingsCard+" w-80",children:[e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(J,{checked:i,onChange:v=>{v&&r?o():x(v)},disabled:p}),e.jsx("span",{className:"font-medium",children:t}),u?e.jsx(H,{status:l?"connected":"disconnected"}):e.jsx("span",{className:"text-xs opacity-40",children:"Not configured"})]}),e.jsx("button",{onClick:o,className:`${a.secondaryBtn} ${i&&r?"":"invisible"}`,children:"Edit"})]}),u&&e.jsx(ve,{providerType:s}),u&&s==="gcp"&&g&&e.jsx(be,{existingConfig:g}),h&&!l&&e.jsx("p",{className:a.warnText+" mt-2",children:h}),d&&e.jsx("p",{className:a.errorText+" mt-2",children:d})]})}function Y(s,t){return!!s&&!!t&&s===t}function ae({open:s,label:t,configFields:l,formValues:i,onFormChange:o,existingConfig:x,saveResult:p,savePending:d,configured:h,note:r,onSave:g,onClose:u,onRemove:v}){const b=l.some(c=>c.required!==!1&&c.type==="password"&&Y(i[c.key],x?.[c.key])),C=l.some(c=>c.required!==!1&&!i[c.key]);return e.jsxs(me,{open:s,onClose:u,children:[e.jsxs("div",{className:a.dialogTitle+" text-base mb-4",children:["Configure ",t]}),r&&e.jsx("div",{className:"mb-4",children:r}),e.jsx("div",{className:"space-y-3",children:l.map(c=>{const N=c.type==="password"&&Y(i[c.key],x?.[c.key]);return e.jsxs("div",{children:[e.jsxs("label",{className:a.sectionTitle,children:[c.label,c.required===!1&&e.jsx("span",{className:"text-xs opacity-40 ml-1",children:"(optional)"})]}),e.jsx("input",{type:c.type==="password"&&i[c.key]&&!N?"password":"text",value:i[c.key]??"",onChange:S=>o(c.key,S.target.value),onFocus:S=>{N&&S.target.select()},placeholder:`Enter ${c.label.toLowerCase()}`,className:`${a.input} ${N?"!text-[#999] !border-l-2 !border-l-amber-400":""}`})]},c.key)})}),e.jsxs("div",{className:"flex items-center gap-2 mt-4 pt-4 border-t border-[#d4d2cd]",children:[e.jsx("button",{onClick:g,disabled:C||b||d,className:a.primaryBtn,children:d?e.jsxs("span",{className:"flex items-center gap-2",children:[e.jsx(I,{size:"sm"})," Saving..."]}):"Save & Test"}),e.jsx("button",{onClick:u,disabled:d,className:a.secondaryBtn,children:"Cancel"}),h&&e.jsx("button",{onClick:v,disabled:d,className:a.dangerBtn,children:"Remove"})]}),b&&!d&&!p&&e.jsx("p",{className:"mt-2 text-xs text-amber-600",children:"Re-enter highlighted fields to save"}),p&&e.jsx("div",{className:`mt-3 ${p.success?a.successText:a.errorText}`,children:p.success?"Connected successfully":p.error||"Connection failed"})]})}const Ne={newrelic:e.jsxs($,{children:[e.jsxs("div",{children:["Create a ",e.jsx("span",{className:"font-medium",children:"User key"})," at:",e.jsx("br",{}),e.jsx("a",{href:"https://one.newrelic.com/admin-portal/api-keys/home",target:"_blank",rel:"noopener noreferrer",className:Z,children:"https://one.newrelic.com/admin-portal/api-keys/home"}),e.jsx("br",{}),"Your numeric Account ID is shown on the same page."]}),e.jsxs("div",{children:[e.jsx("div",{className:"font-medium",children:"What Tracer can do with it"}),e.jsx("ul",{className:"list-disc ml-4 mt-1 space-y-0.5",children:e.jsxs("li",{children:[e.jsx("span",{className:"font-medium",children:"Run read-only NRQL queries"})," against your account — to inspect metrics, logs, traces, and errors while investigating."]})})]}),e.jsx("div",{className:"opacity-80",children:"It only reads via NRQL. It cannot write, modify, deploy, or delete anything. A New Relic User key inherits your role, so for least privilege use a user scoped to read-only access."})]}),posthog:e.jsxs($,{children:[e.jsxs("div",{children:["Create a ",e.jsx("span",{className:"font-medium",children:"Personal API key"})," in your PostHog instance at:",e.jsx("br",{}),e.jsx("span",{className:"font-mono",children:"/settings/user-api-keys"}),e.jsx("br",{}),"Grant it the single scope ",e.jsx("span",{className:"font-medium",children:"Query → Read"}),". The Project ID is in Settings → Project. Set Host only if you are not on US cloud (e.g.",e.jsx("span",{className:"font-mono",children:" eu.posthog.com"})," or a self-hosted URL)."]}),e.jsxs("div",{children:[e.jsx("div",{className:"font-medium",children:"What Tracer can do with it"}),e.jsx("ul",{className:"list-disc ml-4 mt-1 space-y-0.5",children:e.jsxs("li",{children:[e.jsx("span",{className:"font-medium",children:"Run read-only HogQL queries"})," against the project — to inspect events, persons, and analytics while investigating."]})})]}),e.jsxs("div",{className:"opacity-80",children:["With only the ",e.jsx("span",{className:"font-medium",children:"Query → Read"})," scope it cannot create, modify, or delete anything in PostHog, and it reaches only the project you configure."]})]})};function Ce(s,t){const l={};for(const i of s)l[i.key]=t?.[i.key]??"";return l}function we(){const s=m.useUtils(),{data:t,isLoading:l}=m.provider.list.useQuery(),{data:i,isLoading:o}=m.provider.getConfigs.useQuery(),{data:x,isLoading:p}=m.provider.getRegisteredTypes.useQuery(),{data:d}=m.provider.ping.useQuery(void 0,{staleTime:V.sessionStaleTimeMs,refetchOnMount:"always"}),h=m.provider.saveConfig.useMutation({onSuccess:()=>{s.provider.list.invalidate(),s.provider.getConfigs.invalidate(),s.provider.ping.invalidate()}}),r=m.provider.removeConfig.useMutation({onSuccess:()=>{s.provider.list.invalidate(),s.provider.getConfigs.invalidate(),s.provider.ping.invalidate()}}),[g,u]=f.useState(null),[v,b]=f.useState({}),[C,c]=f.useState(null),[N,S]=f.useState(null),[k,j]=f.useState({});function y(n){const w=i?.find(M=>M.type===n),A=x?.find(M=>M.type===n);b(Ce(A?.configFields??[],w?.config)),c(null),u(n)}function P(){u(null),b({}),c(null)}async function U(n){c(null);try{const w=await h.mutateAsync({type:n,config:v});c(w),w.success&&(u(null),b({}))}catch{c({success:!1,error:"Failed to save configuration"})}}async function F(n,w){if(w){j(A=>{const M={...A};return delete M[n],M});try{const A=await h.mutateAsync({type:n,config:{}});A.success||j(M=>({...M,[n]:A.error??"Connection failed"}))}catch{j(A=>({...A,[n]:"Failed to save configuration"}))}}else S(n)}async function K(n){await r.mutateAsync(n),u(null),b({}),c(null),S(null)}const z=l||o||p,R=x??[];if(z)return e.jsx(I,{size:"lg",centered:!0});const T=g?R.find(n=>n.type===g):null,B=g?i?.find(n=>n.type===g):null;return e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"flex flex-wrap gap-3",children:R.map(({type:n,label:w,configFields:A})=>{const M=t?.find(L=>L.type===n),q=i?.find(L=>L.type===n),oe=!!q,D=d?.find(L=>L.type===n),le=D?D.ok:!!M?.connected,re=A.length>0,ce=D&&!D.ok?D.error:void 0;return e.jsx(ye,{type:n,label:w,connected:le,configured:oe,onConfigure:()=>y(n),onToggle:L=>F(n,L),togglePending:h.isPending||r.isPending,toggleError:k[n],pingError:ce,hasConfigFields:re,existingConfig:q?.config},n)})}),g&&T&&e.jsx(ae,{open:!0,label:T.label,configFields:T.configFields,formValues:v,onFormChange:(n,w)=>b(A=>({...A,[n]:w})),existingConfig:B?.config??null,saveResult:C,savePending:h.isPending,configured:!!B,note:Ne[g],onSave:()=>U(g),onClose:P,onRemove:()=>S(g)}),e.jsx(E,{open:N!==null,title:"Disable provider",message:`Disable ${R.find(n=>n.type===N)?.label??N}?`,confirmLabel:"Disable",onConfirm:()=>{N&&K(N)},onCancel:()=>S(null)})]})}const Se=[{key:"domain",label:"Domain (yourco → yourco.atlassian.net)",type:"text"},{key:"email",label:"Email",type:"text"},{key:"apiToken",label:"API Token",type:"password"}],ke=e.jsxs($,{children:[e.jsxs("div",{children:["Create a token (use the plain ",e.jsx("span",{className:"font-medium",children:"Create API token"}),', not "with scopes") at:',e.jsx("br",{}),e.jsx("a",{href:"https://id.atlassian.com/manage-profile/security/api-tokens",target:"_blank",rel:"noopener noreferrer",className:Z,children:"https://id.atlassian.com/manage-profile/security/api-tokens"})]}),e.jsxs("div",{children:[e.jsx("div",{className:"font-medium",children:"What Tracer can do with it"}),e.jsxs("ul",{className:"list-disc ml-4 mt-1 space-y-0.5",children:[e.jsxs("li",{children:[e.jsx("span",{className:"font-medium",children:"Read an issue"})," — summary, description, status, type, priority, assignee, reporter, labels, components, fix versions, resolution, dates, and its comment thread"]}),e.jsxs("li",{children:[e.jsx("span",{className:"font-medium",children:"Post a comment"})," — plain text, only when you ask"]})]})]}),e.jsx("div",{className:"opacity-80",children:"It cannot edit, transition, delete, bulk-read, or administer anything else. The token uses its account's permissions, so for least privilege point it at a Jira account limited to the projects Tracer should touch."})]});function Ae(){const s=m.useUtils(),{data:t,isLoading:l}=m.integrations.getJira.useQuery(),i=m.integrations.saveJira.useMutation({onSuccess:()=>s.integrations.getJira.invalidate()}),o=m.integrations.removeJira.useMutation({onSuccess:()=>s.integrations.getJira.invalidate()}),[x,p]=f.useState(!1),[d,h]=f.useState({}),[r,g]=f.useState(null),[u,v]=f.useState(!1),b=!!t?.configured,C=t?.config??null;function c(){h({domain:C?.domain??"",email:C?.email??"",apiToken:C?.apiToken??""}),g(null),p(!0)}function N(){p(!1),h({}),g(null)}async function S(){g(null);try{const j=await i.mutateAsync({domain:d.domain??"",email:d.email??"",apiToken:d.apiToken??""});g(j),j.success&&N()}catch{g({success:!1,error:"Failed to save configuration"})}}async function k(){await o.mutateAsync(),v(!1),N()}return l?e.jsx(I,{size:"lg",centered:!0}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"flex flex-wrap gap-3",children:e.jsx("div",{className:a.settingsCard+" w-80",children:e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(J,{checked:b,onChange:j=>{j?c():v(!0)},disabled:i.isPending||o.isPending}),e.jsx("span",{className:"font-medium",children:"Jira"}),b?e.jsx(H,{status:"connected"}):e.jsx("span",{className:"text-xs opacity-40",children:"Not configured"})]}),e.jsx("button",{onClick:c,className:`${a.secondaryBtn} ${b?"":"invisible"}`,children:"Edit"})]})})}),x&&e.jsx(ae,{open:!0,label:"Jira",configFields:Se,formValues:d,onFormChange:(j,y)=>h(P=>({...P,[j]:y})),existingConfig:C,saveResult:r,savePending:i.isPending,configured:b,note:ke,onSave:S,onClose:N,onRemove:()=>v(!0)}),e.jsx(E,{open:u,title:"Disable Jira",message:"Disable the Jira integration?",confirmLabel:"Disable",onConfirm:k,onCancel:()=>v(!1)})]})}function Me({memory:s,editingId:t,editNote:l,setEditNote:i,onUpdate:o,onCancelEdit:x,onStartEdit:p,onDelete:d,updatePending:h,removePending:r}){return e.jsxs("li",{className:"flex items-start justify-between gap-3 py-1.5 border-b border-[#d4d2cd] last:border-b-0",children:[e.jsx("div",{className:"flex-1 min-w-0",children:t===s.id?e.jsxs("div",{className:"space-y-2",children:[e.jsx("input",{type:"text",value:l,onChange:g=>i(g.target.value),className:a.input}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{onClick:()=>o(s.id),disabled:!l||h,className:a.primaryBtn,children:"Save"}),e.jsx("button",{onClick:x,disabled:h,className:a.secondaryBtn,children:"Cancel"})]})]}):e.jsxs(e.Fragment,{children:[e.jsx("p",{className:"text-sm text-[#444444]",children:s.note}),s.reviewNote&&e.jsx("p",{className:"text-xs text-[#9c9890] italic mt-0.5",children:s.reviewNote}),e.jsx("p",{className:"text-xs text-[#666666] mt-0.5",children:new Date(s.createdAt*1e3).toLocaleDateString()})]})}),t!==s.id&&e.jsxs("div",{className:"flex items-center gap-1 shrink-0",children:[e.jsx("button",{onClick:()=>p(s.id,s.note),className:a.secondaryBtn,children:"Edit"}),e.jsx("button",{onClick:()=>d(s.id),disabled:r,className:a.dangerBtn,children:"Delete"})]})]})}function Pe(){const s=m.useUtils(),{data:t,isLoading:l}=m.memory.list.useQuery(),{data:i}=m.provider.getRegisteredTypes.useQuery(),o=m.memory.create.useMutation({onSuccess:()=>{s.memory.list.invalidate(),P(""),j("unified"),S(!1)}}),x=m.memory.update.useMutation({onSuccess:()=>s.memory.list.invalidate()}),p=m.memory.remove.useMutation({onSuccess:()=>s.memory.list.invalidate()}),[d,h]=f.useState(null),r=m.memory.optimize.useMutation({onSuccess:n=>{s.memory.list.invalidate(),h(n.stats)}}),[g,u]=f.useState(null),[v,b]=f.useState(""),[C,c]=f.useState(null),[N,S]=f.useState(!1),[k,j]=f.useState("unified"),[y,P]=f.useState("");function U(n,w){u(n),b(w)}async function F(n){await x.mutateAsync({id:n,note:v}),u(null),b("")}function K(){u(null),b("")}const z=[{value:"unified",label:"Unified"},...(i??[]).map(n=>({value:n.type,label:n.label}))],R=5;if(l)return e.jsx(I,{size:"lg",centered:!0});const T=new Map;if(t)for(const n of t){const w=T.get(n.toolName)??[];w.push(n),T.set(n.toolName,w)}const B={editingId:g,editNote:v,setEditNote:b,onUpdate:F,onCancelEdit:K,onStartEdit:U,onDelete:n=>c(n),updatePending:x.isPending,removePending:p.isPending};return e.jsxs("div",{className:"space-y-4",children:[N?e.jsxs("div",{className:a.settingsCard+" space-y-3",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("label",{className:"text-sm font-medium text-[#666666] font-sans",children:"Provider"}),e.jsx("select",{value:k,onChange:n=>{j(n.target.value),n.target.blur()},className:"bg-white border border-[#d4d2cd] rounded px-3 py-2 pr-8 text-sm text-[#2c2c2c] focus:outline-none focus:border-[#2b5ea7] font-sans appearance-none bg-[length:16px_16px] bg-[right_8px_center] bg-no-repeat",style:{backgroundImage:`url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23666666' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E")`},children:z.map(n=>e.jsx("option",{value:n.value,children:n.label},n.value))})]}),e.jsxs("div",{children:[e.jsx("label",{className:a.sectionTitle,children:"Note"}),e.jsx("input",{type:"text",value:y,onChange:n=>P(n.target.value),onKeyDown:n=>{n.key==="Enter"&&y.trim()&&!o.isPending&&o.mutate({toolName:k,note:y})},placeholder:"Reusable lesson or pattern...",className:a.input})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{onClick:()=>o.mutate({toolName:k,note:y}),disabled:!y.trim()||o.isPending,className:a.primaryBtn,children:o.isPending?e.jsxs("span",{className:"flex items-center gap-2",children:[e.jsx(I,{size:"sm"})," Saving..."]}):"Save"}),e.jsx("button",{onClick:()=>{S(!1),P(""),j("unified")},disabled:o.isPending,className:a.secondaryBtn,children:"Cancel"})]})]}):e.jsx("button",{onClick:()=>S(!0),className:a.secondaryBtn,children:"+ Add Memory"}),T.size===0&&e.jsx("div",{className:a.settingsCard,children:e.jsx("p",{className:"text-sm text-[#666666]",children:"No memories yet. The agent will save notes here as it learns from tool usage."})}),[...T.entries()].map(([n,w])=>{const A=w.length>R;return e.jsxs("div",{className:a.settingsCard,children:[e.jsxs("div",{className:"mb-3 flex items-center gap-2",children:[e.jsx("span",{className:`${a.badge} ${a.badgeVariants.info}`,children:n}),A&&e.jsxs("span",{className:"text-xs text-[#666666]",children:[w.length," memories"]}),e.jsx("button",{onClick:()=>r.mutate({toolName:n}),disabled:r.isPending||w.length===0,className:`ml-auto ${a.outlineBtn}`,title:"Optimize memories with AI",children:r.isPending&&r.variables?.toolName===n?e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(I,{size:"sm"})," Optimizing..."]}):"Optimize"})]}),e.jsx("ul",{className:`space-y-2${A?" max-h-64 overflow-y-auto":""}`,children:w.map(M=>e.jsx(Me,{memory:M,...B},M.id))})]},n)}),e.jsx(E,{open:C!==null,title:"Delete memory",message:"Delete this agent memory?",onConfirm:()=>{C!==null&&p.mutate({id:C}),c(null)},onCancel:()=>c(null)}),e.jsx(E,{open:d!==null,title:"Optimization Complete",message:d&&e.jsxs("div",{className:"space-y-1.5 text-sm text-[#444444]",children:[e.jsxs("p",{children:["Kept: ",e.jsx("span",{className:"font-medium",children:d.kept})]}),e.jsxs("p",{children:["Updated: ",e.jsx("span",{className:"font-medium",children:d.updated})]}),e.jsxs("p",{children:["Deleted: ",e.jsx("span",{className:"font-medium",children:d.deleted})]})]}),confirmLabel:"OK",cancelLabel:null,confirmStyle:"primary",onConfirm:()=>h(null),onCancel:()=>h(null)})]})}function Ie(){const s=m.useUtils(),{data:t,isLoading:l}=m.settings.getChatModel.useQuery(),i=m.settings.saveChatModel.useMutation({onSuccess:()=>s.settings.getChatModel.invalidate()}),{models:o,isLoading:x}=se();return l||!t?null:e.jsx(ne,{value:t,models:o,loading:x,disabled:i.isPending,onChange:p=>i.mutate({provider:p.provider,modelId:p.modelId})})}const Q=["Pacific/Auckland","Australia/Sydney","Asia/Tokyo","Asia/Shanghai","Asia/Kolkata","Asia/Dubai","Europe/Moscow","Europe/Berlin","UTC","Europe/London","America/Sao_Paulo","America/New_York","America/Chicago","America/Denver","America/Los_Angeles","Pacific/Honolulu"];function ie(s){try{const t=new Intl.DateTimeFormat("en-US",{timeZone:s,timeZoneName:"short"}).formatToParts(new Date).find(i=>i.type==="timeZoneName")?.value??"",l=new Intl.DateTimeFormat("en-US",{timeZone:s,timeZoneName:"shortOffset"}).formatToParts(new Date).find(i=>i.type==="timeZoneName")?.value??"";return`${t} (${l})`}catch{return s}}const Te=new Map(Q.map(s=>[s,ie(s)]));function Le(){const s=m.useUtils(),{data:t,isLoading:l}=m.settings.getAgentConfig.useQuery(),i=m.settings.saveAgentConfig.useMutation({onSuccess:()=>{s.settings.getAgentConfig.invalidate(),c(!1)}}),[o,x]=f.useState(""),[p,d]=f.useState(100),[h,r]=f.useState(50),[g,u]=f.useState(1024),[v,b]=f.useState(1e4),[C,c]=f.useState(!1);if(f.useEffect(()=>{t&&(x(t.timezone),d(t.directModeMaxSteps),r(t.subAgentMaxSteps),u(t.thinkingBudgetGoogle),b(t.thinkingBudgetAnthropic),c(!1))},[t]),l||!t)return null;const N=C&&(o!==t.timezone||p!==t.directModeMaxSteps||h!==t.subAgentMaxSteps||g!==t.thinkingBudgetGoogle||v!==t.thinkingBudgetAnthropic);function S(){i.mutate({timezone:o,directModeMaxSteps:p,subAgentMaxSteps:h,thinkingBudgetGoogle:g,thinkingBudgetAnthropic:v})}function k(){c(!0)}return e.jsxs("div",{className:"max-w-lg space-y-3",children:[e.jsxs("div",{className:a.settingsCard,children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-sm font-medium",children:"Unified mode model"}),e.jsx("span",{className:"text-xs opacity-40",children:"used when chat scope is “ALL”"})]}),e.jsx(Ie,{})]}),e.jsxs("div",{className:a.settingsCard,children:[e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx("label",{className:"text-xs text-[#666666] w-44 shrink-0",children:"Timezone"}),e.jsxs("select",{value:o,onChange:j=>{x(j.target.value),k()},className:"appearance-none bg-white border border-[#d4d2cd] rounded px-3 py-1.5 text-xs text-[#2c2c2c] focus:outline-none focus:border-[#2b5ea7] font-sans",children:[Q.map(j=>e.jsx("option",{value:j,children:Te.get(j)??j},j)),!Q.includes(o)&&e.jsx("option",{value:o,children:ie(o)})]})]}),e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx("label",{className:"text-xs text-[#666666] w-44 shrink-0",children:"Direct mode max steps"}),e.jsx("input",{type:"number",min:1,max:500,value:p,onChange:j=>{d(Number(j.target.value)),k()},className:"w-20 bg-white border border-[#d4d2cd] rounded px-3 py-1.5 text-xs text-[#2c2c2c] focus:outline-none focus:border-[#2b5ea7] font-mono"})]}),e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx("label",{className:"text-xs text-[#666666] w-44 shrink-0",children:"Sub-agent max steps"}),e.jsx("input",{type:"number",min:1,max:500,value:h,onChange:j=>{r(Number(j.target.value)),k()},className:"w-20 bg-white border border-[#d4d2cd] rounded px-3 py-1.5 text-xs text-[#2c2c2c] focus:outline-none focus:border-[#2b5ea7] font-mono"})]}),e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx("label",{className:"text-xs text-[#666666] w-44 shrink-0",children:"Google thinking budget"}),e.jsx("input",{type:"number",min:0,max:1e5,step:256,value:g,onChange:j=>{u(Number(j.target.value)),k()},className:"w-24 bg-white border border-[#d4d2cd] rounded px-3 py-1.5 text-xs text-[#2c2c2c] focus:outline-none focus:border-[#2b5ea7] font-mono"}),e.jsx("span",{className:"text-[10px] text-[#9c9890]",children:"tokens"})]}),e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx("label",{className:"text-xs text-[#666666] w-44 shrink-0",children:"Anthropic thinking budget"}),e.jsx("input",{type:"number",min:0,max:1e5,step:1e3,value:v,onChange:j=>{b(Number(j.target.value)),k()},className:"w-24 bg-white border border-[#d4d2cd] rounded px-3 py-1.5 text-xs text-[#2c2c2c] focus:outline-none focus:border-[#2b5ea7] font-mono"}),e.jsx("span",{className:"text-[10px] text-[#9c9890]",children:"tokens"})]})]}),e.jsxs("div",{className:"flex items-center gap-3 mt-4 pt-3 border-t border-[#e8e6e1]",children:[e.jsx("button",{onClick:S,disabled:!N||i.isPending,className:a.primaryBtn,children:i.isPending?"Saving...":"Save"}),i.isSuccess&&!C&&e.jsx("span",{className:a.successText,children:"Saved"})]})]})]})}function De(){return e.jsxs("div",{className:a.page,children:[e.jsxs("div",{children:[e.jsx("h3",{className:a.sectionTitle,children:"LLM API Keys"}),e.jsx(fe,{})]}),e.jsxs("div",{children:[e.jsx("h3",{className:a.sectionTitle,children:"Data Providers"}),e.jsx(we,{})]}),e.jsxs("div",{children:[e.jsx("h3",{className:a.sectionTitle,children:"Integrations"}),e.jsx(Ae,{})]}),e.jsxs("div",{children:[e.jsx("h3",{className:a.sectionTitle,children:"Agent Configuration"}),e.jsx(Le,{})]}),e.jsxs("div",{children:[e.jsx("h3",{className:a.sectionTitle,children:"Agent Memory"}),e.jsx(Pe,{})]})]})}export{De as Settings};
|
|
1
|
+
import{t as m,r as f,j as e,S as I,c as _,b as a,C as E,u as X,W as V,A as ee,d as de,g as ue,m as O,p as G,e as se,M as me}from"./index-BsLO7f3R.js";import{S as te}from"./SearchableSelect-VoTpUxSB.js";function W({type:s,label:t,note:l}){const i=m.useUtils(),{data:o,isLoading:x}=m.settings.getApiKey.useQuery(s),p=m.settings.saveApiKey.useMutation({onSuccess:()=>i.settings.getApiKey.invalidate(s)}),d=m.settings.removeApiKey.useMutation({onSuccess:()=>i.settings.getApiKey.invalidate(s)}),[h,r]=f.useState(!1),[g,u]=f.useState(""),[v,b]=f.useState(!1);async function C(){await p.mutateAsync({type:s,apiKey:g}),u(""),r(!1)}async function c(){await d.mutateAsync(s),r(!1),b(!1)}return x?e.jsx("div",{className:"px-4 py-3",children:e.jsx(I,{size:"sm"})}):e.jsxs("div",{className:"px-4 py-3",children:[e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx("span",{className:"text-sm font-medium w-24 shrink-0",children:t}),e.jsx("span",{className:a.maskedKey+" flex-1 truncate",style:o?{color:_.success}:void 0,children:o?o.maskedApiKey:"Not configured"}),!h&&e.jsx("button",{onClick:()=>{u(""),r(!0)},className:a.secondaryBtn+" text-xs px-3 py-1",children:o?"Edit":"Add"})]}),h&&e.jsxs("div",{className:"mt-3 pt-3 border-t border-[#e8e6e1] space-y-2",children:[l&&e.jsx("div",{children:l}),e.jsx("input",{type:g?"password":"text",value:g,onChange:N=>u(N.target.value),placeholder:o?.maskedApiKey??"Enter API key",className:a.input}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{onClick:C,disabled:!g||p.isPending,className:a.primaryBtn+" text-xs px-3 py-1",children:p.isPending?e.jsxs("span",{className:"flex items-center gap-2",children:[e.jsx(I,{size:"sm"})," Saving..."]}):"Save"}),e.jsx("button",{onClick:()=>r(!1),disabled:p.isPending,className:a.secondaryBtn+" text-xs px-3 py-1",children:"Cancel"}),o&&e.jsx("button",{onClick:()=>b(!0),disabled:d.isPending,className:a.dangerBtn+" text-xs px-3 py-1",children:"Remove"})]})]}),e.jsx(E,{open:v,title:"Remove API key",message:`Remove the ${t} API key?`,confirmLabel:"Remove",onConfirm:c,onCancel:()=>b(!1)})]})}function J({checked:s,onChange:t,disabled:l,"aria-label":i}){return e.jsx("button",{type:"button",role:"switch","aria-checked":s,"aria-label":i,disabled:l,onClick:()=>t(!s),className:`relative inline-flex h-5 w-9 items-center rounded-full transition-colors ${s?"bg-[#2b5ea7]":"bg-[#d4d2cd]"} ${l?"opacity-50 cursor-not-allowed":"cursor-pointer"}`,children:e.jsx("span",{className:`inline-block h-3.5 w-3.5 rounded-full bg-white transition-transform ${s?"translate-x-[18px]":"translate-x-[3px]"}`})})}function H({status:s,label:t}){return e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:`inline-block h-2 w-2 rounded-full ${a.statusDot[s]}`}),t&&e.jsx("span",{className:a.statusLabel,children:t})]})}function xe(){const s=m.useUtils(),{data:t,isLoading:l}=m.settings.getVertexConfig.useQuery(),i=X(),o=!!t,x=i.data,p=x?.ok??!1,d=o&&p,h=()=>{s.settings.getVertexConfig.invalidate(),s.provider.listVertexModels.invalidate()},r=m.settings.saveVertexConfig.useMutation({onSuccess:h}),g=m.settings.removeVertexConfig.useMutation({onSuccess:h}),u=r.isPending||g.isPending,[v,b]=f.useState(!1),{data:C,isLoading:c}=m.provider.listGcpProjects.useQuery(void 0,{staleTime:V.updateCheckStaleTimeMs,enabled:d}),N=f.useMemo(()=>(C??[]).map(y=>({value:y.projectId,label:y.name?`${y.name} (${y.projectId})`:y.projectId,displayLabel:y.name||y.projectId})),[C]);function S(y){y?r.mutate({}):b(!0)}function k(){g.mutate(),b(!1)}function j(y){y!==t?.projectId&&r.mutate({projectId:y})}return l?e.jsx("div",{className:"px-4 py-3",children:e.jsx(I,{size:"sm"})}):e.jsxs("div",{className:"px-4 py-3",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(J,{checked:o,onChange:S,disabled:u,"aria-label":"Enable Vertex AI"}),e.jsx("span",{className:"text-sm font-medium",children:"Vertex AI"}),o?e.jsx(H,{status:d?"connected":"disconnected"}):e.jsx("span",{className:"text-xs opacity-40",children:"Not configured"})]}),o&&e.jsx("div",{className:"mt-3 pt-3 border-t border-[#e8e6e1]",children:i.isLoading?e.jsxs("div",{className:"flex items-center gap-2 text-xs text-[#666666]",children:[e.jsx(I,{size:"sm"})," Checking authentication…"]}):p?e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("span",{className:"text-xs text-[#666666] whitespace-nowrap w-14",children:"Project"}),e.jsx("div",{className:"flex-1",children:e.jsx(te,{options:N,value:t?.projectId??"",onChange:j,placeholder:c?"Loading...":"Select project...",storageKey:"gcp-projectId",fitContent:!0,disabled:c||u})})]}),e.jsx(pe,{value:t?.location??"global",onCommit:y=>{const P=y.trim()||"global";P!==t?.location&&r.mutate({location:P})},disabled:u})]}):e.jsx("p",{className:a.warnText,children:x&&!x.ok?x.message:"Not authenticated. Run: gcloud auth application-default login"})}),e.jsx(E,{open:v,title:"Disable Vertex AI",message:"Disable Vertex AI? Your project selection will be removed.",confirmLabel:"Disable",onConfirm:k,onCancel:()=>b(!1)})]})}function pe({value:s,onCommit:t,disabled:l}){const[i,o]=f.useState(s);return f.useEffect(()=>o(s),[s]),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("span",{className:"text-xs text-[#666666] whitespace-nowrap w-14",children:"Location"}),e.jsx("input",{type:"text",value:i,onChange:x=>o(x.target.value),onBlur:()=>t(i),onKeyDown:x=>{x.key==="Enter"&&x.currentTarget.blur()},placeholder:"global",disabled:l,className:a.input})]})}function ge({configuredProviders:s}){return e.jsx("div",{className:"border-t border-[#e8e6e1]",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{children:e.jsxs("tr",{className:a.tableHeaderRow,children:[e.jsx("th",{className:a.tableHeaderCell+" text-xs py-2",children:"Model"}),e.jsx("th",{className:a.tableHeaderCell+" text-xs py-2",children:"Provider"}),e.jsx("th",{className:a.tableHeaderCell+" text-xs py-2 text-right",children:"Input ($/M)"}),e.jsx("th",{className:a.tableHeaderCell+" text-xs py-2 text-right",children:"Output ($/M)"})]})}),e.jsx("tbody",{className:"divide-y divide-[#e8e6e1]",children:ee.map(t=>{const l=s.has(t.provider);return e.jsxs("tr",{style:l?{color:_.success}:{color:_.inkFaint},children:[e.jsx("td",{className:"px-4 py-2 font-mono text-xs",children:t.modelId}),e.jsx("td",{className:"px-4 py-2 capitalize",children:t.provider}),e.jsxs("td",{className:"px-4 py-2 text-right font-mono text-xs",children:["$",t.inputPrice.toFixed(2)]}),e.jsxs("td",{className:"px-4 py-2 text-right font-mono text-xs",children:["$",t.outputPrice.toFixed(2)]})]},t.modelId)})})]})})}function $({children:s}){return e.jsx("div",{className:"text-xs leading-relaxed rounded border border-[#d4d2cd] bg-[#f5f4f1] p-3 space-y-2",children:s})}const Z="underline break-all text-[#0052cc]",he=e.jsxs($,{children:[e.jsxs("div",{children:["Create a Gemini API key at:",e.jsx("br",{}),e.jsx("a",{href:"https://aistudio.google.com/api-keys",target:"_blank",rel:"noopener noreferrer",className:Z,children:"https://aistudio.google.com/api-keys"})]}),e.jsx("div",{className:"opacity-80",children:"This key powers the Gemini models Tracer uses to run chats and analyze your data — it is the model provider, not a data source. Tracer sends your prompts and the data it has already fetched to Google's Gemini API for inference; it grants no access back into your Google account."})]});function fe(){const[s,t]=f.useState(!1),l=de();return e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"max-w-lg bg-white border border-[#d4d2cd] rounded divide-y divide-[#e8e6e1] overflow-hidden",children:[e.jsx(W,{type:"anthropic",label:"Anthropic"}),e.jsx(W,{type:"google",label:"Google AI",note:he}),e.jsx(xe,{})]}),e.jsxs("div",{className:"bg-white border border-[#d4d2cd] rounded overflow-hidden",children:[e.jsxs("button",{onClick:()=>t(!s),className:"w-full flex items-center justify-between px-4 py-3 text-sm text-[#666666] hover:bg-[#f5f4f0] transition-colors font-sans",children:[e.jsx("span",{className:"font-medium",children:"Model Pricing"}),e.jsx("span",{className:"text-xs transition-transform duration-200",style:{transform:s?"rotate(180deg)":"rotate(0deg)"},children:"▾"})]}),s&&e.jsx(ge,{configuredProviders:l})]})]})}function ne({value:s,models:t,onChange:l,loading:i,disabled:o,label:x="Model"}){const p=ue(t),d=O(s),r=!t.some(u=>O(u)===d)&&!i;function g(u){const v=u.indexOf(":");l({provider:u.slice(0,v),modelId:u.slice(v+1)})}return e.jsxs("div",{className:"flex items-start gap-3 mt-3 pt-3 border-t border-[#d4d2cd]",children:[e.jsx("span",{className:"text-xs text-[#666666] whitespace-nowrap w-14 mt-2",children:x}),e.jsxs("div",{className:"flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"shrink-0 inline-flex items-center rounded px-1.5 py-0.5 text-[10px] font-medium bg-[#f0eee9] text-[#666666] border border-[#d4d2cd]",children:G(s.provider)}),e.jsxs("div",{className:"relative flex-1",children:[e.jsxs("select",{value:d,onChange:u=>g(u.target.value),disabled:o,className:"w-full appearance-none bg-white border border-[#d4d2cd] rounded px-3 py-2 pr-7 text-xs text-[#2c2c2c] focus:outline-none focus:border-[#2b5ea7] font-sans disabled:opacity-50 disabled:cursor-not-allowed",children:[r&&e.jsx("optgroup",{label:"Unavailable",children:e.jsxs("option",{value:d,children:[G(s.provider)," · ",s.modelId]})}),p.map(u=>e.jsx("optgroup",{label:u.label,children:u.models.map(v=>e.jsx("option",{value:O(v),children:v.modelId},O(v)))},u.provider))]}),e.jsx("span",{className:"pointer-events-none absolute right-2 top-1/2 -translate-y-1/2 text-[#9c9890] text-[10px]",children:"▾"})]})]}),r&&e.jsxs("p",{className:a.warnText+" mt-1.5",children:[G(s.provider)," · ",s.modelId," isn’t available. Configure its provider or pick another model."]})]})]})}const je=ee[0];function ve({providerType:s}){const t=m.useUtils(),{data:l,isLoading:i}=m.settings.getSubAgentModel.useQuery(s),o=m.settings.saveSubAgentModel.useMutation({onSuccess:()=>t.settings.getSubAgentModel.invalidate(s)}),{models:x,isLoading:p}=se();if(i)return null;const d=l??je;return e.jsx(ne,{value:d,models:x,loading:p,disabled:o.isPending,onChange:h=>o.mutate({providerType:s,model:{provider:h.provider,modelId:h.modelId}})})}function be({existingConfig:s}){const t=m.useUtils(),l=X(),{data:i,isLoading:o}=m.provider.listGcpProjects.useQuery(void 0,{staleTime:V.updateCheckStaleTimeMs}),x=m.provider.saveConfig.useMutation({onSuccess:()=>{t.provider.getConfigs.invalidate(),t.provider.list.invalidate()}}),p=f.useMemo(()=>(i??[]).map(r=>({value:r.projectId,label:r.name?`${r.name} (${r.projectId})`:r.projectId,displayLabel:r.name||r.projectId})),[i]),d=s.projectId??"";if(l.data&&!l.data.ok)return null;function h(r){r!==d&&x.mutate({type:"gcp",config:{...s,projectId:r}})}return e.jsxs("div",{className:"flex items-center gap-3 mt-3 pt-3 border-t border-[#d4d2cd]",children:[e.jsx("span",{className:"text-xs text-[#666666] whitespace-nowrap w-14",children:"Project"}),e.jsx("div",{className:"flex-1",children:e.jsx(te,{options:p,value:d,onChange:h,placeholder:o?"Loading...":"Select project...",storageKey:"gcp-projectId",fitContent:!0,disabled:o||x.isPending})})]})}function ye({type:s,label:t,connected:l,configured:i,onConfigure:o,onToggle:x,togglePending:p,toggleError:d,pingError:h,hasConfigFields:r,existingConfig:g}){const u=i||l;return e.jsxs("div",{className:a.settingsCard+" w-80",children:[e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(J,{checked:i,onChange:v=>{v&&r?o():x(v)},disabled:p}),e.jsx("span",{className:"font-medium",children:t}),u?e.jsx(H,{status:l?"connected":"disconnected"}):e.jsx("span",{className:"text-xs opacity-40",children:"Not configured"})]}),e.jsx("button",{onClick:o,className:`${a.secondaryBtn} ${i&&r?"":"invisible"}`,children:"Edit"})]}),u&&e.jsx(ve,{providerType:s}),u&&s==="gcp"&&g&&e.jsx(be,{existingConfig:g}),h&&!l&&e.jsx("p",{className:a.warnText+" mt-2",children:h}),d&&e.jsx("p",{className:a.errorText+" mt-2",children:d})]})}function Y(s,t){return!!s&&!!t&&s===t}function ae({open:s,label:t,configFields:l,formValues:i,onFormChange:o,existingConfig:x,saveResult:p,savePending:d,configured:h,note:r,onSave:g,onClose:u,onRemove:v}){const b=l.some(c=>c.required!==!1&&c.type==="password"&&Y(i[c.key],x?.[c.key])),C=l.some(c=>c.required!==!1&&!i[c.key]);return e.jsxs(me,{open:s,onClose:u,children:[e.jsxs("div",{className:a.dialogTitle+" text-base mb-4",children:["Configure ",t]}),r&&e.jsx("div",{className:"mb-4",children:r}),e.jsx("div",{className:"space-y-3",children:l.map(c=>{const N=c.type==="password"&&Y(i[c.key],x?.[c.key]);return e.jsxs("div",{children:[e.jsxs("label",{className:a.sectionTitle,children:[c.label,c.required===!1&&e.jsx("span",{className:"text-xs opacity-40 ml-1",children:"(optional)"})]}),e.jsx("input",{type:c.type==="password"&&i[c.key]&&!N?"password":"text",value:i[c.key]??"",onChange:S=>o(c.key,S.target.value),onFocus:S=>{N&&S.target.select()},placeholder:`Enter ${c.label.toLowerCase()}`,className:`${a.input} ${N?"!text-[#999] !border-l-2 !border-l-amber-400":""}`})]},c.key)})}),e.jsxs("div",{className:"flex items-center gap-2 mt-4 pt-4 border-t border-[#d4d2cd]",children:[e.jsx("button",{onClick:g,disabled:C||b||d,className:a.primaryBtn,children:d?e.jsxs("span",{className:"flex items-center gap-2",children:[e.jsx(I,{size:"sm"})," Saving..."]}):"Save & Test"}),e.jsx("button",{onClick:u,disabled:d,className:a.secondaryBtn,children:"Cancel"}),h&&e.jsx("button",{onClick:v,disabled:d,className:a.dangerBtn,children:"Remove"})]}),b&&!d&&!p&&e.jsx("p",{className:"mt-2 text-xs text-amber-600",children:"Re-enter highlighted fields to save"}),p&&e.jsx("div",{className:`mt-3 ${p.success?a.successText:a.errorText}`,children:p.success?"Connected successfully":p.error||"Connection failed"})]})}const Ne={newrelic:e.jsxs($,{children:[e.jsxs("div",{children:["Create a ",e.jsx("span",{className:"font-medium",children:"User key"})," at:",e.jsx("br",{}),e.jsx("a",{href:"https://one.newrelic.com/admin-portal/api-keys/home",target:"_blank",rel:"noopener noreferrer",className:Z,children:"https://one.newrelic.com/admin-portal/api-keys/home"}),e.jsx("br",{}),"Your numeric Account ID is shown on the same page."]}),e.jsxs("div",{children:[e.jsx("div",{className:"font-medium",children:"What Tracer can do with it"}),e.jsx("ul",{className:"list-disc ml-4 mt-1 space-y-0.5",children:e.jsxs("li",{children:[e.jsx("span",{className:"font-medium",children:"Run read-only NRQL queries"})," against your account — to inspect metrics, logs, traces, and errors while investigating."]})})]}),e.jsx("div",{className:"opacity-80",children:"It only reads via NRQL. It cannot write, modify, deploy, or delete anything. A New Relic User key inherits your role, so for least privilege use a user scoped to read-only access."})]}),posthog:e.jsxs($,{children:[e.jsxs("div",{children:["Create a ",e.jsx("span",{className:"font-medium",children:"Personal API key"})," in your PostHog instance at:",e.jsx("br",{}),e.jsx("span",{className:"font-mono",children:"/settings/user-api-keys"}),e.jsx("br",{}),"Grant it the single scope ",e.jsx("span",{className:"font-medium",children:"Query → Read"}),". The Project ID is in Settings → Project. Set Host only if you are not on US cloud (e.g.",e.jsx("span",{className:"font-mono",children:" eu.posthog.com"})," or a self-hosted URL)."]}),e.jsxs("div",{children:[e.jsx("div",{className:"font-medium",children:"What Tracer can do with it"}),e.jsx("ul",{className:"list-disc ml-4 mt-1 space-y-0.5",children:e.jsxs("li",{children:[e.jsx("span",{className:"font-medium",children:"Run read-only HogQL queries"})," against the project — to inspect events, persons, and analytics while investigating."]})})]}),e.jsxs("div",{className:"opacity-80",children:["With only the ",e.jsx("span",{className:"font-medium",children:"Query → Read"})," scope it cannot create, modify, or delete anything in PostHog, and it reaches only the project you configure."]})]})};function Ce(s,t){const l={};for(const i of s)l[i.key]=t?.[i.key]??"";return l}function we(){const s=m.useUtils(),{data:t,isLoading:l}=m.provider.list.useQuery(),{data:i,isLoading:o}=m.provider.getConfigs.useQuery(),{data:x,isLoading:p}=m.provider.getRegisteredTypes.useQuery(),{data:d}=m.provider.ping.useQuery(void 0,{staleTime:V.sessionStaleTimeMs,refetchOnMount:"always"}),h=m.provider.saveConfig.useMutation({onSuccess:()=>{s.provider.list.invalidate(),s.provider.getConfigs.invalidate(),s.provider.ping.invalidate()}}),r=m.provider.removeConfig.useMutation({onSuccess:()=>{s.provider.list.invalidate(),s.provider.getConfigs.invalidate(),s.provider.ping.invalidate()}}),[g,u]=f.useState(null),[v,b]=f.useState({}),[C,c]=f.useState(null),[N,S]=f.useState(null),[k,j]=f.useState({});function y(n){const w=i?.find(M=>M.type===n),A=x?.find(M=>M.type===n);b(Ce(A?.configFields??[],w?.config)),c(null),u(n)}function P(){u(null),b({}),c(null)}async function U(n){c(null);try{const w=await h.mutateAsync({type:n,config:v});c(w),w.success&&(u(null),b({}))}catch{c({success:!1,error:"Failed to save configuration"})}}async function F(n,w){if(w){j(A=>{const M={...A};return delete M[n],M});try{const A=await h.mutateAsync({type:n,config:{}});A.success||j(M=>({...M,[n]:A.error??"Connection failed"}))}catch{j(A=>({...A,[n]:"Failed to save configuration"}))}}else S(n)}async function K(n){await r.mutateAsync(n),u(null),b({}),c(null),S(null)}const z=l||o||p,R=x??[];if(z)return e.jsx(I,{size:"lg",centered:!0});const T=g?R.find(n=>n.type===g):null,B=g?i?.find(n=>n.type===g):null;return e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"flex flex-wrap gap-3",children:R.map(({type:n,label:w,configFields:A})=>{const M=t?.find(L=>L.type===n),q=i?.find(L=>L.type===n),oe=!!q,D=d?.find(L=>L.type===n),le=D?D.ok:!!M?.connected,re=A.length>0,ce=D&&!D.ok?D.error:void 0;return e.jsx(ye,{type:n,label:w,connected:le,configured:oe,onConfigure:()=>y(n),onToggle:L=>F(n,L),togglePending:h.isPending||r.isPending,toggleError:k[n],pingError:ce,hasConfigFields:re,existingConfig:q?.config},n)})}),g&&T&&e.jsx(ae,{open:!0,label:T.label,configFields:T.configFields,formValues:v,onFormChange:(n,w)=>b(A=>({...A,[n]:w})),existingConfig:B?.config??null,saveResult:C,savePending:h.isPending,configured:!!B,note:Ne[g],onSave:()=>U(g),onClose:P,onRemove:()=>S(g)}),e.jsx(E,{open:N!==null,title:"Disable provider",message:`Disable ${R.find(n=>n.type===N)?.label??N}?`,confirmLabel:"Disable",onConfirm:()=>{N&&K(N)},onCancel:()=>S(null)})]})}const Se=[{key:"domain",label:"Domain (yourco → yourco.atlassian.net)",type:"text"},{key:"email",label:"Email",type:"text"},{key:"apiToken",label:"API Token",type:"password"}],ke=e.jsxs($,{children:[e.jsxs("div",{children:["Create a token (use the plain ",e.jsx("span",{className:"font-medium",children:"Create API token"}),', not "with scopes") at:',e.jsx("br",{}),e.jsx("a",{href:"https://id.atlassian.com/manage-profile/security/api-tokens",target:"_blank",rel:"noopener noreferrer",className:Z,children:"https://id.atlassian.com/manage-profile/security/api-tokens"})]}),e.jsxs("div",{children:[e.jsx("div",{className:"font-medium",children:"What Tracer can do with it"}),e.jsxs("ul",{className:"list-disc ml-4 mt-1 space-y-0.5",children:[e.jsxs("li",{children:[e.jsx("span",{className:"font-medium",children:"Read an issue"})," — summary, description, status, type, priority, assignee, reporter, labels, components, fix versions, resolution, dates, and its comment thread"]}),e.jsxs("li",{children:[e.jsx("span",{className:"font-medium",children:"Post a comment"})," — plain text, only when you ask"]})]})]}),e.jsx("div",{className:"opacity-80",children:"It cannot edit, transition, delete, bulk-read, or administer anything else. The token uses its account's permissions, so for least privilege point it at a Jira account limited to the projects Tracer should touch."})]});function Ae(){const s=m.useUtils(),{data:t,isLoading:l}=m.integrations.getJira.useQuery(),i=m.integrations.saveJira.useMutation({onSuccess:()=>s.integrations.getJira.invalidate()}),o=m.integrations.removeJira.useMutation({onSuccess:()=>s.integrations.getJira.invalidate()}),[x,p]=f.useState(!1),[d,h]=f.useState({}),[r,g]=f.useState(null),[u,v]=f.useState(!1),b=!!t?.configured,C=t?.config??null;function c(){h({domain:C?.domain??"",email:C?.email??"",apiToken:C?.apiToken??""}),g(null),p(!0)}function N(){p(!1),h({}),g(null)}async function S(){g(null);try{const j=await i.mutateAsync({domain:d.domain??"",email:d.email??"",apiToken:d.apiToken??""});g(j),j.success&&N()}catch{g({success:!1,error:"Failed to save configuration"})}}async function k(){await o.mutateAsync(),v(!1),N()}return l?e.jsx(I,{size:"lg",centered:!0}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"flex flex-wrap gap-3",children:e.jsx("div",{className:a.settingsCard+" w-80",children:e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(J,{checked:b,onChange:j=>{j?c():v(!0)},disabled:i.isPending||o.isPending}),e.jsx("span",{className:"font-medium",children:"Jira"}),b?e.jsx(H,{status:"connected"}):e.jsx("span",{className:"text-xs opacity-40",children:"Not configured"})]}),e.jsx("button",{onClick:c,className:`${a.secondaryBtn} ${b?"":"invisible"}`,children:"Edit"})]})})}),x&&e.jsx(ae,{open:!0,label:"Jira",configFields:Se,formValues:d,onFormChange:(j,y)=>h(P=>({...P,[j]:y})),existingConfig:C,saveResult:r,savePending:i.isPending,configured:b,note:ke,onSave:S,onClose:N,onRemove:()=>v(!0)}),e.jsx(E,{open:u,title:"Disable Jira",message:"Disable the Jira integration?",confirmLabel:"Disable",onConfirm:k,onCancel:()=>v(!1)})]})}function Me({memory:s,editingId:t,editNote:l,setEditNote:i,onUpdate:o,onCancelEdit:x,onStartEdit:p,onDelete:d,updatePending:h,removePending:r}){return e.jsxs("li",{className:"flex items-start justify-between gap-3 py-1.5 border-b border-[#d4d2cd] last:border-b-0",children:[e.jsx("div",{className:"flex-1 min-w-0",children:t===s.id?e.jsxs("div",{className:"space-y-2",children:[e.jsx("input",{type:"text",value:l,onChange:g=>i(g.target.value),className:a.input}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{onClick:()=>o(s.id),disabled:!l||h,className:a.primaryBtn,children:"Save"}),e.jsx("button",{onClick:x,disabled:h,className:a.secondaryBtn,children:"Cancel"})]})]}):e.jsxs(e.Fragment,{children:[e.jsx("p",{className:"text-sm text-[#444444]",children:s.note}),s.reviewNote&&e.jsx("p",{className:"text-xs text-[#9c9890] italic mt-0.5",children:s.reviewNote}),e.jsx("p",{className:"text-xs text-[#666666] mt-0.5",children:new Date(s.createdAt*1e3).toLocaleDateString()})]})}),t!==s.id&&e.jsxs("div",{className:"flex items-center gap-1 shrink-0",children:[e.jsx("button",{onClick:()=>p(s.id,s.note),className:a.secondaryBtn,children:"Edit"}),e.jsx("button",{onClick:()=>d(s.id),disabled:r,className:a.dangerBtn,children:"Delete"})]})]})}function Pe(){const s=m.useUtils(),{data:t,isLoading:l}=m.memory.list.useQuery(),{data:i}=m.provider.getRegisteredTypes.useQuery(),o=m.memory.create.useMutation({onSuccess:()=>{s.memory.list.invalidate(),P(""),j("unified"),S(!1)}}),x=m.memory.update.useMutation({onSuccess:()=>s.memory.list.invalidate()}),p=m.memory.remove.useMutation({onSuccess:()=>s.memory.list.invalidate()}),[d,h]=f.useState(null),r=m.memory.optimize.useMutation({onSuccess:n=>{s.memory.list.invalidate(),h(n.stats)}}),[g,u]=f.useState(null),[v,b]=f.useState(""),[C,c]=f.useState(null),[N,S]=f.useState(!1),[k,j]=f.useState("unified"),[y,P]=f.useState("");function U(n,w){u(n),b(w)}async function F(n){await x.mutateAsync({id:n,note:v}),u(null),b("")}function K(){u(null),b("")}const z=[{value:"unified",label:"Unified"},...(i??[]).map(n=>({value:n.type,label:n.label}))],R=5;if(l)return e.jsx(I,{size:"lg",centered:!0});const T=new Map;if(t)for(const n of t){const w=T.get(n.toolName)??[];w.push(n),T.set(n.toolName,w)}const B={editingId:g,editNote:v,setEditNote:b,onUpdate:F,onCancelEdit:K,onStartEdit:U,onDelete:n=>c(n),updatePending:x.isPending,removePending:p.isPending};return e.jsxs("div",{className:"space-y-4",children:[N?e.jsxs("div",{className:a.settingsCard+" space-y-3",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("label",{className:"text-sm font-medium text-[#666666] font-sans",children:"Provider"}),e.jsx("select",{value:k,onChange:n=>{j(n.target.value),n.target.blur()},className:"bg-white border border-[#d4d2cd] rounded px-3 py-2 pr-8 text-sm text-[#2c2c2c] focus:outline-none focus:border-[#2b5ea7] font-sans appearance-none bg-[length:16px_16px] bg-[right_8px_center] bg-no-repeat",style:{backgroundImage:`url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23666666' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E")`},children:z.map(n=>e.jsx("option",{value:n.value,children:n.label},n.value))})]}),e.jsxs("div",{children:[e.jsx("label",{className:a.sectionTitle,children:"Note"}),e.jsx("input",{type:"text",value:y,onChange:n=>P(n.target.value),onKeyDown:n=>{n.key==="Enter"&&y.trim()&&!o.isPending&&o.mutate({toolName:k,note:y})},placeholder:"Reusable lesson or pattern...",className:a.input})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{onClick:()=>o.mutate({toolName:k,note:y}),disabled:!y.trim()||o.isPending,className:a.primaryBtn,children:o.isPending?e.jsxs("span",{className:"flex items-center gap-2",children:[e.jsx(I,{size:"sm"})," Saving..."]}):"Save"}),e.jsx("button",{onClick:()=>{S(!1),P(""),j("unified")},disabled:o.isPending,className:a.secondaryBtn,children:"Cancel"})]})]}):e.jsx("button",{onClick:()=>S(!0),className:a.secondaryBtn,children:"+ Add Memory"}),T.size===0&&e.jsx("div",{className:a.settingsCard,children:e.jsx("p",{className:"text-sm text-[#666666]",children:"No memories yet. The agent will save notes here as it learns from tool usage."})}),[...T.entries()].map(([n,w])=>{const A=w.length>R;return e.jsxs("div",{className:a.settingsCard,children:[e.jsxs("div",{className:"mb-3 flex items-center gap-2",children:[e.jsx("span",{className:`${a.badge} ${a.badgeVariants.info}`,children:n}),A&&e.jsxs("span",{className:"text-xs text-[#666666]",children:[w.length," memories"]}),e.jsx("button",{onClick:()=>r.mutate({toolName:n}),disabled:r.isPending||w.length===0,className:`ml-auto ${a.outlineBtn}`,title:"Optimize memories with AI",children:r.isPending&&r.variables?.toolName===n?e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(I,{size:"sm"})," Optimizing..."]}):"Optimize"})]}),e.jsx("ul",{className:`space-y-2${A?" max-h-64 overflow-y-auto":""}`,children:w.map(M=>e.jsx(Me,{memory:M,...B},M.id))})]},n)}),e.jsx(E,{open:C!==null,title:"Delete memory",message:"Delete this agent memory?",onConfirm:()=>{C!==null&&p.mutate({id:C}),c(null)},onCancel:()=>c(null)}),e.jsx(E,{open:d!==null,title:"Optimization Complete",message:d&&e.jsxs("div",{className:"space-y-1.5 text-sm text-[#444444]",children:[e.jsxs("p",{children:["Kept: ",e.jsx("span",{className:"font-medium",children:d.kept})]}),e.jsxs("p",{children:["Updated: ",e.jsx("span",{className:"font-medium",children:d.updated})]}),e.jsxs("p",{children:["Deleted: ",e.jsx("span",{className:"font-medium",children:d.deleted})]})]}),confirmLabel:"OK",cancelLabel:null,confirmStyle:"primary",onConfirm:()=>h(null),onCancel:()=>h(null)})]})}function Ie(){const s=m.useUtils(),{data:t,isLoading:l}=m.settings.getChatModel.useQuery(),i=m.settings.saveChatModel.useMutation({onSuccess:()=>s.settings.getChatModel.invalidate()}),{models:o,isLoading:x}=se();return l||!t?null:e.jsx(ne,{value:t,models:o,loading:x,disabled:i.isPending,onChange:p=>i.mutate({provider:p.provider,modelId:p.modelId})})}const Q=["Pacific/Auckland","Australia/Sydney","Asia/Tokyo","Asia/Shanghai","Asia/Kolkata","Asia/Dubai","Europe/Moscow","Europe/Berlin","UTC","Europe/London","America/Sao_Paulo","America/New_York","America/Chicago","America/Denver","America/Los_Angeles","Pacific/Honolulu"];function ie(s){try{const t=new Intl.DateTimeFormat("en-US",{timeZone:s,timeZoneName:"short"}).formatToParts(new Date).find(i=>i.type==="timeZoneName")?.value??"",l=new Intl.DateTimeFormat("en-US",{timeZone:s,timeZoneName:"shortOffset"}).formatToParts(new Date).find(i=>i.type==="timeZoneName")?.value??"";return`${t} (${l})`}catch{return s}}const Te=new Map(Q.map(s=>[s,ie(s)]));function Le(){const s=m.useUtils(),{data:t,isLoading:l}=m.settings.getAgentConfig.useQuery(),i=m.settings.saveAgentConfig.useMutation({onSuccess:()=>{s.settings.getAgentConfig.invalidate(),c(!1)}}),[o,x]=f.useState(""),[p,d]=f.useState(100),[h,r]=f.useState(50),[g,u]=f.useState(1024),[v,b]=f.useState(1e4),[C,c]=f.useState(!1);if(f.useEffect(()=>{t&&(x(t.timezone),d(t.directModeMaxSteps),r(t.subAgentMaxSteps),u(t.thinkingBudgetGoogle),b(t.thinkingBudgetAnthropic),c(!1))},[t]),l||!t)return null;const N=C&&(o!==t.timezone||p!==t.directModeMaxSteps||h!==t.subAgentMaxSteps||g!==t.thinkingBudgetGoogle||v!==t.thinkingBudgetAnthropic);function S(){i.mutate({timezone:o,directModeMaxSteps:p,subAgentMaxSteps:h,thinkingBudgetGoogle:g,thinkingBudgetAnthropic:v})}function k(){c(!0)}return e.jsxs("div",{className:"max-w-lg space-y-3",children:[e.jsxs("div",{className:a.settingsCard,children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-sm font-medium",children:"Unified mode model"}),e.jsx("span",{className:"text-xs opacity-40",children:"used when chat scope is “ALL”"})]}),e.jsx(Ie,{})]}),e.jsxs("div",{className:a.settingsCard,children:[e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx("label",{className:"text-xs text-[#666666] w-44 shrink-0",children:"Timezone"}),e.jsxs("select",{value:o,onChange:j=>{x(j.target.value),k()},className:"appearance-none bg-white border border-[#d4d2cd] rounded px-3 py-1.5 text-xs text-[#2c2c2c] focus:outline-none focus:border-[#2b5ea7] font-sans",children:[Q.map(j=>e.jsx("option",{value:j,children:Te.get(j)??j},j)),!Q.includes(o)&&e.jsx("option",{value:o,children:ie(o)})]})]}),e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx("label",{className:"text-xs text-[#666666] w-44 shrink-0",children:"Direct mode max steps"}),e.jsx("input",{type:"number",min:1,max:500,value:p,onChange:j=>{d(Number(j.target.value)),k()},className:"w-20 bg-white border border-[#d4d2cd] rounded px-3 py-1.5 text-xs text-[#2c2c2c] focus:outline-none focus:border-[#2b5ea7] font-mono"})]}),e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx("label",{className:"text-xs text-[#666666] w-44 shrink-0",children:"Sub-agent max steps"}),e.jsx("input",{type:"number",min:1,max:500,value:h,onChange:j=>{r(Number(j.target.value)),k()},className:"w-20 bg-white border border-[#d4d2cd] rounded px-3 py-1.5 text-xs text-[#2c2c2c] focus:outline-none focus:border-[#2b5ea7] font-mono"})]}),e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx("label",{className:"text-xs text-[#666666] w-44 shrink-0",children:"Google thinking budget"}),e.jsx("input",{type:"number",min:0,max:1e5,step:256,value:g,onChange:j=>{u(Number(j.target.value)),k()},className:"w-24 bg-white border border-[#d4d2cd] rounded px-3 py-1.5 text-xs text-[#2c2c2c] focus:outline-none focus:border-[#2b5ea7] font-mono"}),e.jsx("span",{className:"text-[10px] text-[#9c9890]",children:"tokens"})]}),e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx("label",{className:"text-xs text-[#666666] w-44 shrink-0",children:"Anthropic thinking budget"}),e.jsx("input",{type:"number",min:0,max:1e5,step:1e3,value:v,onChange:j=>{b(Number(j.target.value)),k()},className:"w-24 bg-white border border-[#d4d2cd] rounded px-3 py-1.5 text-xs text-[#2c2c2c] focus:outline-none focus:border-[#2b5ea7] font-mono"}),e.jsx("span",{className:"text-[10px] text-[#9c9890]",children:"tokens"})]})]}),e.jsxs("div",{className:"flex items-center gap-3 mt-4 pt-3 border-t border-[#e8e6e1]",children:[e.jsx("button",{onClick:S,disabled:!N||i.isPending,className:a.primaryBtn,children:i.isPending?"Saving...":"Save"}),i.isSuccess&&!C&&e.jsx("span",{className:a.successText,children:"Saved"})]})]})]})}function De(){return e.jsxs("div",{className:a.page,children:[e.jsxs("div",{children:[e.jsx("h3",{className:a.sectionTitle,children:"LLM API Keys"}),e.jsx(fe,{})]}),e.jsxs("div",{children:[e.jsx("h3",{className:a.sectionTitle,children:"Data Providers"}),e.jsx(we,{})]}),e.jsxs("div",{children:[e.jsx("h3",{className:a.sectionTitle,children:"Integrations"}),e.jsx(Ae,{})]}),e.jsxs("div",{children:[e.jsx("h3",{className:a.sectionTitle,children:"Agent Configuration"}),e.jsx(Le,{})]}),e.jsxs("div",{children:[e.jsx("h3",{className:a.sectionTitle,children:"Agent Memory"}),e.jsx(Pe,{})]})]})}export{De as Settings};
|