" })
-
-Do not use contact_supervisor or intercom for routine completion handoffs. If no coordination is needed, return a focused task result.`;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-function resolveIntercomSessionTarget(sessionName, sessionId) {
- const trimmedName = sessionName?.trim();
- if (trimmedName) return trimmedName;
- const normalizedSessionId = sessionId.startsWith("session-") ? sessionId.slice("session-".length) : sessionId;
- return `${DEFAULT_INTERCOM_TARGET_PREFIX}-${normalizedSessionId.slice(0, 8)}`;
-}
-
-function sanitizeIntercomTargetPart(value) {
- return value.trim().toLowerCase().replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "") || "agent";
-}
-
-function resolveSubagentIntercomTarget(runId, agent, index) {
- const stepSuffix = index !== undefined ? `-${index + 1}` : "";
- return `subagent-${sanitizeIntercomTargetPart(agent)}-${sanitizeIntercomTargetPart(runId)}${stepSuffix}`;
-}
-
-function resolveIntercomBridgeMode(value) {
- if (value === "off" || value === "always" || value === "fork-only") return value;
- return "always";
-}
-
-function resolveIntercomBridgeConfig(value) {
- if (!value || typeof value !== "object" || Array.isArray(value)) {
- return {
- mode: "always",
- instructionFile: ""
- };
- }
- return {
- mode: resolveIntercomBridgeMode(value.mode),
- instructionFile: typeof value.instructionFile === "string" ? value.instructionFile : ""
- };
-}
-
-function intercomConfigStatus(configPath) {
- if (!fs.existsSync(configPath)) return { enabled: true };
- try {
- const parsed = JSON.parse(fs.readFileSync(configPath, "utf-8"));
- return { enabled: parsed.enabled !== false };
- } catch (error) {
- return { enabled: true, error };
- }
-}
-
-function readJsonBestEffort(filePath) {
- try {
- return JSON.parse(fs.readFileSync(filePath, "utf-8"));
- } catch (error) {
- const code = error && typeof error === "object" && "code" in error ? error.code : undefined;
- if (code !== "ENOENT") console.warn(`Failed to read JSON from '${filePath}'.`, error);
- return null;
- }
-}
-
-function packageHasPiExtension(packageRoot) {
- if (!fs.existsSync(packageRoot)) return false;
- const pkg = readJsonBestEffort(path.join(packageRoot, "package.json"));
- if (pkg && typeof pkg === "object" && !Array.isArray(pkg)) {
- const pi = pkg.pi;
- if (pi && typeof pi === "object" && !Array.isArray(pi)) {
- const extensions = pi.extensions;
- return Array.isArray(extensions) && extensions.some((entry) => typeof entry === "string" && entry.trim() !== "");
- }
- }
- return fs.existsSync(path.join(packageRoot, "extensions"));
-}
-
-function isSafePackagePath(value) {
- return value.length > 0 &&
- !path.isAbsolute(value) &&
- value.split(/[\\/]/).every((part) => part.length > 0 && part !== "." && part !== "..");
-}
-
-function parseNpmPackageName(source) {
- const spec = source.slice(4).trim();
- if (!spec) return undefined;
- const match = spec.match(/^(@?[^@]+(?:\/[^@]+)?)(?:@(.+))?$/);
- const packageName = match?.[1] ?? spec;
- return isSafePackagePath(packageName) ? packageName : undefined;
-}
-
-function packageEntrySource(entry) {
- if (typeof entry === "string") return entry;
- if (entry && typeof entry === "object" && !Array.isArray(entry) && typeof entry.source === "string") {
- return entry.source;
- }
- return undefined;
-}
-
-function packageEntryAllowsExtensions(entry) {
- if (!entry || typeof entry !== "object" || Array.isArray(entry)) return true;
- const extensions = entry.extensions;
- return !Array.isArray(extensions) || extensions.length > 0;
-}
-
-function findNearestProjectConfigDir(cwd) {
- let current = path.resolve(cwd);
- while (true) {
- const configDir = path.join(current, CONFIG_DIR);
- if (fs.existsSync(path.join(configDir, "settings.json"))) return configDir;
- const parent = path.dirname(current);
- if (parent === current) return undefined;
- current = parent;
- }
-}
-
-let cachedGlobalNpmRoot;
-
-function getGlobalNpmRoot() {
- if (cachedGlobalNpmRoot !== undefined) return cachedGlobalNpmRoot;
- try {
- cachedGlobalNpmRoot = (0, _nodeChild_process.execSync)("npm root -g", { encoding: "utf-8", timeout: 5000 }).trim();
- return cachedGlobalNpmRoot;
- } catch {
- cachedGlobalNpmRoot = null;
- return null;
- }
-}
-
-function configuredPiIntercomPackageDir(input, agentDir) {
- const cwd = path.resolve(input.cwd ?? process.cwd());
- const projectConfigDir = findNearestProjectConfigDir(cwd);
- const settingsFiles = [
- ...(projectConfigDir ? [{ file: path.join(projectConfigDir, "settings.json"), configDir: projectConfigDir, scope: "project" }] : []),
- { file: path.join(agentDir, "settings.json"), configDir: agentDir, scope: "user" }];
-
- const globalNpmRoot = input.globalNpmRoot === undefined ? getGlobalNpmRoot() : input.globalNpmRoot;
-
- for (const { file, configDir, scope } of settingsFiles) {
- const settings = readJsonBestEffort(file);
- if (!settings || typeof settings !== "object" || Array.isArray(settings)) continue;
- const packages = settings.packages;
- if (!Array.isArray(packages)) continue;
-
- for (const entry of packages) {
- if (!packageEntryAllowsExtensions(entry)) continue;
- const source = packageEntrySource(entry)?.trim();
- if (!source?.startsWith("npm:")) continue;
- const packageName = parseNpmPackageName(source);
- if (packageName !== PI_INTERCOM_PACKAGE_NAME) continue;
- const candidates = scope === "project" ?
- [path.join(configDir, "npm", "node_modules", packageName)] :
- [
- ...(globalNpmRoot ? [path.join(globalNpmRoot, packageName)] : []),
- path.join(agentDir, "npm", "node_modules", packageName)];
-
- const packageRoot = candidates.find(packageHasPiExtension);
- if (packageRoot) return path.resolve(packageRoot);
- }
- }
- return undefined;
-}
-
-function resolveIntercomExtensionDir(input, agentDir) {
- const legacyDir = path.resolve(input.extensionDir ?? defaultIntercomExtensionDir(agentDir));
- if (fs.existsSync(legacyDir)) return legacyDir;
- return configuredPiIntercomPackageDir(input, agentDir) ?? legacyDir;
-}
-
-function extensionSandboxAllowsIntercom(extensions, extensionDir) {
- if (extensions === undefined) return true;
-
- const intercomDir = path.resolve(extensionDir).replaceAll("\\", "/").toLowerCase();
- for (const entry of extensions) {
- const normalized = entry.trim().replaceAll("\\", "/").toLowerCase();
- if (normalized === "pi-intercom") return true;
- if (normalized === intercomDir) return true;
- if (normalized.startsWith(`${intercomDir}/`)) return true;
- if (normalized.endsWith("/pi-intercom")) return true;
- if (normalized.includes("/pi-intercom/")) return true;
- }
- return false;
-}
-
-function expandTilde(filePath) {
- return filePath.startsWith("~/") ? path.join(os.homedir(), filePath.slice(2)) : filePath;
-}
-
-function resolveInstructionTemplate(instructionFile, settingsDir) {
- if (!instructionFile) return DEFAULT_INTERCOM_BRIDGE_TEMPLATE;
- const expandedPath = expandTilde(instructionFile);
- const resolvedPath = path.isAbsolute(expandedPath) ?
- expandedPath :
- path.resolve(settingsDir, expandedPath);
- try {
- return fs.readFileSync(resolvedPath, "utf-8");
- } catch (error) {
- console.warn(`Failed to read intercom bridge instructionFile at '${resolvedPath}'. Using default instructions.`, error);
- return DEFAULT_INTERCOM_BRIDGE_TEMPLATE;
- }
-}
-
-function buildIntercomBridgeInstruction(orchestratorTarget, template) {
- const instruction = template.replaceAll("{orchestratorTarget}", orchestratorTarget).trim();
- if (instruction.startsWith(INTERCOM_BRIDGE_MARKER)) return instruction;
- return `${INTERCOM_BRIDGE_MARKER}
-${instruction}`;
-}
-
-function diagnoseIntercomBridge(input) {
- const config = resolveIntercomBridgeConfig(input.config);
- const mode = config.mode;
- const agentDir = path.resolve(input.agentDir ?? defaultAgentDir());
- const extensionDir = resolveIntercomExtensionDir(input, agentDir);
- const orchestratorTarget = input.orchestratorTarget?.trim();
- const configPath = path.resolve(input.configPath ?? defaultIntercomConfigPath(agentDir));
- const wantsIntercom = mode !== "off" && !(mode === "fork-only" && input.context !== "fork");
- const piIntercomAvailable = fs.existsSync(extensionDir);
- let configStatus;
- let reason;
- if (mode === "off") reason = "bridge mode is off";else
- if (mode === "fork-only" && input.context !== "fork") reason = "bridge mode is fork-only and context is not fork";else
- if (!orchestratorTarget) reason = "orchestrator target is not available";else
- if (!piIntercomAvailable) reason = "pi-intercom extension was not found";else
- {
- configStatus = intercomConfigStatus(configPath);
- if (!configStatus.enabled) reason = "intercom config is disabled";
- }
- let intercomConfigError;
- if (configStatus?.error) {
- const error = configStatus.error;
- intercomConfigError = error instanceof Error ? `${error.name}: ${error.message}` : String(error);
- }
-
- return {
- active: reason === undefined,
- mode,
- wantsIntercom,
- piIntercomAvailable,
- extensionDir,
- configPath,
- ...(orchestratorTarget ? { orchestratorTarget } : {}),
- ...(reason ? { reason } : {}),
- ...(configStatus ? { intercomConfigEnabled: configStatus.enabled } : {}),
- ...(intercomConfigError ? { intercomConfigError } : {})
- };
-}
-
-function resolveIntercomBridge(input) {
- const config = resolveIntercomBridgeConfig(input.config);
- const mode = config.mode;
- const agentDir = path.resolve(input.agentDir ?? defaultAgentDir());
- const extensionDir = resolveIntercomExtensionDir(input, agentDir);
- const orchestratorTarget = input.orchestratorTarget?.trim();
- const settingsDir = path.resolve(input.settingsDir ?? defaultSubagentConfigDir(agentDir));
- const defaultInstruction = buildIntercomBridgeInstruction(
- orchestratorTarget || "{orchestratorTarget}",
- DEFAULT_INTERCOM_BRIDGE_TEMPLATE
- );
-
- if (mode === "off") {
- return { active: false, mode, extensionDir, instruction: defaultInstruction };
- }
- if (mode === "fork-only" && input.context !== "fork") {
- return { active: false, mode, extensionDir, instruction: defaultInstruction };
- }
- if (!orchestratorTarget) {
- return { active: false, mode, extensionDir, instruction: defaultInstruction };
- }
- if (!fs.existsSync(extensionDir)) {
- return { active: false, mode, extensionDir, instruction: defaultInstruction };
- }
-
- const configPath = path.resolve(input.configPath ?? defaultIntercomConfigPath(agentDir));
- const intercomStatus = intercomConfigStatus(configPath);
- if (intercomStatus.error) console.warn(`Failed to parse intercom config at '${configPath}'. Assuming enabled.`, intercomStatus.error);
- if (!intercomStatus.enabled) {
- return { active: false, mode, extensionDir, instruction: defaultInstruction };
- }
-
- const instruction = buildIntercomBridgeInstruction(
- orchestratorTarget,
- resolveInstructionTemplate(config.instructionFile, settingsDir)
- );
-
- return {
- active: true,
- mode,
- orchestratorTarget,
- extensionDir,
- instruction
- };
-}
-
-function applyIntercomBridgeToAgent(agent, bridge) {
- if (!bridge.active || !bridge.orchestratorTarget) return agent;
- if (!extensionSandboxAllowsIntercom(agent.extensions, bridge.extensionDir)) return agent;
-
- const bridgeTools = ["intercom", "contact_supervisor"];
- const tools = agent.tools ?
- [...agent.tools, ...bridgeTools.filter((tool) => !agent.tools?.includes(tool))] :
- agent.tools;
- const instruction = bridge.instruction;
- const trimmedPrompt = agent.systemPrompt?.trim() || "";
- const systemPrompt = trimmedPrompt.includes(INTERCOM_BRIDGE_MARKER) ?
- trimmedPrompt :
- trimmedPrompt ?
- `${trimmedPrompt}\n\n${instruction}` :
- instruction;
-
- if (tools === agent.tools && systemPrompt === agent.systemPrompt) return agent;
- return {
- ...agent,
- tools,
- systemPrompt
- };
-} /* v9-8debbb1836ab02f2 */
diff --git a/pip-tmp/jiti/intercom-result-intercom.32a45520.mjs b/pip-tmp/jiti/intercom-result-intercom.32a45520.mjs
deleted file mode 100644
index fc4c372d6e9ad7efb978bb91b8985fbac6173b07..0000000000000000000000000000000000000000
--- a/pip-tmp/jiti/intercom-result-intercom.32a45520.mjs
+++ /dev/null
@@ -1,269 +0,0 @@
-"use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.buildSubagentResultIntercomPayload = buildSubagentResultIntercomPayload;exports.deliverSubagentIntercomMessageEvent = deliverSubagentIntercomMessageEvent;exports.deliverSubagentResultIntercomEvent = deliverSubagentResultIntercomEvent;exports.formatSubagentResultReceipt = formatSubagentResultReceipt;exports.resolveSubagentResultStatus = resolveSubagentResultStatus;exports.stripDetailsOutputsForIntercomReceipt = stripDetailsOutputsForIntercomReceipt;var _nodeCrypto = await jitiImport("node:crypto");
-var fs = _interopRequireWildcard(await jitiImport("node:fs"));
-var _types = await jitiImport("../shared/types.ts");function _interopRequireWildcard(e, t) {if ("function" == typeof WeakMap) var r = new WeakMap(),n = new WeakMap();return (_interopRequireWildcard = function (e, t) {if (!t && e && e.__esModule) return e;var o,i,f = { __proto__: null, default: e };if (null === e || "object" != typeof e && "function" != typeof e) return f;if (o = t ? n : r) {if (o.has(e)) return o.get(e);o.set(e, f);}for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]);return f;})(e, t);}
-
-
-
-
-
-
-
-
-
-
-
-function resolveSubagentResultStatus(input)
-
-
-
-
-
-{
- if (input.detached) return "detached";
- if (input.interrupted || input.state === "paused") return "paused";
- if (typeof input.success === "boolean") return input.success ? "completed" : "failed";
- if (input.state === "complete") return "completed";
- if (input.state === "failed") return "failed";
- if (typeof input.exitCode === "number") return input.exitCode === 0 ? "completed" : "failed";
- return "failed";
-}
-
-function countStatuses(children) {
- const counts = {
- completed: 0,
- failed: 0,
- paused: 0,
- detached: 0
- };
- for (const child of children) {
- counts[child.status] += 1;
- }
- return counts;
-}
-
-function formatStatusCounts(counts) {
- const parts = [
- counts.completed ? `${counts.completed} completed` : undefined,
- counts.failed ? `${counts.failed} failed` : undefined,
- counts.paused ? `${counts.paused} paused` : undefined,
- counts.detached ? `${counts.detached} detached` : undefined].
- filter((part) => Boolean(part));
- return parts.length ? parts.join(", ") : "0 results";
-}
-
-function resolveGroupedStatus(children) {
- const counts = countStatuses(children);
- if (counts.failed > 0) return "failed";
- if (counts.paused > 0) return "paused";
- if (counts.completed > 0) return "completed";
- if (counts.detached > 0) return "detached";
- return "failed";
-}
-
-
-
-
-
-
-
-
-
-
-
-
-function asyncResumeGuidance(input)
-
-
-
-{
- if (input.source !== "async" || !input.asyncId) return undefined;
- const resumable = input.children.filter((child) => typeof child.sessionPath === "string" && fs.existsSync(child.sessionPath));
- if (input.children.length === 1 && resumable.length === 1) {
- return `Revive: subagent({ action: "resume", id: "${input.asyncId}", message: "..." })`;
- }
- if (resumable.length > 0) {
- const firstIndex = resumable[0]?.index ?? input.children.indexOf(resumable[0]);
- return `Revive child: subagent({ action: "resume", id: "${input.asyncId}", index: ${firstIndex}, message: "..." })`;
- }
- return "Resume: unavailable; no child session file was persisted.";
-}
-
-function formatSubagentResultIntercomMessage(input)
-
-
-
-
-
-
-
-
-{
- const counts = countStatuses(input.children);
- const lines = [
- "subagent results",
- "",
- `Run: ${input.runId}`,
- `Mode: ${input.mode}`,
- `Status: ${input.status}`,
- `Children: ${formatStatusCounts(counts)}`];
-
- if (input.mode === "chain" && typeof input.chainSteps === "number") {
- lines.push(`Chain steps: ${input.chainSteps}`);
- }
- if (input.asyncId) lines.push(`Async id: ${input.asyncId}`);
- if (input.asyncDir) lines.push(`Async dir: ${input.asyncDir}`);
- const resumeGuidance = asyncResumeGuidance(input);
- if (resumeGuidance) lines.push(resumeGuidance);
- if (input.children.some((child) => child.intercomTarget)) {
- lines.push("");
- lines.push(input.source === "async" ?
- "Previous intercom targets below identify child sessions used while they were running. Inspect artifacts or session logs if resume is unavailable." :
- "Intercom targets below identify child sessions used while they were running; completed child sessions may no longer be reachable. Inspect artifacts or session logs for follow-up.");
- }
-
- for (let index = 0; index < input.children.length; index++) {
- const child = input.children[index];
- lines.push("");
- lines.push(`${index + 1}. ${child.agent} — ${child.status}`);
- if (child.intercomTarget) lines.push(`${input.source === "async" ? "Previous intercom target" : "Run intercom target"}: ${child.intercomTarget}`);
- if (child.artifactPath) lines.push(`Output artifact: ${child.artifactPath}`);
- if (child.sessionPath) lines.push(`Session: ${child.sessionPath}`);
- lines.push("Summary:");
- lines.push(child.summary);
- }
-
- return lines.join("\n");
-}
-
-function buildSubagentResultIntercomPayload(input) {
- const children = input.children.map((child) => ({
- ...child,
- summary: child.summary.trim() || "(no output)"
- }));
- const status = resolveGroupedStatus(children);
- const summary = formatStatusCounts(countStatuses(children));
- const firstChild = children[0];
- const payload = {
- to: input.to,
- runId: input.runId,
- mode: input.mode,
- status,
- summary,
- source: input.source,
- children,
- ...(input.asyncId ? { asyncId: input.asyncId } : {}),
- ...(input.asyncDir ? { asyncDir: input.asyncDir } : {}),
- ...(typeof input.chainSteps === "number" ? { chainSteps: input.chainSteps } : {}),
- ...(firstChild?.agent ? { agent: firstChild.agent } : {}),
- ...(firstChild?.index !== undefined ? { index: firstChild.index } : {}),
- ...(firstChild?.artifactPath ? { artifactPath: firstChild.artifactPath } : {}),
- ...(firstChild?.sessionPath ? { sessionPath: firstChild.sessionPath } : {}),
- message: ""
- };
- payload.message = formatSubagentResultIntercomMessage(payload);
- return payload;
-}
-
-async function deliverSubagentResultIntercomEvent(
-events,
-payload,
-timeoutMs = 500)
-{
- return deliverSubagentIntercomMessageEvent(events, payload.to, payload.message, timeoutMs, payload);
-}
-
-async function deliverSubagentIntercomMessageEvent(
-events,
-to,
-message,
-timeoutMs = 500,
-extra = {})
-{
- if (typeof events.on !== "function" || typeof events.emit !== "function") return false;
- const requestId = typeof extra.requestId === "string" ? extra.requestId : (0, _nodeCrypto.randomUUID)();
- return new Promise((resolve) => {
- let settled = false;
- let unsubscribe;
- let timer;
- const finish = (delivered) => {
- if (settled) return;
- settled = true;
- if (timer) clearTimeout(timer);
- unsubscribe?.();
- resolve(delivered);
- };
- unsubscribe = events.on(_types.SUBAGENT_RESULT_INTERCOM_DELIVERY_EVENT, (data) => {
- if (!data || typeof data !== "object") return;
- const delivery = data;
- if (delivery.requestId !== requestId) return;
- finish(delivery.delivered === true);
- });
- timer = setTimeout(() => finish(false), timeoutMs);
- try {
- events.emit(_types.SUBAGENT_RESULT_INTERCOM_EVENT, { ...extra, to, message, requestId });
- } catch {
- finish(false);
- }
- });
-}
-
-function stripSingleResultOutputs(result) {
- return {
- ...result,
- messages: undefined,
- finalOutput: undefined,
- truncation: undefined
- };
-}
-
-function stripDetailsOutputsForIntercomReceipt(details) {
- return {
- ...details,
- results: details.results.map(stripSingleResultOutputs)
- };
-}
-
-function formatSubagentResultReceipt(input)
-
-
-
-{
- const counts = countStatuses(input.payload.children);
- const modeLabel = input.mode === "single" ?
- "single subagent result" :
- input.mode === "parallel" ?
- "parallel subagent results" :
- "chain subagent results";
- const lines = [
- `Delivered ${modeLabel} via intercom.`,
- `Run: ${input.runId}`,
- `Children: ${formatStatusCounts(counts)}`];
-
-
- const artifacts = input.payload.children.filter((child) => typeof child.artifactPath === "string");
- if (artifacts.length > 0) {
- lines.push("Artifacts:");
- for (const child of artifacts) {
- lines.push(`- ${child.agent} [${child.status}]: ${child.artifactPath}`);
- }
- }
-
- const intercomTargets = input.payload.children.filter((child) => typeof child.intercomTarget === "string");
- if (intercomTargets.length > 0) {
- lines.push("Run intercom targets (may be inactive after completion):");
- for (const child of intercomTargets) {
- lines.push(`- ${child.agent} [${child.status}]: ${child.intercomTarget}`);
- }
- }
-
- const sessions = input.payload.children.filter((child) => typeof child.sessionPath === "string");
- if (sessions.length > 0) {
- lines.push("Sessions:");
- for (const child of sessions) {
- lines.push(`- ${child.agent} [${child.status}]: ${child.sessionPath}`);
- }
- }
-
- lines.push("Full grouped output was sent over intercom.");
- return lines.join("\n");
-} /* v9-427c8e4be18cce04 */
diff --git a/pip-tmp/jiti/pi-web-access-activity.4dfe2849.mjs b/pip-tmp/jiti/pi-web-access-activity.4dfe2849.mjs
deleted file mode 100644
index cb2c2a4860315c4c9d41f04ec6825be8aae6b657..0000000000000000000000000000000000000000
--- a/pip-tmp/jiti/pi-web-access-activity.4dfe2849.mjs
+++ /dev/null
@@ -1,101 +0,0 @@
-"use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.activityMonitor = exports.ActivityMonitor = void 0; // Types
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-class ActivityMonitor {
- entries = [];
- maxEntries = 10;
- listeners = new Set();
- rateLimitInfo = { used: 0, max: 10, oldestTimestamp: null, windowMs: 60000 };
- nextId = 1;
-
- logStart(partial) {
- const id = `act-${this.nextId++}`;
- const entry = {
- ...partial,
- id,
- startTime: Date.now(),
- status: null
- };
- this.entries.push(entry);
- if (this.entries.length > this.maxEntries) {
- this.entries.shift();
- }
- this.notify();
- return id;
- }
-
- logComplete(id, status) {
- const entry = this.entries.find((e) => e.id === id);
- if (entry) {
- entry.endTime = Date.now();
- entry.status = status;
- this.notify();
- }
- }
-
- logError(id, error) {
- const entry = this.entries.find((e) => e.id === id);
- if (entry) {
- entry.endTime = Date.now();
- entry.error = error;
- this.notify();
- }
- }
-
- getEntries() {
- return this.entries;
- }
-
- getRateLimitInfo() {
- return this.rateLimitInfo;
- }
-
- updateRateLimit(info) {
- this.rateLimitInfo = info;
- this.notify();
- }
-
- onUpdate(callback) {
- this.listeners.add(callback);
- return () => this.listeners.delete(callback);
- }
-
- clear() {
- this.entries = [];
- this.rateLimitInfo = { used: 0, max: 10, oldestTimestamp: null, windowMs: 60000 };
- this.notify();
- }
-
- notify() {
- for (const cb of this.listeners) {
- try {
- cb();
- } catch {
- }
- }
- }
-}exports.ActivityMonitor = ActivityMonitor;
-
-const activityMonitor = exports.activityMonitor = new ActivityMonitor(); /* v9-be7b38195f5d2adb */
diff --git a/pip-tmp/jiti/pi-web-access-chrome-cookies.ad56e10d.mjs b/pip-tmp/jiti/pi-web-access-chrome-cookies.ad56e10d.mjs
deleted file mode 100644
index 3bb7688d573df870afbce530774eae1d90dca7d8..0000000000000000000000000000000000000000
--- a/pip-tmp/jiti/pi-web-access-chrome-cookies.ad56e10d.mjs
+++ /dev/null
@@ -1,322 +0,0 @@
-"use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.getGoogleCookies = getGoogleCookies;var _nodeChild_process = await jitiImport("node:child_process");
-var _nodeCrypto = await jitiImport("node:crypto");
-var _nodeFs = await jitiImport("node:fs");
-var _nodeOs = await jitiImport("node:os");
-var _nodePath = await jitiImport("node:path");function _interopRequireWildcard(e, t) {if ("function" == typeof WeakMap) var r = new WeakMap(),n = new WeakMap();return (_interopRequireWildcard = function (e, t) {if (!t && e && e.__esModule) return e;var o,i,f = { __proto__: null, default: e };if (null === e || "object" != typeof e && "function" != typeof e) return f;if (o = t ? n : r) {if (o.has(e)) return o.get(e);o.set(e, f);}for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]);return f;})(e, t);}
-
-
-
-
-
-
-
-
-
-
-
-const GOOGLE_ORIGINS = [
-"https://gemini.google.com",
-"https://accounts.google.com",
-"https://www.google.com"];
-
-
-const ALL_COOKIE_NAMES = new Set([
-"__Secure-1PSID",
-"__Secure-1PSIDTS",
-"__Secure-1PSIDCC",
-"__Secure-1PAPISID",
-"NID",
-"AEC",
-"SOCS",
-"__Secure-BUCKET",
-"__Secure-ENID",
-"SID",
-"HSID",
-"SSID",
-"APISID",
-"SAPISID",
-"__Secure-3PSID",
-"__Secure-3PSIDTS",
-"__Secure-3PAPISID",
-"SIDCC"]
-);
-
-const MACOS_BROWSER_CONFIGS = [
-{
- name: "Helium",
- baseDir: "Library/Application Support/net.imput.helium",
- keychainService: "Helium Storage Key",
- keychainAccount: "Helium"
-},
-{
- name: "Chrome",
- baseDir: "Library/Application Support/Google/Chrome",
- keychainService: "Chrome Safe Storage",
- keychainAccount: "Chrome"
-},
-{
- name: "Arc",
- baseDir: "Library/Application Support/Arc/User Data",
- keychainService: "Arc Safe Storage",
- keychainAccount: "Arc"
-}];
-
-
-const LINUX_BROWSER_CONFIGS = [
-{ name: "Chromium", baseDir: ".config/chromium", secretToolApp: "chromium" },
-{ name: "Chrome", baseDir: ".config/google-chrome", secretToolApp: "chrome" }];
-
-
-async function getGoogleCookies(
-options)
-{
- const currentPlatform = (0, _nodeOs.platform)();
- const configs = currentPlatform === "darwin" ?
- MACOS_BROWSER_CONFIGS :
- currentPlatform === "linux" ?
- LINUX_BROWSER_CONFIGS :
- [];
- if (configs.length === 0) return null;
-
- const warnings = [];
- const profile = options?.profile ?? "Default";
- const hosts = GOOGLE_ORIGINS.map((origin) => new URL(origin).hostname);
-
- for (const config of configs) {
- const cookiesPath = (0, _nodePath.join)((0, _nodeOs.homedir)(), config.baseDir, profile, "Cookies");
- if (!(0, _nodeFs.existsSync)(cookiesPath)) continue;
-
- const password = await readBrowserPassword(config, currentPlatform);
- if (!password) {
- warnings.push(`Could not read ${config.name} cookie encryption password`);
- continue;
- }
-
- const key = (0, _nodeCrypto.pbkdf2Sync)(password, "saltysalt", currentPlatform === "darwin" ? 1003 : 1, 16, "sha1");
- const tempDir = (0, _nodeFs.mkdtempSync)((0, _nodePath.join)((0, _nodeOs.tmpdir)(), "pi-chrome-cookies-"));
-
- try {
- const tempDb = (0, _nodePath.join)(tempDir, "Cookies");
- (0, _nodeFs.copyFileSync)(cookiesPath, tempDb);
- copySidecar(cookiesPath, tempDb, "-wal");
- copySidecar(cookiesPath, tempDb, "-shm");
-
- const metaVersion = await readMetaVersion(tempDb);
- const stripHash = metaVersion >= 24;
- const rows = await queryCookieRows(tempDb, hosts);
- if (!rows) {
- warnings.push(`Failed to query ${config.name} cookie database`);
- continue;
- }
-
- const cookies = {};
- for (const row of rows) {
- const name = row.name;
- if (!ALL_COOKIE_NAMES.has(name)) continue;
- if (cookies[name]) continue;
-
- let value = typeof row.value === "string" && row.value.length > 0 ? row.value : null;
- if (!value) {
- const encrypted = row.encrypted_value;
- if (encrypted instanceof Uint8Array) {
- value = decryptCookieValue(encrypted, key, stripHash);
- }
- }
- if (value) cookies[name] = value;
- }
-
- if (options?.requiredCookies?.length && !options.requiredCookies.every((name) => Boolean(cookies[name]))) {
- continue;
- }
-
- return { cookies, warnings };
- } finally {
- (0, _nodeFs.rmSync)(tempDir, { recursive: true, force: true });
- }
- }
-
- return null;
-}
-
-function decryptCookieValue(encrypted, key, stripHash) {
- const buf = Buffer.from(encrypted);
- if (buf.length < 3) return null;
-
- const prefix = buf.subarray(0, 3).toString("utf8");
- if (!/^v\d\d$/.test(prefix)) return null;
-
- const ciphertext = buf.subarray(3);
- if (!ciphertext.length) return "";
-
- try {
- const iv = Buffer.alloc(16, 0x20);
- const decipher = (0, _nodeCrypto.createDecipheriv)("aes-128-cbc", key, iv);
- decipher.setAutoPadding(false);
- const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
- const unpadded = removePkcs7Padding(plaintext);
- const bytes = stripHash && unpadded.length >= 32 ? unpadded.subarray(32) : unpadded;
- const decoded = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
- let i = 0;
- while (i < decoded.length && decoded.charCodeAt(i) < 0x20) i++;
- return decoded.slice(i);
- } catch {
- return null;
- }
-}
-
-function removePkcs7Padding(buf) {
- if (!buf.length) return buf;
- const padding = buf[buf.length - 1];
- if (!padding || padding > 16) return buf;
- return buf.subarray(0, buf.length - padding);
-}
-
-function readBrowserPassword(
-config,
-currentPlatform)
-{
- if (currentPlatform === "darwin") {
- if (!config.keychainAccount || !config.keychainService) return Promise.resolve(null);
- return readKeychainPassword(config.keychainAccount, config.keychainService);
- }
- if (currentPlatform === "linux") {
- return readLinuxPassword(config.secretToolApp);
- }
- return Promise.resolve(null);
-}
-
-function readKeychainPassword(account, service) {
- return new Promise((resolve) => {
- (0, _nodeChild_process.execFile)(
- "security",
- ["find-generic-password", "-w", "-a", account, "-s", service],
- { timeout: 5000 },
- (err, stdout) => {
- if (err) {resolve(null);return;}
- resolve(stdout.trim() || null);
- }
- );
- });
-}
-
-function readLinuxPassword(secretToolApp) {
- if (!secretToolApp) return Promise.resolve("peanuts");
-
- return new Promise((resolve) => {
- (0, _nodeChild_process.execFile)(
- "secret-tool",
- ["lookup", "application", secretToolApp],
- { timeout: 5000 },
- (err, stdout) => {
- if (err) {
- // KDE Wallet users fall through to peanuts intentionally.
- resolve("peanuts");
- return;
- }
- resolve(stdout.trim() || "peanuts");
- }
- );
- });
-}
-
-let sqliteModule = null;
-
-async function importSqlite() {
- if (sqliteModule) return sqliteModule;
- const orig = process.emitWarning.bind(process);
- process.emitWarning = (warning, ...args) => {
- const msg = typeof warning === "string" ? warning : warning?.message ?? "";
- if (msg.includes("SQLite is an experimental feature")) return;
- return orig(warning, ...args);
- };
- try {
- sqliteModule = await Promise.resolve().then(() => jitiImport("node:sqlite").then((m) => _interopRequireWildcard(m)));
- return sqliteModule;
- } catch {
- return null;
- } finally {
- process.emitWarning = orig;
- }
-}
-
-function supportsReadBigInts() {
- const [major, minor] = process.versions.node.split(".").map(Number);
- if (major > 24) return true;
- if (major < 24) return false;
- return minor >= 4;
-}
-
-async function readMetaVersion(dbPath) {
- const sqlite = await importSqlite();
- if (!sqlite) return 0;
- const opts = { readOnly: true };
- if (supportsReadBigInts()) opts.readBigInts = true;
- const db = new sqlite.DatabaseSync(dbPath, opts);
- try {
- const rows = db.prepare("SELECT value FROM meta WHERE key = 'version'").all();
- const val = rows[0]?.value;
- if (typeof val === "number") return Math.floor(val);
- if (typeof val === "bigint") return Number(val);
- if (typeof val === "string") return parseInt(val, 10) || 0;
- return 0;
- } catch {
- return 0;
- } finally {
- db.close();
- }
-}
-
-async function queryCookieRows(
-dbPath,
-hosts)
-{
- const sqlite = await importSqlite();
- if (!sqlite) return null;
-
- const clauses = [];
- for (const host of hosts) {
- for (const candidate of expandHosts(host)) {
- const esc = candidate.replaceAll("'", "''");
- clauses.push(`host_key = '${esc}'`);
- clauses.push(`host_key = '.${esc}'`);
- clauses.push(`host_key LIKE '%.${esc}'`);
- }
- }
- const where = clauses.join(" OR ");
-
- const opts = { readOnly: true };
- if (supportsReadBigInts()) opts.readBigInts = true;
- const db = new sqlite.DatabaseSync(dbPath, opts);
- try {
- return db.
- prepare(
- `SELECT name, value, host_key, encrypted_value FROM cookies WHERE (${where}) ORDER BY expires_utc DESC`
- ).
- all();
- } catch {
- return null;
- } finally {
- db.close();
- }
-}
-
-function expandHosts(host) {
- const parts = host.split(".").filter(Boolean);
- if (parts.length <= 1) return [host];
- const candidates = new Set();
- candidates.add(host);
- for (let i = 1; i <= parts.length - 2; i++) {
- const c = parts.slice(i).join(".");
- if (c) candidates.add(c);
- }
- return Array.from(candidates);
-}
-
-function copySidecar(srcDb, targetDb, suffix) {
- const sidecar = `${srcDb}${suffix}`;
- if (!(0, _nodeFs.existsSync)(sidecar)) return;
- try {
- (0, _nodeFs.copyFileSync)(sidecar, `${targetDb}${suffix}`);
- } catch {
- }
-} /* v9-cf2975e0a9fd33bd */
diff --git a/pip-tmp/jiti/pi-web-access-code-search.f93c7d37.mjs b/pip-tmp/jiti/pi-web-access-code-search.f93c7d37.mjs
deleted file mode 100644
index df6d4a280a61af12534883f621ed9185b91c6b04..0000000000000000000000000000000000000000
--- a/pip-tmp/jiti/pi-web-access-code-search.f93c7d37.mjs
+++ /dev/null
@@ -1,107 +0,0 @@
-"use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.executeCodeSearch = executeCodeSearch;var _activity = await jitiImport("./activity.js");
-var _exa = await jitiImport("./exa.js");
-
-const CODE_CONTEXT_TOOL = "get_code_context_exa";
-const WEB_SEARCH_TOOL = "web_search_exa";
-const DEFAULT_MAX_TOKENS = 5000;
-
-let codeContextToolMissing = false;
-
-function isMissingMcpToolError(message) {
- const normalized = message.toLowerCase();
- return normalized.includes("tool") && normalized.includes("not found");
-}
-
-function buildFallbackQuery(query) {
- const normalized = query.toLowerCase();
- const hasCodeTerms = /\b(api|code|docs?|documentation|example|github|implementation|library|source|stackoverflow|stack overflow)\b/.test(normalized);
- return hasCodeTerms ? query : `${query} code examples documentation GitHub Stack Overflow official docs`;
-}
-
-function maxTokensToResultCount(maxTokens) {
- return Math.min(20, Math.max(5, Math.ceil(maxTokens / 1000)));
-}
-
-function trimApproxTokens(text, maxTokens) {
- const maxCharacters = Math.max(1000, maxTokens * 4);
- if (text.length <= maxCharacters) return text;
- return `${text.slice(0, maxCharacters).trimEnd()}\n\n[Truncated by code_search to approximately ${maxTokens} tokens.]`;
-}
-
-async function executeFallbackSearch(query, maxTokens, signal) {
- const text = await (0, _exa.callExaMcp)(
- WEB_SEARCH_TOOL,
- {
- query: buildFallbackQuery(query),
- numResults: maxTokensToResultCount(maxTokens),
- livecrawl: "fallback",
- type: "auto",
- contextMaxCharacters: Math.min(50000, Math.max(1000, maxTokens * 4))
- },
- signal
- );
- return trimApproxTokens(text, maxTokens);
-}
-
-async function executeCodeSearch(
-_toolCallId,
-params,
-signal)
-
-
-
-{
- const query = params.query.trim();
- if (!query) {
- return {
- content: [{ type: "text", text: "Error: No query provided." }],
- details: { query: "", maxTokens: params.maxTokens ?? DEFAULT_MAX_TOKENS, error: "No query provided" }
- };
- }
-
- const maxTokens = params.maxTokens ?? DEFAULT_MAX_TOKENS;
- const activityId = _activity.activityMonitor.logStart({ type: "api", query });
-
- try {
- let mode = "web-search-fallback";
- let text;
-
- if (codeContextToolMissing) {
- text = await executeFallbackSearch(query, maxTokens, signal);
- } else {
- try {
- text = await (0, _exa.callExaMcp)(
- CODE_CONTEXT_TOOL,
- {
- query,
- tokensNum: maxTokens
- },
- signal
- );
- mode = "code-context";
- } catch (err) {
- const message = err instanceof Error ? err.message : String(err);
- if (!isMissingMcpToolError(message)) throw err;
- codeContextToolMissing = true;
- text = await executeFallbackSearch(query, maxTokens, signal);
- }
- }
-
- _activity.activityMonitor.logComplete(activityId, 200);
- return {
- content: [{ type: "text", text }],
- details: { query, maxTokens, mode }
- };
- } catch (err) {
- const message = err instanceof Error ? err.message : String(err);
- if (message.toLowerCase().includes("abort")) {
- _activity.activityMonitor.logComplete(activityId, 0);
- throw err;
- }
- _activity.activityMonitor.logError(activityId, message);
- return {
- content: [{ type: "text", text: `Error: ${message}` }],
- details: { query, maxTokens, error: message }
- };
- }
-} /* v9-7cb6dc1a8d8e5070 */
diff --git a/pip-tmp/jiti/pi-web-access-curator-page.f382e376.mjs b/pip-tmp/jiti/pi-web-access-curator-page.f382e376.mjs
deleted file mode 100644
index 0a4cda91a4f5ed82c5cd871736b6c83dfba6c22f..0000000000000000000000000000000000000000
--- a/pip-tmp/jiti/pi-web-access-curator-page.f382e376.mjs
+++ /dev/null
@@ -1,3359 +0,0 @@
-"use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.generateCuratorPage = generateCuratorPage;function safeInlineJSON(data) {
- return JSON.stringify(data).
- replace(//g, "\\u003e").
- replace(/&/g, "\\u0026").
- replace(/\u2028/g, "\\u2028").
- replace(/\u2029/g, "\\u2029");
-}
-
-function buildProviderButtons(
-available,
-selected,
-hasInitialQueries)
-{
- const providers = [
- { value: "perplexity", label: "Perplexity", available: available.perplexity },
- { value: "exa", label: "Exa", available: available.exa },
- { value: "gemini", label: "Gemini", available: available.gemini }];
-
-
- return providers.
- filter((p) => p.available).
- map((p) => {
- const isDefault = p.value === selected;
- const state = isDefault && hasInitialQueries ? "loading" : "idle";
- const classes = ["provider-btn", state, isDefault ? "is-default" : ""].filter(Boolean).join(" ");
- const disabled = state === "loading" ? " disabled" : "";
- return ``;
- }).
- join("");
-}
-
-function generateCuratorPage(
-queries,
-sessionToken,
-timeout,
-availableProviders,
-defaultProvider,
-summaryModels,
-defaultSummaryModel)
-{
- const providerButtonsHtml = buildProviderButtons(availableProviders, defaultProvider, queries.length > 0);
- const inlineData = safeInlineJSON({ queries, sessionToken, timeout, defaultProvider, summaryModels, defaultSummaryModel, availableProviders });
-
- return `
-
-
-
-
-Curate Search Results
-
-
-
-
-
-`;
-}
-
-const CSS = `
-*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
-
-:root {
- --bg: #18181e;
- --bg-card: #1e1e24;
- --bg-elevated: #252530;
- --bg-hover: #2b2b37;
- --fg: #e0e0e0;
- --fg-muted: #909098;
- --fg-dim: #606068;
- --accent: #8abeb7;
- --accent-hover: #9dcec7;
- --accent-muted: rgba(138, 190, 183, 0.15);
- --accent-subtle: rgba(138, 190, 183, 0.08);
- --border: #2a2a34;
- --border-muted: #353540;
- --border-checked: #8abeb7;
- --check-bg: #8abeb7;
- --btn-primary: #8abeb7;
- --btn-primary-hover: #9dcec7;
- --btn-primary-fg: #18181e;
- --btn-secondary: #252530;
- --btn-secondary-hover: #2b2b37;
- --timer-bg: #252530;
- --timer-fg: #909098;
- --timer-warn-bg: rgba(240, 198, 116, 0.15);
- --timer-warn-fg: #f0c674;
- --timer-urgent-bg: rgba(204, 102, 102, 0.15);
- --timer-urgent-fg: #cc6666;
- --overlay-bg: rgba(24, 24, 30, 0.92);
- --success: #b5bd68;
- --warning: #f0c674;
- --font: 'Outfit', system-ui, -apple-system, sans-serif;
- --font-display: 'Instrument Serif', Georgia, 'Times New Roman', serif;
- --font-mono: 'SF Mono', Consolas, monospace;
- --radius: 10px;
- --radius-sm: 6px;
-}
-
-@media (prefers-color-scheme: light) {
- :root {
- --bg: #f5f5f7;
- --bg-card: #ffffff;
- --bg-elevated: #eeeef0;
- --bg-hover: #e4e4e8;
- --fg: #1a1a1e;
- --fg-muted: #6c6c74;
- --fg-dim: #9a9aa2;
- --accent: #5f8787;
- --accent-hover: #4a7272;
- --accent-muted: rgba(95, 135, 135, 0.12);
- --accent-subtle: rgba(95, 135, 135, 0.06);
- --border: #dcdce0;
- --border-muted: #c8c8d0;
- --border-checked: #5f8787;
- --check-bg: #5f8787;
- --btn-primary: #5f8787;
- --btn-primary-hover: #4a7272;
- --btn-primary-fg: #ffffff;
- --btn-secondary: #e4e4e8;
- --btn-secondary-hover: #d4d4d8;
- --timer-bg: #e4e4e8;
- --timer-fg: #6c6c74;
- --timer-warn-bg: rgba(217, 119, 6, 0.10);
- --timer-warn-fg: #92400e;
- --timer-urgent-bg: rgba(175, 95, 95, 0.10);
- --timer-urgent-fg: #991b1b;
- --overlay-bg: rgba(255, 255, 255, 0.92);
- --success: #4d7c0f;
- --warning: #b45309;
- }
-}
-
-body {
- font-family: var(--font);
- background: var(--bg);
- background-image: radial-gradient(ellipse at 50% 0%, var(--accent-muted) 0%, transparent 60%);
- color: var(--fg);
- line-height: 1.5;
- min-height: 100dvh;
- padding-bottom: 72px;
-}
-
-.timer-badge {
- position: fixed;
- top: 20px;
- right: 24px;
- z-index: 50;
- font-family: var(--font);
- font-size: 12px;
- font-weight: 600;
- font-variant-numeric: tabular-nums;
- padding: 5px 14px;
- border-radius: 999px;
- background: var(--bg-elevated);
- color: var(--timer-fg);
- border: 1px solid var(--border);
- transition: background 0.3s, color 0.3s, border-color 0.3s, opacity 0.3s;
- box-shadow: 0 2px 8px rgba(0,0,0,0.2);
- cursor: pointer;
- user-select: none;
- opacity: 0.5;
-}
-.timer-badge:hover { opacity: 1; }
-.timer-badge.active { opacity: 1; }
-.timer-badge.warn {
- opacity: 1;
- background: var(--timer-warn-bg);
- color: var(--timer-warn-fg);
- border-color: color-mix(in srgb, var(--timer-warn-fg) 30%, transparent);
-}
-.timer-badge.urgent {
- opacity: 1;
- background: var(--timer-urgent-bg);
- color: var(--timer-urgent-fg);
- border-color: color-mix(in srgb, var(--timer-urgent-fg) 30%, transparent);
-}
-.timer-adjust {
- position: fixed;
- top: 20px;
- right: 24px;
- z-index: 51;
- display: none;
- align-items: center;
- gap: 6px;
- padding: 4px 6px 4px 12px;
- background: var(--bg-elevated);
- border: 1px solid var(--accent);
- border-radius: 999px;
- box-shadow: 0 2px 12px rgba(0,0,0,0.3);
-}
-.timer-adjust.visible { display: flex; }
-.timer-adjust input {
- width: 48px;
- background: transparent;
- border: none;
- outline: none;
- color: var(--fg);
- font-family: var(--font);
- font-size: 13px;
- font-weight: 600;
- font-variant-numeric: tabular-nums;
- text-align: center;
-}
-.timer-adjust-label { font-size: 11px; color: var(--fg-dim); }
-.timer-adjust-btn {
- font-family: var(--font);
- font-size: 11px;
- font-weight: 600;
- padding: 3px 10px;
- border-radius: 999px;
- border: none;
- background: var(--accent);
- color: var(--btn-primary-fg);
- cursor: pointer;
-}
-.timer-adjust-btn:hover { background: var(--accent-hover); }
-
-main {
- max-width: 640px;
- margin: 0 auto;
- padding: 56px 24px 16px;
-}
-
-.hero { margin-bottom: 28px; }
-.hero-kicker {
- font-size: 11px;
- font-weight: 600;
- text-transform: uppercase;
- letter-spacing: 0.1em;
- color: var(--accent);
- margin-bottom: 8px;
-}
-.hero-title {
- font-family: var(--font-display);
- font-size: 40px;
- font-weight: 400;
- font-style: italic;
- letter-spacing: -0.01em;
- line-height: 1.1;
- color: var(--fg);
- margin-bottom: 10px;
- text-wrap: balance;
-}
-.hero-desc {
- font-size: 14px;
- color: var(--fg-muted);
- line-height: 1.5;
- margin-bottom: 12px;
- max-width: 480px;
-}
-.hero-meta {
- display: flex;
- align-items: center;
- gap: 10px;
- font-size: 13px;
- color: var(--fg-dim);
-}
-.hero-meta-sep {
- width: 3px;
- height: 3px;
- border-radius: 50%;
- background: var(--fg-dim);
- flex-shrink: 0;
-}
-#hero-status:empty + .hero-meta-sep { display: none; }
-.provider-buttons {
- display: flex;
- align-items: center;
- flex-wrap: wrap;
- gap: 6px;
-}
-.summary-model-controls {
- display: flex;
- align-items: center;
- gap: 6px;
- min-width: 0;
- flex-shrink: 0;
-}
-.summary-model-dropdown {
- font-family: var(--font);
- font-size: 12px;
- font-weight: 600;
- color: var(--fg);
- background: var(--bg-elevated);
- border: 1px solid var(--border-muted);
- border-radius: var(--radius-sm);
- padding: 4px 8px;
- max-width: 220px;
-}
-.summary-model-dropdown:focus {
- outline: none;
- border-color: var(--accent);
- box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 18%, transparent);
-}
-.summary-model-dropdown:disabled {
- opacity: 0.65;
- cursor: default;
-}
-.provider-btn {
- font-family: var(--font);
- font-size: 12px;
- font-weight: 600;
- padding: 3px 10px;
- border-radius: 999px;
- border: 1px solid var(--border-muted);
- background: transparent;
- color: var(--fg-muted);
- cursor: pointer;
- transition: border-color 0.12s, background 0.12s, color 0.12s, opacity 0.12s;
-}
-.provider-btn.idle:hover {
- color: var(--fg);
- border-color: var(--accent);
-}
-.provider-btn.loading {
- background: var(--accent-subtle);
- color: var(--accent);
- border-color: color-mix(in srgb, var(--accent) 35%, var(--border-muted));
- cursor: default;
- pointer-events: none;
- opacity: 0.85;
-}
-.provider-btn.loading::after {
- content: " …";
- animation: provider-pulse 1.2s ease-in-out infinite;
-}
-.provider-btn.searched {
- background: var(--btn-secondary);
- color: var(--fg);
- border-color: var(--border-muted);
-}
-.provider-btn.searched::after {
- content: " ✓";
- color: var(--success);
-}
-.provider-btn.is-default {
- box-shadow: inset 0 -2px 0 0 var(--accent);
- border-color: var(--accent);
-}
-.provider-btn:disabled {
- cursor: default;
- opacity: 0.5;
-}
-
-@keyframes provider-pulse {
- 0%, 100% { opacity: 0.4; }
- 50% { opacity: 1; }
-}
-
-#result-cards { display: flex; flex-direction: column; gap: 8px; }
-
-.send-raw-row {
- display: flex;
- justify-content: flex-end;
- padding: 4px 0;
-}
-.send-raw-row.hidden { display: none; }
-
-.result-loading {
- border: 1px solid var(--border);
- border-radius: var(--radius);
- background: color-mix(in srgb, var(--bg-card) 86%, var(--accent-subtle));
- overflow: hidden;
- box-shadow: 0 1px 2px rgba(0,0,0,0.06);
-}
-.result-loading-header {
- display: flex;
- align-items: center;
- justify-content: space-between;
- gap: 10px;
- padding: 12px 14px 10px;
- border-bottom: 1px solid var(--border);
-}
-.result-loading-title {
- font-size: 12px;
- font-weight: 600;
- letter-spacing: 0.04em;
- text-transform: uppercase;
- color: var(--accent);
-}
-.result-loading-sub {
- font-size: 12px;
- color: var(--fg-dim);
- font-variant-numeric: tabular-nums;
-}
-.result-loading-grid {
- display: grid;
- gap: 10px;
- padding: 12px 14px 14px;
-}
-.loading-card {
- border: 1px solid color-mix(in srgb, var(--border-muted) 80%, var(--accent-subtle));
- border-radius: var(--radius-sm);
- background: var(--bg-card);
- overflow: hidden;
- position: relative;
-}
-.loading-card::after {
- content: "";
- position: absolute;
- inset: 0;
- background: linear-gradient(105deg, transparent 10%, color-mix(in srgb, var(--accent) 18%, transparent) 45%, transparent 75%);
- transform: translateX(-130%);
- animation: loading-sweep 2s ease-in-out infinite;
- pointer-events: none;
-}
-.loading-card-row {
- height: 10px;
- border-radius: 999px;
- margin: 10px 12px;
- background: color-mix(in srgb, var(--fg-dim) 35%, transparent);
-}
-.loading-card-row.short { width: 35%; }
-.loading-card-row.mid { width: 58%; }
-.loading-card-row.long { width: 78%; }
-
-.result-card {
- background: var(--bg-card);
- border: 1px solid var(--border);
- border-radius: var(--radius);
- overflow: hidden;
- transition: border-color 0.12s;
- box-shadow: 0 1px 2px rgba(0,0,0,0.06);
-}
-.result-card.checked { border-color: var(--border-checked); }
-.result-card.searching {
- opacity: 1;
- border-color: color-mix(in srgb, var(--accent) 40%, var(--border));
- background: linear-gradient(180deg, color-mix(in srgb, var(--accent-subtle) 70%, var(--bg-card)) 0%, var(--bg-card) 100%);
- position: relative;
-}
-.result-card.searching::after {
- content: "";
- position: absolute;
- inset: 0;
- background: linear-gradient(110deg, transparent 20%, color-mix(in srgb, var(--accent) 14%, transparent) 50%, transparent 80%);
- transform: translateX(-130%);
- animation: loading-sweep 2.2s ease-in-out infinite;
- pointer-events: none;
-}
-.result-card.searching .result-card-header { cursor: default; }
-.result-card.searching .result-card-header:hover { background: transparent; }
-.result-card.error { border-color: var(--timer-urgent-fg); }
-
-.result-card-header {
- display: flex;
- align-items: flex-start;
- gap: 12px;
- padding: 14px 16px;
- cursor: pointer;
- user-select: none;
- transition: background 0.12s;
-}
-.result-card-header:hover { background: var(--bg-hover); }
-
-.result-card-header input[type="checkbox"] {
- appearance: none;
- width: 16px;
- height: 16px;
- min-width: 16px;
- border: 1.5px solid var(--border-muted);
- border-radius: 4px;
- margin-top: 2px;
- cursor: pointer;
- transition: background 0.12s, border-color 0.12s;
- display: grid;
- place-content: center;
-}
-.result-card-header input[type="checkbox"]:checked {
- background: var(--check-bg);
- border-color: var(--check-bg);
-}
-.result-card-header input[type="checkbox"]:checked::after {
- content: "";
- width: 9px;
- height: 6px;
- border-left: 2px solid var(--btn-primary-fg);
- border-bottom: 2px solid var(--btn-primary-fg);
- transform: rotate(-45deg);
- margin-top: -1px;
-}
-
-.result-card-info { flex: 1; min-width: 0; }
-
-.result-card-query-row {
- display: flex;
- align-items: center;
- gap: 8px;
- flex-wrap: wrap;
- margin-bottom: 2px;
-}
-.result-card-query {
- font-size: 14px;
- font-weight: 600;
- color: var(--fg);
-}
-.provider-tag {
- display: inline-flex;
- align-items: center;
- padding: 1px 7px;
- border-radius: 999px;
- font-size: 10px;
- font-weight: 700;
- letter-spacing: 0.03em;
- text-transform: uppercase;
- border: 1px solid transparent;
-}
-.provider-tag.provider-exa {
- color: #8dd3ff;
- background: rgba(141, 211, 255, 0.14);
- border-color: rgba(141, 211, 255, 0.3);
-}
-.provider-tag.provider-perplexity {
- color: #cba6f7;
- background: rgba(203, 166, 247, 0.14);
- border-color: rgba(203, 166, 247, 0.3);
-}
-.provider-tag.provider-gemini {
- color: #f5c27b;
- background: rgba(245, 194, 123, 0.14);
- border-color: rgba(245, 194, 123, 0.3);
-}
-.provider-tag.provider-unknown {
- color: var(--fg-muted);
- background: var(--bg-elevated);
- border-color: var(--border-muted);
-}
-.result-card-meta {
- font-size: 12px;
- color: var(--fg-dim);
-}
-.result-card-preview {
- font-size: 12.5px;
- color: var(--fg-muted);
- margin-top: 6px;
- display: -webkit-box;
- -webkit-line-clamp: 2;
- -webkit-box-orient: vertical;
- overflow: hidden;
- line-height: 1.45;
-}
-
-.result-card-expand {
- color: var(--fg-dim);
- font-size: 11px;
- margin-top: 2px;
- flex-shrink: 0;
- padding-top: 3px;
- transition: color 0.12s;
-}
-.result-card-header:hover .result-card-expand { color: var(--fg-muted); }
-
-.result-card-body {
- display: none;
- border-top: 1px solid var(--border);
-}
-.result-card-body.open { display: block; }
-
-.result-card-answer {
- padding: 14px 16px;
- font-size: 13.5px;
- color: var(--fg-muted);
- line-height: 1.6;
- max-height: 400px;
- overflow-y: auto;
-}
-.result-card-answer h1,
-.result-card-answer h2,
-.result-card-answer h3,
-.result-card-answer h4 {
- color: var(--fg);
- font-family: var(--font);
- font-weight: 600;
- margin: 16px 0 6px;
- line-height: 1.3;
-}
-.result-card-answer h1 { font-size: 16px; }
-.result-card-answer h2 { font-size: 14.5px; }
-.result-card-answer h3 { font-size: 13.5px; }
-.result-card-answer h4 { font-size: 13px; color: var(--fg-muted); }
-.result-card-answer p { margin: 0 0 10px; }
-.result-card-answer p:last-child { margin-bottom: 0; }
-.result-card-answer strong { color: var(--fg); font-weight: 600; }
-.result-card-answer a { color: var(--accent); text-decoration: none; }
-.result-card-answer a:hover { text-decoration: underline; }
-.result-card-answer ul, .result-card-answer ol {
- margin: 6px 0 10px;
- padding-left: 20px;
-}
-.result-card-answer li { margin-bottom: 4px; }
-.result-card-answer li::marker { color: var(--fg-dim); }
-.result-card-answer code {
- font-family: var(--font-mono);
- font-size: 12px;
- padding: 1px 5px;
- background: var(--bg-elevated);
- border: 1px solid var(--border);
- border-radius: 3px;
- color: var(--fg);
-}
-.result-card-answer pre {
- margin: 8px 0 12px;
- padding: 12px 14px;
- background: var(--bg);
- border: 1px solid var(--border);
- border-radius: var(--radius-sm);
- overflow-x: auto;
- line-height: 1.45;
-}
-.result-card-answer pre code {
- padding: 0;
- background: none;
- border: none;
- font-size: 12px;
- color: var(--fg-muted);
-}
-.result-card-answer blockquote {
- margin: 8px 0;
- padding: 8px 14px;
- border-left: 3px solid var(--accent);
- color: var(--fg-dim);
- background: var(--accent-subtle);
- border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
-}
-.result-card-answer table {
- width: 100%;
- border-collapse: collapse;
- margin: 8px 0 12px;
- font-size: 12.5px;
-}
-.result-card-answer th, .result-card-answer td {
- padding: 6px 10px;
- border: 1px solid var(--border);
- text-align: left;
-}
-.result-card-answer th {
- background: var(--bg-elevated);
- color: var(--fg);
- font-weight: 600;
- font-size: 11.5px;
- text-transform: uppercase;
- letter-spacing: 0.03em;
-}
-.result-card-answer hr {
- border: none;
- border-top: 1px solid var(--border);
- margin: 14px 0;
-}
-
-.result-card-sources {
- padding: 10px 16px 14px;
- border-top: 1px solid var(--border);
-}
-.result-card-sources-title {
- font-size: 11px;
- font-weight: 600;
- text-transform: uppercase;
- letter-spacing: 0.06em;
- color: var(--fg-dim);
- margin-bottom: 6px;
-}
-.source-link {
- display: block;
- padding: 4px 0;
- font-size: 12.5px;
- color: var(--fg-muted);
- text-decoration: none;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- transition: color 0.12s;
-}
-.source-link:hover { color: var(--accent); }
-.source-domain {
- color: var(--fg-dim);
- margin-left: 6px;
-}
-
-.result-card-error-msg {
- padding: 12px 16px;
- font-size: 13px;
- color: var(--timer-urgent-fg);
-}
-
-.card-alt-providers {
- display: flex;
- align-items: center;
- gap: 6px;
- padding: 4px 16px 8px 42px;
- font-size: 11px;
- color: var(--fg-dim);
-}
-.card-alt-chip {
- font-family: var(--font);
- font-size: 10px;
- font-weight: 600;
- padding: 2px 8px;
- border-radius: 999px;
- border: 1px solid var(--border-muted);
- background: transparent;
- color: var(--fg-muted);
- cursor: pointer;
- transition: border-color 0.12s, color 0.12s, background 0.12s;
-}
-.card-alt-chip:hover:not(:disabled) {
- color: var(--accent);
- border-color: var(--accent);
-}
-.card-alt-chip:disabled {
- opacity: 0.4;
- cursor: default;
-}
-.card-alt-chip.loading {
- opacity: 0.6;
- pointer-events: none;
-}
-.card-alt-chip.loading::after {
- content: " …";
-}
-
-.searching-dots::after {
- content: "";
- animation: dots 1.5s steps(4, end) infinite;
-}
-@keyframes dots {
- 0% { content: ""; }
- 25% { content: "."; }
- 50% { content: ".."; }
- 75% { content: "..."; }
-}
-
-@keyframes loading-sweep {
- 0% { transform: translateX(-130%); }
- 100% { transform: translateX(130%); }
-}
-
-@keyframes summary-pulse {
- 0%, 100% {
- transform: scale(0.9);
- box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 35%, transparent);
- }
- 50% {
- transform: scale(1.15);
- box-shadow: 0 0 0 6px color-mix(in srgb, var(--accent) 0%, transparent);
- }
-}
-
-@keyframes summary-sweep {
- 0% { transform: translateX(-100%); }
- 100% { transform: translateX(120%); }
-}
-
-@keyframes summary-panel-sweep {
- 0% { transform: translateX(-115%); }
- 100% { transform: translateX(115%); }
-}
-
-.add-search {
- display: flex;
- align-items: center;
- gap: 10px;
- margin-top: 12px;
- padding: 11px 14px;
- border: 1px dashed var(--border);
- border-radius: var(--radius);
- cursor: text;
- transition: border-color 0.15s, background 0.15s;
-}
-.add-search:hover {
- border-color: var(--border-muted);
- background: var(--accent-subtle);
-}
-.add-search:focus-within {
- border-color: var(--accent);
- border-style: solid;
- background: var(--accent-subtle);
-}
-.add-search-icon {
- color: var(--fg-dim);
- font-size: 16px;
- font-weight: 300;
- line-height: 1;
- flex-shrink: 0;
- transition: color 0.15s;
-}
-.add-search:focus-within .add-search-icon { color: var(--accent); }
-.add-search input {
- flex: 1;
- background: transparent;
- border: none;
- outline: none;
- color: var(--fg);
- font-family: var(--font);
- font-size: 13.5px;
- font-weight: 500;
-}
-.add-search input::placeholder {
- color: var(--fg-dim);
- font-weight: 400;
-}
-.add-search-wand {
- flex-shrink: 0;
- width: 26px;
- height: 26px;
- display: flex;
- align-items: center;
- justify-content: center;
- border: 1px solid var(--border-muted);
- border-radius: 6px;
- background: transparent;
- color: var(--fg-dim);
- font-size: 14px;
- cursor: pointer;
- transition: color 0.12s, border-color 0.12s, background 0.12s;
-}
-.add-search-wand:hover:not(:disabled) {
- color: var(--accent);
- border-color: var(--accent);
- background: var(--accent-subtle);
-}
-.add-search-wand:disabled {
- opacity: 0.3;
- cursor: default;
-}
-.add-search-wand.rewriting {
- pointer-events: none;
- animation: wand-spin 0.8s linear infinite;
-}
-@keyframes wand-spin {
- 0% { transform: rotate(0deg); }
- 100% { transform: rotate(360deg); }
-}
-
-.summary-panel {
- margin-top: 14px;
- border: 1px solid var(--border);
- border-radius: var(--radius);
- background: var(--bg-card);
- padding: 14px;
- display: flex;
- flex-direction: column;
- gap: 10px;
-}
-.summary-panel.hidden { display: none; }
-.summary-header { display: flex; flex-direction: column; gap: 2px; }
-.summary-header-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
-.summary-title {
- font-size: 14px;
- font-weight: 600;
- color: var(--fg);
-}
-.summary-subtitle {
- font-size: 12px;
- color: var(--fg-dim);
-}
-.summary-generating {
- position: relative;
- isolation: isolate;
- overflow: hidden;
- border: 1px solid color-mix(in srgb, var(--accent) 28%, var(--border));
- border-radius: var(--radius-sm);
- background: linear-gradient(130deg, color-mix(in srgb, var(--accent-subtle) 78%, transparent) 0%, var(--bg-elevated) 70%);
- padding: 12px;
- display: flex;
- flex-direction: column;
- gap: 10px;
-}
-.summary-generating::before {
- content: "";
- position: absolute;
- inset: 0;
- background: linear-gradient(110deg, transparent 0%, color-mix(in srgb, var(--accent) 16%, transparent) 50%, transparent 100%);
- transform: translateX(-115%);
- animation: summary-panel-sweep 2.4s ease-in-out infinite;
- pointer-events: none;
-}
-.summary-generating > * {
- position: relative;
- z-index: 1;
-}
-.summary-generating.hidden { display: none; }
-.summary-generating-head {
- display: flex;
- align-items: center;
- gap: 8px;
- font-size: 12px;
- font-weight: 600;
- color: var(--accent-hover);
-}
-.summary-generating-orb {
- width: 10px;
- height: 10px;
- border-radius: 999px;
- background: var(--accent);
- box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 35%, transparent);
- animation: summary-pulse 1.1s ease-in-out infinite;
-}
-.summary-generating-bars {
- display: grid;
- gap: 6px;
-}
-.summary-generating-bar {
- position: relative;
- display: block;
- height: 8px;
- border-radius: 999px;
- background: color-mix(in srgb, var(--bg) 65%, var(--bg-elevated));
- overflow: hidden;
- transition: width 220ms ease;
-}
-.summary-generating-bar::after {
- content: "";
- position: absolute;
- inset: 0;
- transform: translateX(-100%);
- background: linear-gradient(90deg, transparent 0%, color-mix(in srgb, var(--accent) 45%, transparent) 50%, transparent 100%);
- animation: summary-sweep 1.6s ease-in-out infinite;
-}
-.summary-generating-bar.b1 { width: 86%; }
-.summary-generating-bar.b2 { width: 68%; }
-.summary-generating-bar.b3 { width: 74%; }
-.summary-generating[data-phase="1"] .summary-generating-bar.b1 { width: 72%; }
-.summary-generating[data-phase="1"] .summary-generating-bar.b2 { width: 82%; }
-.summary-generating[data-phase="1"] .summary-generating-bar.b3 { width: 60%; }
-.summary-generating[data-phase="2"] .summary-generating-bar.b1 { width: 64%; }
-.summary-generating[data-phase="2"] .summary-generating-bar.b2 { width: 71%; }
-.summary-generating[data-phase="2"] .summary-generating-bar.b3 { width: 90%; }
-.summary-generating-bar.b2::after { animation-delay: 0.15s; }
-.summary-generating-bar.b3::after { animation-delay: 0.3s; }
-.summary-input {
- width: 100%;
- min-height: 180px;
- resize: vertical;
- border: 1px solid var(--border-muted);
- border-radius: var(--radius-sm);
- padding: 10px 12px;
- font-family: var(--font);
- font-size: 13px;
- line-height: 1.5;
- color: var(--fg);
- background: var(--bg-elevated);
- outline: none;
-}
-.summary-input.hidden { display: none; }
-.summary-input:focus {
- border-color: var(--accent);
-}
-.summary-feedback-row {
- display: flex;
- align-items: center;
- gap: 8px;
- margin-top: 6px;
-}
-.summary-feedback {
- flex: 1;
- height: 32px;
- border: 1px solid var(--border-muted);
- border-radius: var(--radius-sm);
- padding: 4px 10px;
- font-family: var(--font);
- font-size: 12px;
- color: var(--fg);
- background: var(--bg-elevated);
- outline: none;
-}
-.summary-feedback:focus {
- border-color: var(--accent);
-}
-.summary-feedback::placeholder {
- color: var(--fg-muted);
-}
-.summary-actions {
- display: flex;
- align-items: center;
- justify-content: flex-end;
- gap: 8px;
-}
-
-.action-bar {
- position: fixed;
- bottom: 0;
- left: 0;
- right: 0;
- z-index: 10;
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 12px 24px;
- background: color-mix(in srgb, var(--bg) 90%, transparent);
- backdrop-filter: blur(12px);
- -webkit-backdrop-filter: blur(12px);
- border-top: 1px solid var(--border);
-}
-.action-shortcuts { display: flex; align-items: center; gap: 16px; }
-.shortcut { display: flex; align-items: center; gap: 5px; font-size: 11px; color: var(--fg-dim); }
-.shortcut kbd {
- display: inline-flex;
- align-items: center;
- justify-content: center;
- min-width: 18px;
- height: 18px;
- padding: 0 4px;
- font-family: var(--font-mono);
- font-size: 10px;
- font-weight: 500;
- background: var(--bg-elevated);
- border: 1px solid var(--border-muted);
- border-radius: 3px;
- color: var(--fg-muted);
-}
-.action-buttons { display: flex; gap: 8px; }
-
-.btn {
- font-family: var(--font);
- font-size: 13px;
- font-weight: 500;
- padding: 7px 16px;
- border: none;
- border-radius: var(--radius-sm);
- cursor: pointer;
- transition: background 0.12s, opacity 0.12s;
-}
-.btn:disabled { opacity: 0.35; cursor: default; }
-.btn-submit { background: var(--btn-primary); color: var(--btn-primary-fg); }
-.btn-submit:hover:not(:disabled) { background: var(--btn-primary-hover); }
-.btn-secondary { background: var(--btn-secondary); color: var(--fg-muted); border: 1px solid var(--border); }
-.btn-secondary:hover:not(:disabled) { background: var(--btn-secondary-hover); color: var(--fg); }
-
-.success-overlay {
- position: fixed; inset: 0; z-index: 200;
- background: var(--overlay-bg);
- display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px;
- transition: opacity 200ms;
-}
-.success-overlay.hidden { display: flex !important; opacity: 0; pointer-events: none; }
-.success-icon {
- width: 56px; height: 56px; border-radius: 50%;
- border: 2px solid var(--success);
- display: flex; align-items: center; justify-content: center;
- font-size: 18px; font-weight: 700; color: var(--success);
-}
-.success-overlay p { margin: 0; font-size: 13px; font-weight: 600; color: var(--success); letter-spacing: 0.06em; text-transform: uppercase; }
-
-.expired-overlay {
- position: fixed; inset: 0;
- background: var(--overlay-bg);
- display: flex; align-items: center; justify-content: center;
- opacity: 0; transition: opacity 400ms; pointer-events: none; z-index: 200;
-}
-.expired-overlay.visible { opacity: 1; pointer-events: auto; }
-.expired-overlay.hidden { display: flex !important; opacity: 0; pointer-events: none; }
-.expired-content {
- text-align: center; max-width: 480px; padding: 48px 56px;
- background: var(--bg-card); border: 1px solid var(--border); border-radius: 12px;
-}
-.expired-overlay.visible .expired-content { animation: slide-up 400ms ease-out; }
-@keyframes slide-up { from { transform: translateY(20px); } to { transform: translateY(0); } }
-.expired-icon {
- width: 72px; height: 72px; border-radius: 50%; border: 2px solid var(--warning);
- display: flex; align-items: center; justify-content: center;
- font-size: 32px; font-weight: bold; color: var(--warning); margin: 0 auto 24px;
-}
-.expired-content h2 { color: var(--fg); margin: 0 0 16px; font-size: 22px; font-weight: 600; }
-.expired-content p { color: var(--fg-muted); margin: 0 0 24px; font-size: 14px; line-height: 1.6; }
-.expired-countdown { font-size: 13px; color: var(--fg-dim); font-variant-numeric: tabular-nums; }
-.expired-countdown span { color: var(--warning); font-weight: 600; }
-
-.preview-modal {
- position: fixed; inset: 0; z-index: 250;
- background: var(--overlay-bg);
- display: flex; align-items: center; justify-content: center;
- animation: fade-in 150ms ease-out;
-}
-.preview-modal.hidden { display: none; }
-@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
-.preview-modal-inner {
- width: min(720px, calc(100% - 48px));
- max-height: calc(100vh - 80px);
- background: var(--bg-card);
- border: 1px solid var(--border);
- border-radius: 12px;
- display: flex; flex-direction: column;
- animation: slide-up 200ms ease-out;
-}
-.preview-modal-header {
- display: flex; align-items: center; justify-content: space-between;
- padding: 16px 20px;
- border-bottom: 1px solid var(--border);
- flex-shrink: 0;
-}
-.preview-modal-title { font-size: 14px; font-weight: 600; color: var(--fg); margin: 0; }
-.preview-modal-close {
- background: none; border: none; cursor: pointer;
- font-size: 22px; line-height: 1; color: var(--fg-muted); padding: 0 4px;
- transition: color 0.12s;
-}
-.preview-modal-close:hover { color: var(--fg); }
-.preview-modal-body {
- position: relative;
- padding: 24px 28px;
- overflow-y: auto;
- font-size: 14px; line-height: 1.7; color: var(--fg);
-}
-.preview-modal-body h1 { font-size: 20px; font-weight: 600; margin: 1.2em 0 0.5em; color: var(--fg); }
-.preview-modal-body h2 { font-size: 16px; font-weight: 600; margin: 1.2em 0 0.4em; color: var(--fg); }
-.preview-modal-body h3 { font-size: 14px; font-weight: 600; margin: 1em 0 0.3em; color: var(--fg); }
-.preview-modal-body p { margin: 0.6em 0; }
-.preview-modal-body a { color: var(--accent); }
-.preview-modal-body pre { background: var(--bg-elevated); padding: 14px; border-radius: var(--radius-sm); overflow-x: auto; }
-.preview-modal-body code { font-size: 0.9em; }
-.preview-modal-body blockquote { border-left: 3px solid var(--border); padding-left: 14px; color: var(--fg-muted); margin: 0.6em 0; }
-.preview-modal-body hr { border: none; border-top: 1px solid var(--border); margin: 1.5em 0; }
-.preview-modal-body ul, .preview-modal-body ol { padding-left: 1.4em; }
-.preview-modal-body li + li { margin-top: 0.25em; }
-.preview-modal-body strong { color: var(--fg); }
-.preview-modal-footer {
- padding: 12px 20px;
- border-top: 1px solid var(--border);
- display: flex; align-items: center; gap: 8px;
- flex-shrink: 0;
-}
-.preview-modal-model {
- margin-right: auto;
- font-family: var(--font);
- font-size: 11px;
- color: var(--fg-muted);
- background: var(--bg-elevated);
- border: 1px solid var(--border-muted);
- border-radius: var(--radius-sm);
- padding: 4px 8px;
- max-width: 220px;
- outline: none;
-}
-.preview-modal-model:focus { border-color: var(--accent); }
-
-.preview-popover {
- position: absolute;
- z-index: 260;
- width: min(340px, calc(100% - 40px));
- background: var(--bg-elevated);
- border: 1px solid var(--accent);
- border-radius: var(--radius);
- padding: 10px 12px;
- display: flex; flex-direction: column; gap: 8px;
- box-shadow: 0 8px 24px rgba(0,0,0,0.35);
- animation: fade-in 100ms ease-out;
-}
-.preview-popover.hidden { display: none; }
-.preview-popover-quote {
- font-size: 12px;
- color: var(--fg-muted);
- font-style: italic;
- border-left: 2px solid var(--accent);
- padding-left: 8px;
- max-height: 48px;
- overflow: hidden;
- display: -webkit-box;
- -webkit-line-clamp: 2;
- -webkit-box-orient: vertical;
-}
-.preview-popover-input {
- font-family: var(--font);
- font-size: 13px;
- line-height: 1.4;
- color: var(--fg);
- background: var(--bg-card);
- border: 1px solid var(--border-muted);
- border-radius: var(--radius-sm);
- padding: 6px 10px;
- outline: none;
- width: 100%;
- resize: vertical;
-}
-.preview-popover-input:focus { border-color: var(--accent); }
-.preview-popover-btn { align-self: flex-end; font-size: 12px; padding: 5px 14px; }
-
-.error-banner {
- position: fixed; bottom: 64px; left: 50%; transform: translateX(-50%); z-index: 50;
- padding: 10px 20px; background: var(--timer-urgent-bg); color: var(--timer-urgent-fg);
- border-radius: var(--radius); font-size: 13px; font-weight: 500;
-}
-
-.summary-panel.updating {
- border-color: color-mix(in srgb, var(--accent) 35%, var(--border));
- position: relative;
- overflow: hidden;
-}
-.summary-panel.updating::after {
- content: "";
- position: absolute;
- top: 0;
- left: 0;
- width: 30%;
- height: 2px;
- border-radius: var(--radius) var(--radius) 0 0;
- background: linear-gradient(90deg, transparent, var(--accent), transparent);
- animation: updating-bar 1.8s ease-in-out infinite;
- pointer-events: none;
-}
-.summary-panel.updating .summary-input,
-.summary-panel.updating .summary-feedback-row {
- opacity: 0.45;
- pointer-events: none;
-}
-.summary-panel.updating .summary-actions {
- opacity: 0.72;
-}
-@keyframes updating-bar {
- 0% { transform: translateX(-50%); }
- 100% { transform: translateX(430%); }
-}
-
-@media (prefers-reduced-motion: reduce) {
- .loading-card::after,
- .result-card.searching::after,
- .provider-btn.loading::after,
- .searching-dots::after,
- .summary-generating::before,
- .summary-generating-orb,
- .summary-generating-bar::after,
- .summary-panel.updating::after {
- animation: none !important;
- }
-}
-
-@media (max-width: 500px) {
- main { padding: 32px 16px 16px; }
- .hero-title { font-size: 28px; }
- .hero-desc { font-size: 13px; }
- .summary-header-top { flex-direction: column; }
- .summary-model-controls { flex-wrap: wrap; }
- .summary-model-dropdown { max-width: 100%; }
- .action-bar { padding: 10px 14px; }
- .action-shortcuts { display: none; }
- .result-card-header { padding: 12px 14px; }
- .expired-content { padding: 32px 24px; }
- .timer-badge { top: 12px; right: 16px; }
-}
-`;
-
-const SCRIPT = `(function() {
- var DATA = __INLINE_DATA__;
- var token = DATA.sessionToken;
- var timeoutSec = DATA.timeout;
- var queries = Array.isArray(DATA.queries) ? DATA.queries : [];
- var providers = ["perplexity", "exa", "gemini"];
- var availProviders = DATA.availableProviders && typeof DATA.availableProviders === "object" ? DATA.availableProviders : {};
- var workflow = "summary-review";
- var initialDefaultProvider = typeof DATA.defaultProvider === "string" ? DATA.defaultProvider : "exa";
- if (providers.indexOf(initialDefaultProvider) === -1) initialDefaultProvider = "exa";
-
- var summaryModels = Array.isArray(DATA.summaryModels)
- ? DATA.summaryModels.filter(function(model) {
- return model && typeof model === "object" && typeof model.value === "string";
- })
- : [];
- var defaultSummaryModel = typeof DATA.defaultSummaryModel === "string"
- ? DATA.defaultSummaryModel.trim()
- : "";
-
- var submitted = false;
- var timerExpired = false;
- var submitInFlight = false;
- var searchesDone = false;
- var stage = "results";
- var summaryMeta = null;
- var summaryRequestSeq = 0;
- var lastAutoSummarySignature = "";
- var lastInteraction = Date.now();
- var completedCount = 0;
- var es = null;
-
- var allQueries = queries.map(function(query, slotId) { return { slotId: slotId, query: query }; });
- var nextSlotId = queries.length;
- var queryIndexToSlot = new Map();
- var providerCoverage = new Map();
-
- var currentProvider = initialDefaultProvider;
- var initialStreamDone = queries.length === 0;
- var providerBatchInFlight = false;
- var batchLoadingProvider = null;
- var addSearchInFlight = 0;
- var isRegenerating = false;
-
- var timerEl = document.getElementById("timer");
- var timerAdjustEl = document.getElementById("timer-adjust");
- var timerInput = document.getElementById("timer-input");
- var timerSetBtn = document.getElementById("timer-set");
- var heroTitle = document.querySelector(".hero-title");
- var heroDesc = document.querySelector(".hero-desc");
- var resultCardsEl = document.getElementById("result-cards");
- var btnSend = document.getElementById("btn-send");
- var btnSendRaw = document.getElementById("btn-send-raw");
- var sendRawRow = document.getElementById("send-raw-row");
- var summaryPanel = document.getElementById("summary-panel");
- var summarySubtitle = document.getElementById("summary-subtitle");
- var summaryGeneratingEl = document.getElementById("summary-generating");
- var summaryGeneratingCopy = document.getElementById("summary-generating-copy");
- var summaryInput = document.getElementById("summary-input");
- var summaryFeedback = document.getElementById("summary-feedback");
- var btnSummaryBack = document.getElementById("btn-summary-back");
- var btnSummaryRegenerate = document.getElementById("btn-summary-regenerate");
- var btnSummaryPreview = document.getElementById("btn-summary-preview");
- var btnSummaryApprove = document.getElementById("btn-summary-approve");
- var successOverlay = document.getElementById("success-overlay");
- var successText = document.getElementById("success-text");
- var expiredOverlay = document.getElementById("expired-overlay");
- var expiredText = document.getElementById("expired-text");
- var closeCountdown = document.getElementById("close-countdown");
- var errorBanner = document.getElementById("error-banner");
- var addSearchInput = document.getElementById("add-search-input");
- var addSearchEl = document.getElementById("add-search");
- var addSearchWand = document.getElementById("add-search-wand");
- var heroStatus = document.getElementById("hero-status");
- var summaryProviderSelect = document.getElementById("summary-provider-select");
- var summaryModelSelect = document.getElementById("summary-model-select");
- var previewModal = document.getElementById("preview-modal");
- var previewModalBody = document.getElementById("preview-modal-body");
- var previewModalClose = document.getElementById("preview-modal-close");
- var previewModalModel = document.getElementById("preview-modal-model");
- var previewModalRegenerate = document.getElementById("preview-modal-regenerate");
- var previewModalApprove = document.getElementById("preview-modal-approve");
- var previewPopover = document.getElementById("preview-popover");
- var previewPopoverQuote = document.getElementById("preview-popover-quote");
- var previewPopoverInput = document.getElementById("preview-popover-input");
- var previewPopoverRegen = document.getElementById("preview-popover-regen");
- var providerButtons = Array.prototype.slice.call(document.querySelectorAll(".provider-btn"));
- var loadingPanelEl = null;
-
- var summaryModelsByProvider = Object.create(null);
- var summaryProviders = [];
- var currentSummaryProvider = "";
- var currentSummaryModel = "";
- var summaryPendingModel = "";
- var summaryGeneratingStartedAt = 0;
- var summaryGeneratingPhase = -1;
- var rewriteInFlight = false;
-
- function escHtml(s) {
- return String(s)
- .replace(/&/g, "&")
- .replace(//g, ">")
- .replace(/\"/g, """);
- }
-
- function sanitizeHref(url) {
- var value = typeof url === "string" ? url.trim() : "";
- return /^https?:\/\//i.test(value) ? value : "#";
- }
-
- function sanitizeMarkdownHtml(html) {
- var container = document.createElement("div");
- container.innerHTML = html;
-
- container.querySelectorAll("script, iframe, object, embed, form, style, link, meta, base")
- .forEach(function(el) { el.remove(); });
-
- var nodes = container.querySelectorAll("*");
- nodes.forEach(function(node) {
- for (var i = node.attributes.length - 1; i >= 0; i--) {
- var attr = node.attributes[i];
- if (/^on/i.test(attr.name)) node.removeAttribute(attr.name);
- }
- });
-
- var anchors = container.querySelectorAll("a[href]");
- anchors.forEach(function(anchor) {
- var safe = sanitizeHref(anchor.getAttribute("href") || "");
- anchor.setAttribute("href", safe);
- anchor.setAttribute("rel", "noopener noreferrer");
- anchor.setAttribute("target", "_blank");
- });
-
- var images = container.querySelectorAll("img[src]");
- images.forEach(function(img) {
- var safe = sanitizeHref(img.getAttribute("src") || "");
- if (safe === "#") {
- img.remove();
- } else {
- img.setAttribute("src", safe);
- }
- });
-
- return container.innerHTML;
- }
-
- function post(path, body) {
- return fetch(path, {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify(Object.assign({ token: token }, body)),
- });
- }
-
- function extractServerError(data) {
- if (!data || typeof data !== "object") return "";
- if (typeof data.error === "string" && data.error.trim()) return data.error.trim();
- return "";
- }
-
- function postJson(path, body) {
- return post(path, body).then(function(res) {
- return res.text().then(function(raw) {
- var data = null;
- if (raw) {
- try {
- data = JSON.parse(raw);
- } catch (err) {
- var parseMessage = err instanceof Error ? err.message : String(err);
- throw new Error("Invalid JSON response from " + path + ": " + parseMessage);
- }
- }
-
- if (!res.ok) {
- throw new Error(extractServerError(data) || ("HTTP " + res.status));
- }
-
- return data;
- });
- });
- }
-
- function formatTime(sec) {
- var m = Math.floor(sec / 60);
- var s = sec % 60;
- return m + ":" + (s < 10 ? "0" : "") + s;
- }
-
- function normalizeProvider(provider, fallback) {
- if (typeof provider === "string") {
- var normalized = provider.toLowerCase();
- if (providers.indexOf(normalized) !== -1) return normalized;
- }
- if (typeof fallback === "string") {
- var fallbackNormalized = fallback.toLowerCase();
- if (providers.indexOf(fallbackNormalized) !== -1) return fallbackNormalized;
- }
- return "";
- }
-
- function providerLabel(provider) {
- if (provider === "perplexity") return "Perplexity";
- if (provider === "exa") return "Exa";
- if (provider === "gemini") return "Gemini";
- return "Unknown";
- }
-
- function providerTagHtml(provider) {
- var normalized = normalizeProvider(provider, "");
- if (!normalized) return "";
- return '' + escHtml(providerLabel(normalized)) + "";
- }
-
- function buildAltChipsHtml(provider, queryText) {
- var normalizedProv = normalizeProvider(provider, "");
- if (!normalizedProv) return "";
- var altProviders = providers.filter(function(p) { return p !== normalizedProv && availProviders[p] === true; });
- if (altProviders.length === 0) return "";
- var html = 'Also try';
- for (var ap = 0; ap < altProviders.length; ap++) {
- html += '';
- }
- html += "
";
- return html;
- }
-
- function getSummaryProvider(modelValue) {
- if (typeof modelValue !== "string") return "";
- var trimmed = modelValue.trim();
- var slash = trimmed.indexOf("/");
- if (slash <= 0) return "";
- return trimmed.slice(0, slash);
- }
-
- function summaryProviderLabel(provider) {
- if (!provider) return "";
- if (provider === "openai") return "OpenAI";
- if (provider === "google") return "Google";
- if (provider === "anthropic") return "Anthropic";
- return provider.charAt(0).toUpperCase() + provider.slice(1);
- }
-
- function buildSummaryModelState() {
- summaryModelsByProvider = Object.create(null);
- summaryProviders = [];
- var seenValues = {};
-
- for (var i = 0; i < summaryModels.length; i++) {
- var model = summaryModels[i];
- if (!model || typeof model.value !== "string") continue;
- var value = model.value.trim();
- if (!value || seenValues[value]) continue;
- var provider = getSummaryProvider(value);
- if (!provider) continue;
- seenValues[value] = true;
-
- if (!summaryModelsByProvider[provider]) {
- summaryModelsByProvider[provider] = [];
- summaryProviders.push(provider);
- }
-
- var label = typeof model.label === "string" && model.label.trim().length > 0
- ? model.label.trim()
- : value;
- summaryModelsByProvider[provider].push({ value: value, label: label });
- }
- }
-
- function renderSummaryProviderSelect() {
- if (!summaryProviderSelect) return;
-
- summaryProviderSelect.innerHTML = "";
- for (var i = 0; i < summaryProviders.length; i++) {
- var provider = summaryProviders[i];
- var option = document.createElement("option");
- option.value = provider;
- option.textContent = summaryProviderLabel(provider);
- summaryProviderSelect.appendChild(option);
- }
- }
-
- function populateSummaryModelSelect(provider, preferredModel) {
- if (!summaryModelSelect) return;
-
- summaryModelSelect.innerHTML = "";
-
- var autoOption = document.createElement("option");
- autoOption.value = "";
- autoOption.textContent = "Auto";
- summaryModelSelect.appendChild(autoOption);
-
- var models = summaryModelsByProvider[provider] || [];
- for (var i = 0; i < models.length; i++) {
- var option = document.createElement("option");
- option.value = models[i].value;
- var shortLabel = models[i].value;
- var labelSlash = shortLabel.indexOf("/");
- if (labelSlash > 0) shortLabel = shortLabel.slice(labelSlash + 1);
- option.textContent = shortLabel;
- summaryModelSelect.appendChild(option);
- }
-
- var hasPreferred = false;
- if (preferredModel) {
- for (var j = 0; j < models.length; j++) {
- if (models[j].value === preferredModel) {
- hasPreferred = true;
- break;
- }
- }
- }
-
- if (hasPreferred) {
- summaryModelSelect.value = preferredModel;
- } else if (models.length > 0) {
- summaryModelSelect.value = models[0].value;
- } else {
- summaryModelSelect.value = "";
- }
-
- currentSummaryModel = typeof summaryModelSelect.value === "string"
- ? summaryModelSelect.value.trim()
- : "";
- }
-
- function setSummaryProvider(provider, preferredModel) {
- if (summaryProviders.indexOf(provider) === -1) return;
- currentSummaryProvider = provider;
-
- if (summaryProviderSelect) {
- summaryProviderSelect.value = provider;
- }
-
- populateSummaryModelSelect(provider, preferredModel);
- }
-
- function initializeSummaryModelControls() {
- buildSummaryModelState();
- renderSummaryProviderSelect();
-
- if (summaryProviders.length === 0) {
- currentSummaryProvider = "";
- currentSummaryModel = "";
- if (summaryProviderSelect) summaryProviderSelect.innerHTML = "";
- if (summaryModelSelect) {
- summaryModelSelect.innerHTML = '';
- summaryModelSelect.value = "";
- }
- return;
- }
-
- var defaultProvider = getSummaryProvider(defaultSummaryModel);
- if (defaultProvider && summaryProviders.indexOf(defaultProvider) !== -1) {
- setSummaryProvider(defaultProvider, defaultSummaryModel);
- return;
- }
-
- setSummaryProvider(summaryProviders[0], "");
- }
-
- function getSelectedSummaryModel() {
- if (!summaryModelSelect) return currentSummaryModel;
- if (typeof summaryModelSelect.value !== "string") return currentSummaryModel;
- currentSummaryModel = summaryModelSelect.value.trim();
- return currentSummaryModel;
- }
-
- function getFeedbackText() {
- if (!summaryFeedback || typeof summaryFeedback.value !== "string") return "";
- return summaryFeedback.value;
- }
-
- function getCoverageSet(provider) {
- var set = providerCoverage.get(provider);
- if (set) return set;
- set = new Set();
- providerCoverage.set(provider, set);
- return set;
- }
-
- function markCoverage(provider, slotId) {
- if (typeof slotId !== "number") return;
- var normalized = normalizeProvider(provider, "");
- if (!normalized) return;
- getCoverageSet(normalized).add(slotId);
- }
-
- function removeSlot(slotId) {
- allQueries = allQueries.filter(function(slot) { return slot.slotId !== slotId; });
-
- providerCoverage.forEach(function(coveredSlots) {
- coveredSlots.delete(slotId);
- });
-
- queryIndexToSlot.forEach(function(mappedSlotId, qi) {
- if (mappedSlotId === slotId) queryIndexToSlot.delete(qi);
- });
-
- syncLoadingPanel();
- }
-
- function isResultMutationLocked() {
- return submitted || timerExpired || submitInFlight;
- }
-
- function applyProviderInterlocks() {
- var disableProviders = isResultMutationLocked() || providerBatchInFlight || addSearchInFlight;
- for (var i = 0; i < providerButtons.length; i++) {
- var btn = providerButtons[i];
- var state = btn.dataset.state || "idle";
- btn.disabled = disableProviders || state === "loading";
- }
-
- var disableAddSearch = isResultMutationLocked();
- if (addSearchInput) {
- addSearchInput.disabled = disableAddSearch;
- }
-
- if (addSearchEl) {
- addSearchEl.style.opacity = disableAddSearch ? "0.6" : "";
- addSearchEl.style.pointerEvents = disableAddSearch ? "none" : "";
- }
-
- var cards = resultCardsEl ? resultCardsEl.querySelectorAll(".result-card") : [];
- cards.forEach(function(card) {
- var cb = card.querySelector("input[type=checkbox]");
- if (!cb) return;
- var searching = card.classList.contains("searching");
- var error = card.classList.contains("error");
- cb.disabled = searching || error || isResultMutationLocked();
- });
- }
-
- function recomputeProviderStates() {
- for (var i = 0; i < providerButtons.length; i++) {
- var btn = providerButtons[i];
- var provider = normalizeProvider(btn.dataset.provider, "");
- if (!provider) continue;
-
- var state = "idle";
- if (providerBatchInFlight && batchLoadingProvider === provider) {
- state = "loading";
- } else if (!initialStreamDone && queries.length > 0 && provider === initialDefaultProvider) {
- state = "loading";
- } else if (allQueries.length > 0) {
- var coveredSlots = providerCoverage.get(provider);
- if (coveredSlots && coveredSlots.size >= allQueries.length) {
- state = "searched";
- }
- }
-
- btn.dataset.state = state;
- btn.classList.remove("idle", "loading", "searched");
- btn.classList.add(state);
- btn.classList.toggle("is-default", provider === currentProvider);
- }
-
- applyProviderInterlocks();
- }
-
- function updateSummaryText() {
- if (completedCount <= 0) return;
- var totalCards = resultCardsEl.querySelectorAll(".result-card").length;
- var searchingCount = totalCards - completedCount;
- if (searchingCount > 0) {
- heroTitle.textContent = completedCount + " of " + totalCards + " Searches Complete";
- } else {
- heroTitle.textContent = completedCount + " Search" + (completedCount !== 1 ? "es" : "") + " Complete";
- }
- heroDesc.textContent = "Check the results to include, then generate and approve a summary.";
- if (heroStatus) heroStatus.textContent = completedCount + " completed" + (searchingCount > 0 ? ", " + searchingCount + " searching" : "");
- }
-
- function getSummaryDraftText() {
- if (!summaryInput || typeof summaryInput.value !== "string") return "";
- return summaryInput.value.trim();
- }
-
- function clearError() {
- if (!errorBanner) return;
- errorBanner.hidden = true;
- errorBanner.textContent = "";
- }
-
- function setError(text) {
- if (!errorBanner) return;
- errorBanner.textContent = text;
- errorBanner.hidden = false;
- }
-
- function updateSummaryGeneratingIndicator() {
- if (!summaryGeneratingCopy) return;
-
- if (stage !== "generating-summary") {
- summaryGeneratingCopy.textContent = "Generating summary draft…";
- summaryGeneratingPhase = -1;
- if (summaryGeneratingEl) {
- summaryGeneratingEl.removeAttribute("data-phase");
- }
- return;
- }
-
- if (summaryGeneratingStartedAt <= 0) {
- summaryGeneratingStartedAt = Date.now();
- }
-
- var elapsedMs = Date.now() - summaryGeneratingStartedAt;
- var nextPhase = Math.min(2, Math.floor(elapsedMs / 1800));
- if (nextPhase === summaryGeneratingPhase) return;
-
- summaryGeneratingPhase = nextPhase;
-
- var phaseLabel = "Planning summary";
- if (nextPhase === 1) phaseLabel = "Drafting summary";
- if (nextPhase === 2) phaseLabel = "Polishing summary";
-
- summaryGeneratingCopy.textContent = summaryPendingModel
- ? phaseLabel + " with " + summaryPendingModel + "…"
- : phaseLabel + "…";
-
- if (summaryGeneratingEl) {
- summaryGeneratingEl.dataset.phase = String(nextPhase);
- }
- }
-
- function updateStageUI() {
- var showSummary = stage === "summary-review" || stage === "generating-summary" || isRegenerating;
- if (summaryPanel) {
- summaryPanel.classList.toggle("hidden", !showSummary);
- summaryPanel.classList.toggle("updating", isRegenerating);
- }
- if (summarySubtitle) {
- var selCount = getSelectedIndices().length;
- var selLabel = selCount + " selected result" + (selCount !== 1 ? "s" : "");
- if (isRegenerating && stage === "generating-summary") {
- summarySubtitle.textContent = "Selection changed — regenerating summary…";
- } else if (isRegenerating) {
- summarySubtitle.textContent = "Selection changed — summary will regenerate shortly…";
- } else if (stage === "generating-summary") {
- summarySubtitle.textContent = summaryPendingModel
- ? "Summarizing " + selLabel + " with " + summaryPendingModel + "…"
- : "Summarizing " + selLabel + "…";
- } else if (summaryMeta && summaryMeta.fallbackUsed) {
- summarySubtitle.textContent = "Fallback summary of " + selLabel + ".";
- } else {
- summarySubtitle.textContent = "Summary of " + selLabel + ". Edit directly, regenerate with feedback, or approve.";
- }
- }
-
- if (summaryGeneratingEl) {
- var showGenerating = stage === "generating-summary" && !isRegenerating;
- summaryGeneratingEl.classList.toggle("hidden", !showGenerating);
- }
- updateSummaryGeneratingIndicator();
-
- if (summaryInput) {
- summaryInput.classList.toggle("hidden", stage === "generating-summary" && !isRegenerating);
- summaryInput.disabled = submitted || timerExpired || stage === "generating-summary" || submitInFlight || isRegenerating;
- }
- if (summaryFeedback) {
- summaryFeedback.disabled = submitted || timerExpired || submitInFlight || stage === "generating-summary" || isRegenerating;
- }
- var disableSummaryModelControls = submitted || timerExpired || stage === "generating-summary" || submitInFlight || summaryProviders.length === 0;
- if (summaryProviderSelect) {
- summaryProviderSelect.disabled = disableSummaryModelControls;
- }
- if (summaryModelSelect) {
- summaryModelSelect.disabled = disableSummaryModelControls;
- }
-
- var inResults = stage === "results";
- var hasSelection = getSelectedIndices().length > 0;
- var hasCompleted = getCompletedSelectableIndices().length > 0;
- var canGenerate = inResults && !submitted && !timerExpired && !submitInFlight && hasCompleted;
-
- if (btnSend) {
- if (stage === "generating-summary") {
- btnSend.textContent = "Generating summary…";
- btnSend.disabled = true;
- } else if (!inResults) {
- btnSend.textContent = "Summary ready";
- btnSend.disabled = true;
- } else if (!hasCompleted) {
- btnSend.textContent = searchesDone ? "No results yet" : "Waiting for results…";
- btnSend.disabled = true;
- } else {
- btnSend.textContent = hasSelection ? "Generate summary" : "Select results to summarize";
- btnSend.disabled = !canGenerate || !hasSelection;
- }
- }
- if (sendRawRow) {
- sendRawRow.classList.toggle("hidden", !hasSelection || submitted || timerExpired);
- }
- if (btnSendRaw) {
- btnSendRaw.disabled = !hasSelection || submitted || timerExpired || submitInFlight;
- }
-
- if (btnSummaryBack) btnSummaryBack.disabled = submitted || timerExpired || submitInFlight || (stage === "generating-summary" && !isRegenerating);
- if (btnSummaryRegenerate) btnSummaryRegenerate.disabled = submitted || timerExpired || submitInFlight || stage === "generating-summary" || isRegenerating;
- var hasDraft = getSummaryDraftText().length > 0;
- if (btnSummaryPreview) btnSummaryPreview.disabled = !hasDraft || stage === "generating-summary";
- if (btnSummaryApprove) {
- btnSummaryApprove.disabled = submitted || timerExpired || submitInFlight || stage === "generating-summary" || isRegenerating || !hasSelection || !hasDraft;
- }
-
- applyProviderInterlocks();
- }
-
- function shouldShowLoadingPanel() {
- if (submitted || timerExpired || searchesDone) return false;
- if (completedCount > 0) return false;
- return allQueries.length > 0;
- }
-
- function ensureLoadingPanel() {
- if (loadingPanelEl) return loadingPanelEl;
- if (!resultCardsEl) return null;
-
- var panel = document.createElement("div");
- panel.className = "result-loading";
- panel.innerHTML =
- '' +
- '';
-
- resultCardsEl.prepend(panel);
- loadingPanelEl = panel;
- return panel;
- }
-
- function updateLoadingPanelSummary() {
- if (!loadingPanelEl) return;
- var sub = loadingPanelEl.querySelector(".result-loading-sub");
- if (!sub) return;
-
- var total = allQueries.length;
- if (total <= 0) {
- sub.textContent = "Searching\u2026";
- return;
- }
-
- var done = Math.min(completedCount, total);
- var noun = total === 1 ? "query" : "queries";
- sub.textContent = "Searching " + done + "/" + total + " " + noun + "\u2026";
- }
-
- function syncLoadingPanel() {
- if (shouldShowLoadingPanel()) {
- if (!ensureLoadingPanel()) return;
- updateLoadingPanelSummary();
- return;
- }
-
- if (loadingPanelEl) {
- loadingPanelEl.remove();
- loadingPanelEl = null;
- }
- }
-
- function renderErrorCard(card, queryText, errorText, provider) {
- var tag = providerTagHtml(provider);
- card.innerHTML =
- '" +
- '' + escHtml(errorText || "Search failed") + "
";
- }
-
- function populateResultCard(card, data, queryText, provider) {
- var sourceCount = data.results ? data.results.length : 0;
- var domains = [];
- if (data.results) {
- for (var i = 0; i < Math.min(data.results.length, 3); i++) {
- domains.push(data.results[i].domain);
- }
- }
- var metaText = sourceCount + " source" + (sourceCount !== 1 ? "s" : "");
- if (domains.length > 0) metaText += " \u00B7 " + domains.join(", ");
- if (sourceCount > 3) metaText += ", +" + (sourceCount - 3);
-
- var preview = "";
- if (data.answer) {
- preview = data.answer.substring(0, 200).replace(/\\n+/g, " ").replace(/[#*_\\[\\]]/g, "");
- }
-
- var bodyHtml = "";
- if (data.answer) {
- var rendered = typeof marked !== "undefined" && marked.parse
- ? marked.parse(data.answer, { breaks: true })
- : "" + escHtml(data.answer) + "
";
- bodyHtml += '' + sanitizeMarkdownHtml(rendered) + "
";
- }
- if (data.results && data.results.length > 0) {
- bodyHtml += 'Sources
';
- for (var k = 0; k < data.results.length; k++) {
- var r = data.results[k];
- var label = r.title && r.title.indexOf("Source ") !== 0 ? r.title : r.url;
- var href = sanitizeHref(r.url);
- bodyHtml += '
' + escHtml(label) + '' + escHtml(r.domain) + "";
- }
- bodyHtml += "
";
- }
-
- var altChipsHtml = buildAltChipsHtml(provider, queryText);
-
- card.innerHTML =
- '" +
- altChipsHtml +
- '' + bodyHtml + "
";
- }
-
- function applyResponseToCard(card, data, queryText, providerHint, slotHint) {
- if (!card || !data) return;
- if (submitted || timerExpired) return;
-
- var queryIndex = typeof data.queryIndex === "number" ? data.queryIndex : null;
- if (queryIndex !== null) {
- card.dataset.qi = String(queryIndex);
- }
-
- var slotId = typeof slotHint === "number" ? slotHint : (queryIndex !== null ? queryIndexToSlot.get(queryIndex) : undefined);
- if (typeof slotId !== "number" && queryIndex !== null) {
- slotId = queryIndex;
- }
- if (queryIndex !== null && typeof slotId === "number") {
- queryIndexToSlot.set(queryIndex, slotId);
- }
-
- var provider = normalizeProvider(data.provider, providerHint);
-
- card.classList.remove("searching", "checked", "error");
-
- if (data.error) {
- card.classList.add("error");
- renderErrorCard(card, queryText, data.error, provider);
- } else {
- card.classList.add("checked");
- populateResultCard(card, data, queryText, provider);
- setupCardInteraction(card);
- }
-
- if (card.dataset.completed !== "true") {
- completedCount++;
- card.dataset.completed = "true";
- }
- markCoverage(provider, slotId);
- updateSummaryText();
- syncLoadingPanel();
- recomputeProviderStates();
- updateStageUI();
- maybeAutoGenerateSummary();
- resetTimer();
- }
-
- function resetTimer() { lastInteraction = Date.now(); }
-
- function updateTimer() {
- var idleSec = Math.floor((Date.now() - lastInteraction) / 1000);
- var remaining = Math.max(0, timeoutSec - idleSec);
- timerEl.textContent = formatTime(remaining);
-
- timerEl.classList.remove("warn", "urgent", "active");
- if (remaining <= 15) timerEl.classList.add("urgent");
- else if (remaining <= 30) timerEl.classList.add("warn");
- else if (remaining < timeoutSec) timerEl.classList.add("active");
-
- updateSummaryGeneratingIndicator();
-
- if (remaining <= 0 && !submitted && !timerExpired) onTimeout();
- }
-
- setInterval(updateTimer, 1000);
- updateTimer();
-
- ["click", "keydown", "input", "change"].forEach(function(evt) {
- document.addEventListener(evt, resetTimer, { passive: true });
- });
- document.addEventListener("scroll", resetTimer, { passive: true });
- document.addEventListener("mousemove", resetTimer, { passive: true });
-
- timerEl.addEventListener("click", function(e) {
- e.stopPropagation();
- timerInput.value = timeoutSec;
- timerAdjustEl.classList.add("visible");
- timerEl.style.display = "none";
- timerInput.focus();
- timerInput.select();
- });
-
- function applyTimerAdjust() {
- var val = parseInt(timerInput.value, 10);
- if (val && val > 0) timeoutSec = Math.min(val, 600);
- timerAdjustEl.classList.remove("visible");
- timerEl.style.display = "";
- resetTimer();
- }
-
- timerSetBtn.addEventListener("click", function(e) { e.stopPropagation(); applyTimerAdjust(); });
- timerInput.addEventListener("keydown", function(e) {
- if (e.key === "Enter") { e.preventDefault(); applyTimerAdjust(); }
- if (e.key === "Escape") { timerAdjustEl.classList.remove("visible"); timerEl.style.display = ""; }
- e.stopPropagation();
- });
- document.addEventListener("click", function() {
- if (timerAdjustEl.classList.contains("visible")) {
- timerAdjustEl.classList.remove("visible");
- timerEl.style.display = "";
- }
- });
-
- function setDefaultProvider(provider, persist) {
- var normalized = normalizeProvider(provider, currentProvider);
- if (!normalized) return;
- currentProvider = normalized;
- recomputeProviderStates();
- if (persist) {
- postJson("/provider", { provider: normalized }).then(function(data) {
- if (data && data.ok === false) {
- throw new Error(extractServerError(data) || "request rejected");
- }
- }).catch(function(err) {
- var message = err instanceof Error ? err.message : String(err);
- setError("Failed to save provider preference: " + (message || "unknown error"));
- });
- }
- }
-
- providerButtons.forEach(function(btn) {
- btn.addEventListener("click", function() {
- if (isResultMutationLocked()) return;
- if (providerBatchInFlight || addSearchInFlight) return;
-
- var provider = normalizeProvider(btn.dataset.provider, "");
- if (!provider) return;
-
- var state = btn.dataset.state || "idle";
- if (state === "loading") return;
-
- if (state === "searched") {
- if (provider === currentProvider) return;
- setDefaultProvider(provider, true);
- resetTimer();
- return;
- }
-
- setDefaultProvider(provider, true);
- if (allQueries.length === 0) {
- resetTimer();
- return;
- }
-
- interruptSummaryIfNeeded();
- providerBatchInFlight = true;
- batchLoadingProvider = provider;
- recomputeProviderStates();
-
- var batchQueries = allQueries.slice();
- var inflight = batchQueries.length;
- if (inflight === 0) {
- providerBatchInFlight = false;
- batchLoadingProvider = null;
- recomputeProviderStates();
- return;
- }
-
- var batchCards = [];
- for (var bi = 0; bi < batchQueries.length; bi++) {
- var bq = batchQueries[bi];
- var card = document.createElement("div");
- card.className = "result-card searching";
- card.innerHTML =
- '" +
- buildAltChipsHtml(provider, bq.query);
- resultCardsEl.appendChild(card);
- batchCards.push(card);
- }
- updateSummaryText();
-
- batchQueries.forEach(function(slot, si) {
- var searchingCard = batchCards[si];
- postJson("/search", { query: slot.query, provider: provider })
- .then(function(data) {
- if (submitted || timerExpired) return;
- if (!data || data.ok === false) {
- applyResponseToCard(searchingCard, {
- answer: "",
- results: [],
- error: extractServerError(data) || "Search failed",
- provider: provider,
- }, slot.query, provider, slot.slotId);
- return;
- }
- applyResponseToCard(searchingCard, data, slot.query, provider, slot.slotId);
- })
- .catch(function(err) {
- if (submitted || timerExpired) return;
- var message = err instanceof Error ? err.message : String(err);
- applyResponseToCard(searchingCard, {
- answer: "",
- results: [],
- error: message || "Search failed",
- provider: provider,
- }, slot.query, provider, slot.slotId);
- })
- .finally(function() {
- inflight -= 1;
- if (inflight <= 0) {
- providerBatchInFlight = false;
- batchLoadingProvider = null;
- recomputeProviderStates();
- updateStageUI();
- maybeAutoGenerateSummary();
- }
- });
- });
-
- resetTimer();
- });
- });
-
- if (resultCardsEl) {
- resultCardsEl.addEventListener("click", function(e) {
- if (!(e.target instanceof Element)) return;
- var chip = e.target.closest(".card-alt-chip");
- if (!chip) return;
- if (isResultMutationLocked()) return;
-
- var altProvider = chip.dataset.altProvider;
- var altQuery = chip.dataset.altQuery;
- if (!altProvider || !altQuery) return;
-
- interruptSummaryIfNeeded();
-
- chip.classList.add("loading");
- chip.disabled = true;
- resetTimer();
-
- var slotId = nextSlotId++;
- allQueries.push({ slotId: slotId, query: altQuery });
-
- var parentCard = chip.closest(".result-card");
- var newCard = document.createElement("div");
- newCard.className = "result-card searching";
- newCard.innerHTML =
- '" +
- buildAltChipsHtml(altProvider, altQuery);
- if (parentCard && parentCard.nextSibling) {
- resultCardsEl.insertBefore(newCard, parentCard.nextSibling);
- } else {
- resultCardsEl.appendChild(newCard);
- }
- updateSummaryText();
-
- postJson("/search", { query: altQuery, provider: altProvider })
- .then(function(data) {
- if (submitted || timerExpired) return;
- if (!data || data.ok === false) {
- applyResponseToCard(newCard, {
- answer: "", results: [],
- error: extractServerError(data) || "Search failed",
- provider: altProvider,
- }, altQuery, altProvider, slotId);
- return;
- }
- applyResponseToCard(newCard, data, altQuery, altProvider, slotId);
- })
- .catch(function(err) {
- removeSlot(slotId);
- newCard.remove();
- var message = err instanceof Error ? err.message : String(err);
- setError("Re-search failed: " + (message || "Search failed"));
- updateSummaryText();
- })
- .finally(function() {
- chip.classList.remove("loading");
- chip.disabled = false;
- recomputeProviderStates();
- updateStageUI();
- maybeAutoGenerateSummary();
- });
- });
- }
-
- if (addSearchInput && addSearchWand) {
- addSearchInput.addEventListener("input", function() {
- addSearchWand.disabled = rewriteInFlight || !addSearchInput.value.trim() || isResultMutationLocked();
- });
-
- addSearchWand.addEventListener("click", function() {
- var text = addSearchInput.value.trim();
- if (!text || rewriteInFlight || isResultMutationLocked()) return;
- rewriteInFlight = true;
- addSearchWand.disabled = true;
- addSearchWand.classList.add("rewriting");
- resetTimer();
-
- postJson("/rewrite", { query: text })
- .then(function(data) {
- if (!data || data.ok === false) {
- throw new Error(extractServerError(data) || "Rewrite failed");
- }
- var rewritten = typeof data.query === "string" ? data.query.trim() : "";
- if (rewritten) {
- addSearchInput.value = rewritten;
- addSearchInput.focus();
- }
- })
- .catch(function(err) {
- var message = err instanceof Error ? err.message : String(err);
- setError("Rewrite failed: " + (message || "unknown error"));
- })
- .finally(function() {
- rewriteInFlight = false;
- addSearchWand.classList.remove("rewriting");
- addSearchWand.disabled = !addSearchInput.value.trim() || isResultMutationLocked();
- });
- });
- }
-
- addSearchInput.addEventListener("keydown", function(e) {
- if (e.key !== "Enter") return;
- var text = addSearchInput.value.trim();
- if (!text || isResultMutationLocked()) return;
- interruptSummaryIfNeeded();
- e.preventDefault();
- e.stopPropagation();
-
- addSearchInFlight++;
- applyProviderInterlocks();
- addSearchInput.value = "";
-
- var slotId = nextSlotId++;
- allQueries.push({ slotId: slotId, query: text });
- syncLoadingPanel();
- recomputeProviderStates();
-
- var requestedProvider = currentProvider;
-
- var card = document.createElement("div");
- card.className = "result-card searching";
- card.innerHTML =
- '" +
- buildAltChipsHtml(requestedProvider, text);
- resultCardsEl.appendChild(card);
- updateSummaryText();
- resetTimer();
-
- postJson("/search", { query: text, provider: requestedProvider })
- .then(function(data) {
- if (!data || data.ok === false) {
- removeSlot(slotId);
- card.remove();
- setError("Failed to add search: " + (extractServerError(data) || "Search failed"));
- recomputeProviderStates();
- updateSummaryText();
- return;
- }
-
- if (submitted || timerExpired) return;
-
- applyResponseToCard(card, data, text, requestedProvider, slotId);
- })
- .catch(function(err) {
- removeSlot(slotId);
- card.remove();
- var message = err instanceof Error ? err.message : String(err);
- setError("Failed to add search: " + (message || "Search failed"));
- recomputeProviderStates();
- updateSummaryText();
- })
- .finally(function() {
- addSearchInFlight--;
- recomputeProviderStates();
- updateStageUI();
- maybeAutoGenerateSummary();
- });
- });
-
- function showSuccess(text) {
- if (es) { es.close(); es = null; }
- closePreviewModal();
- successText.textContent = text;
- successOverlay.classList.remove("hidden");
- setTimeout(function() { window.close(); }, 800);
- }
-
- function showExpired(text) {
- if (es) { es.close(); es = null; }
- closePreviewModal();
- expiredText.textContent = text;
- expiredOverlay.classList.remove("hidden");
- requestAnimationFrame(function() { expiredOverlay.classList.add("visible"); });
- }
-
- function startOverlayCloseCountdown(seconds) {
- var count = seconds;
- closeCountdown.textContent = count;
- var iv = setInterval(function() {
- count--;
- closeCountdown.textContent = count;
- if (count <= 0) {
- clearInterval(iv);
- window.close();
- }
- }, 1000);
- }
-
- function submitPayload(payload, successText) {
- if (submitInFlight) return Promise.reject(new Error("Submit already in progress"));
- submitInFlight = true;
- submitted = true;
- syncLoadingPanel();
- updateStageUI();
- clearError();
-
- return postJson("/submit", payload)
- .then(function(data) {
- if (data && data.ok === false) {
- throw new Error(extractServerError(data) || "submit rejected");
- }
- showSuccess(successText);
- })
- .catch(function(err) {
- submitInFlight = false;
- submitted = false;
- syncLoadingPanel();
- updateStageUI();
- throw err;
- });
- }
-
- function submitWithTimeoutFallback(payload) {
- if (submitInFlight) return;
- submitInFlight = true;
- submitted = true;
- timerExpired = true;
- syncLoadingPanel();
- updateStageUI();
- clearError();
- showExpired("Time\u2019s up \u2014 submitting current summary state.");
-
- function finalizeClose() {
- submitInFlight = false;
- startOverlayCloseCountdown(5);
- }
-
- function toErrorMessage(err) {
- return err instanceof Error ? err.message : String(err);
- }
-
- function attemptCancelFallback(submitErrorMessage) {
- return postJson("/cancel", { reason: "timeout" })
- .catch(function(cancelErr) {
- console.error("Timeout finalize failed after submit errors:", submitErrorMessage, "| cancel:", toErrorMessage(cancelErr));
- })
- .finally(finalizeClose);
- }
-
- postJson("/submit", payload)
- .then(function(data) {
- if (data && data.ok === false) {
- throw new Error(extractServerError(data) || "submit rejected");
- }
- finalizeClose();
- })
- .catch(function(firstErr) {
- var firstMessage = toErrorMessage(firstErr);
- setTimeout(function() {
- postJson("/submit", payload)
- .then(function(data) {
- if (data && data.ok === false) {
- throw new Error(extractServerError(data) || "submit rejected");
- }
- finalizeClose();
- })
- .catch(function(secondErr) {
- var secondMessage = toErrorMessage(secondErr);
- attemptCancelFallback(firstMessage + " | " + secondMessage);
- });
- }, 250);
- });
- }
-
- function onTimeout() {
- if (submitted || timerExpired) return;
- var timeoutSelected = getTimeoutSelectedIndices();
- var payload = { selected: timeoutSelected };
- var draft = getSummaryDraftText();
- if (stage === "summary-review" && draft.length > 0) {
- payload.summary = draft;
- if (summaryMeta) payload.summaryMeta = summaryMeta;
- }
- submitWithTimeoutFallback(payload);
- }
-
- if (queries.length === 0) {
- heroTitle.textContent = "What do you need?";
- heroDesc.textContent = "Search for anything below, then generate and approve a summary.";
- if (heroStatus) heroStatus.textContent = "";
- btnSend.textContent = "No results yet";
- } else {
- for (var i = 0; i < queries.length; i++) {
- queryIndexToSlot.set(i, i);
- var card = document.createElement("div");
- card.className = "result-card searching";
- card.dataset.qi = i;
- card.innerHTML =
- '" +
- buildAltChipsHtml(initialDefaultProvider, queries[i]);
- resultCardsEl.appendChild(card);
- }
- }
-
- initializeSummaryModelControls();
- syncLoadingPanel();
- recomputeProviderStates();
- updateStageUI();
-
- es = new EventSource("/events?session=" + encodeURIComponent(token));
-
- function parseSseEventData(eventName, e) {
- try {
- return JSON.parse(e.data);
- } catch (err) {
- var message = err instanceof Error ? err.message : String(err);
- setError("Invalid " + eventName + " event payload: " + (message || "unknown parse error"));
- return null;
- }
- }
-
- es.addEventListener("result", function(e) {
- var data = parseSseEventData("result", e);
- if (!data) return;
-
- var card = resultCardsEl.querySelector('.result-card[data-qi="' + data.queryIndex + '"]');
- if (!card) return;
-
- var slotId = queryIndexToSlot.get(data.queryIndex);
- if (typeof slotId !== "number") slotId = data.queryIndex;
- applyResponseToCard(card, data, data.query || queries[data.queryIndex], data.provider, slotId);
- });
-
- es.addEventListener("search-error", function(e) {
- var data = parseSseEventData("search-error", e);
- if (!data) return;
-
- var card = resultCardsEl.querySelector('.result-card[data-qi="' + data.queryIndex + '"]');
- if (!card) return;
-
- var slotId = queryIndexToSlot.get(data.queryIndex);
- if (typeof slotId !== "number") slotId = data.queryIndex;
- applyResponseToCard(card, {
- queryIndex: data.queryIndex,
- answer: "",
- results: [],
- error: data.error || "Search failed",
- provider: data.provider,
- }, data.query || queries[data.queryIndex], data.provider, slotId);
- });
-
- es.addEventListener("done", function() {
- searchesDone = true;
- initialStreamDone = true;
- if (completedCount > 0) {
- updateSummaryText();
- }
- syncLoadingPanel();
- recomputeProviderStates();
- updateStageUI();
- maybeAutoGenerateSummary();
- resetTimer();
- });
-
- es.onerror = function() {
- // EventSource reconnects automatically.
- };
-
- function setupCardInteraction(card) {
- var header = card.querySelector(".result-card-header");
- var body = card.querySelector(".result-card-body");
- var cb = card.querySelector("input[type=checkbox]");
- var expandEl = card.querySelector(".result-card-expand");
-
- if (!header || !cb) return;
-
- header.addEventListener("click", function(e) {
- if (e.target.tagName === "A") return;
- if (e.target === cb) {
- if (isResultMutationLocked()) {
- e.preventDefault();
- return;
- }
- card.classList.toggle("checked", cb.checked);
- if (stage === "summary-review" || stage === "generating-summary") {
- interruptSummaryIfNeeded();
- }
- updateStageUI();
- maybeAutoGenerateSummary();
- return;
- }
- var isExpanded = body && body.classList.contains("open");
- if (body) body.classList.toggle("open");
- if (expandEl) expandEl.textContent = isExpanded ? "\u25BC" : "\u25B2";
- });
-
- if (body) {
- body.addEventListener("click", function(e) {
- e.stopPropagation();
- });
- }
- }
-
- function getSelectedIndices() {
- var indices = [];
- var cards = resultCardsEl.querySelectorAll(".result-card");
- cards.forEach(function(card) {
- if (card.dataset.completed !== "true") return;
- if (card.classList.contains("error")) return;
- var cb = card.querySelector("input[type=checkbox]");
- if (!cb || !cb.checked) return;
- var qi = parseInt(card.dataset.qi, 10);
- if (!Number.isNaN(qi)) indices.push(qi);
- });
- return indices;
- }
-
- function getCompletedSelectableIndices() {
- var indices = [];
- var cards = resultCardsEl.querySelectorAll(".result-card");
- cards.forEach(function(card) {
- if (card.dataset.completed !== "true") return;
- if (card.classList.contains("error")) return;
- var qi = parseInt(card.dataset.qi, 10);
- if (!Number.isNaN(qi)) indices.push(qi);
- });
- return indices;
- }
-
- function hasPendingSearchCards() {
- var cards = resultCardsEl.querySelectorAll(".result-card");
- for (var i = 0; i < cards.length; i++) {
- var card = cards[i];
- if (card.dataset.completed !== "true") return true;
- }
- return addSearchInFlight || providerBatchInFlight;
- }
-
- function getTimeoutSelectedIndices() {
- var selected = getSelectedIndices();
- if (selected.length > 0) return selected;
- return getCompletedSelectableIndices();
- }
-
- function normalizeSummaryMeta(meta, edited) {
- if (!meta || typeof meta !== "object") {
- return {
- model: null,
- durationMs: 0,
- tokenEstimate: 0,
- fallbackUsed: false,
- edited: !!edited,
- };
- }
-
- return {
- model: typeof meta.model === "string" || meta.model === null ? meta.model : null,
- durationMs: typeof meta.durationMs === "number" && Number.isFinite(meta.durationMs) && meta.durationMs >= 0 ? meta.durationMs : 0,
- tokenEstimate: typeof meta.tokenEstimate === "number" && Number.isFinite(meta.tokenEstimate) && meta.tokenEstimate >= 0 ? meta.tokenEstimate : 0,
- fallbackUsed: meta.fallbackUsed === true,
- fallbackReason: typeof meta.fallbackReason === "string" ? meta.fallbackReason : undefined,
- edited: !!edited,
- };
- }
-
- function isSummaryModelSelectionError(message) {
- if (typeof message !== "string") return false;
- return message.indexOf("Invalid summary model") !== -1
- || message.indexOf("Summary model not found") !== -1
- || message.indexOf("No API key available for summary model") !== -1
- || message.indexOf("Invalid provider") !== -1;
- }
-
- function resetSummaryGeneratingState() {
- summaryPendingModel = "";
- summaryGeneratingStartedAt = 0;
- summaryGeneratingPhase = -1;
- }
-
- function cancelInFlightSummaryRequest() {
- summaryRequestSeq += 1;
- resetSummaryGeneratingState();
- }
-
- function interruptSummaryIfNeeded() {
- if (stage !== "generating-summary" && stage !== "summary-review") return;
- if (stage === "generating-summary") {
- cancelInFlightSummaryRequest();
- }
- clearError();
- isRegenerating = getSummaryDraftText().length > 0;
- stage = "results";
- updateStageUI();
- }
-
- function exitRegeneratingState() {
- if (!isRegenerating) return false;
- if (stage === "generating-summary") {
- cancelInFlightSummaryRequest();
- }
- isRegenerating = false;
- clearError();
- stage = "results";
- updateStageUI();
- return true;
- }
-
- function requestSummary(indices, feedback) {
- if (submitted || timerExpired || submitInFlight) return;
-
- if (!Array.isArray(indices) || indices.length === 0) {
- setError("Select at least one result to summarize");
- stage = "results";
- updateStageUI();
- return;
- }
-
- if (hasPendingSearchCards()) {
- setError("Wait for running searches to finish before generating summary");
- stage = "results";
- updateStageUI();
- return;
- }
-
- clearError();
- var previousStage = stage;
- var wasRegenerating = isRegenerating;
- var selectedSummaryModel = getSelectedSummaryModel();
- summaryPendingModel = selectedSummaryModel;
- summaryGeneratingStartedAt = Date.now();
- summaryGeneratingPhase = -1;
- stage = "generating-summary";
- updateStageUI();
-
- var requestId = ++summaryRequestSeq;
- var feedbackText = typeof feedback === "string" ? feedback.trim() : "";
- var summarizePayload = { selected: indices };
- if (selectedSummaryModel.length > 0) {
- summarizePayload.model = selectedSummaryModel;
- }
- if (feedbackText.length > 0) {
- summarizePayload.feedback = feedbackText;
- }
-
- postJson("/summarize", summarizePayload)
- .then(function(data) {
- if (requestId !== summaryRequestSeq) return data;
- if (!data || data.ok === false) {
- throw new Error(extractServerError(data) || "summary request rejected");
- }
- return data;
- })
- .catch(function(err) {
- if (requestId !== summaryRequestSeq) throw err;
-
- var firstMessage = err instanceof Error ? err.message : String(err);
- if (selectedSummaryModel.length === 0 || !isSummaryModelSelectionError(firstMessage)) {
- throw err;
- }
-
- summaryPendingModel = "";
- updateStageUI();
-
- var retryPayload = { selected: indices };
- if (feedbackText.length > 0) {
- retryPayload.feedback = feedbackText;
- }
- return postJson("/summarize", retryPayload).then(function(retryData) {
- if (!retryData || retryData.ok === false) {
- throw new Error(extractServerError(retryData) || "summary request rejected");
- }
- return retryData;
- }).catch(function(retryErr) {
- var retryMessage = retryErr instanceof Error ? retryErr.message : String(retryErr);
- throw new Error(firstMessage + " (auto retry failed: " + (retryMessage || "unknown error") + ")");
- });
- })
- .then(function(data) {
- if (requestId !== summaryRequestSeq) return;
-
- var summaryText = typeof data.summary === "string" ? data.summary.trim() : "";
- if (!summaryText) {
- throw new Error("Summary response was empty");
- }
-
- if (summaryInput) {
- summaryInput.value = summaryText;
- }
- if (summaryFeedback) {
- summaryFeedback.value = "";
- }
- summaryMeta = normalizeSummaryMeta(data.meta || null, false);
- lastAutoSummarySignature = selectionSignature(indices);
- resetSummaryGeneratingState();
- isRegenerating = false;
- stage = "summary-review";
- updateStageUI();
- })
- .catch(function(err) {
- if (requestId !== summaryRequestSeq) return;
- var message = err instanceof Error ? err.message : String(err);
- setError("Failed to generate summary — " + (message || "unknown error"));
- resetSummaryGeneratingState();
- isRegenerating = false;
- if (wasRegenerating && getSummaryDraftText().length > 0) {
- stage = "summary-review";
- } else {
- stage = previousStage === "summary-review" ? "summary-review" : "results";
- }
- updateStageUI();
- });
- }
-
- function selectionSignature(indices) {
- return indices.slice().sort(function(a, b) { return a - b; }).join(",");
- }
-
- function maybeAutoGenerateSummary() {
- if (workflow !== "summary-review") return;
- if (!searchesDone) return;
- if (stage !== "results") return;
- if (submitted || timerExpired || submitInFlight) return;
- if (hasPendingSearchCards()) return;
-
- var selected = getSelectedIndices();
- if (selected.length === 0) {
- if (isRegenerating) {
- isRegenerating = false;
- updateStageUI();
- }
- return;
- }
-
- var signature = selectionSignature(selected);
- if (signature === lastAutoSummarySignature) {
- if (isRegenerating) {
- isRegenerating = false;
- if (getSummaryDraftText().length > 0) {
- stage = "summary-review";
- }
- updateStageUI();
- }
- return;
- }
-
- lastAutoSummarySignature = signature;
- requestSummary(selected);
- }
-
- function doApprove() {
- if (submitted || timerExpired || submitInFlight || stage !== "summary-review") return;
-
- var selected = getSelectedIndices();
- if (selected.length === 0) {
- setError("Select at least one result before approving");
- updateStageUI();
- return;
- }
-
- var draft = getSummaryDraftText();
- var payload = { selected: selected };
- if (draft.length > 0) {
- payload.summary = draft;
- payload.summaryMeta = normalizeSummaryMeta(summaryMeta, summaryMeta && summaryMeta.edited === true);
- }
-
- submitPayload(payload, "Summary approved")
- .catch(function(err) {
- var message = err instanceof Error ? err.message : String(err);
- setError("Failed to approve summary — " + (message || "the agent may have moved on"));
- });
- }
-
- function doCancel() {
- if (submitted || timerExpired || submitInFlight) return;
- submitted = true;
- submitInFlight = true;
- syncLoadingPanel();
- updateStageUI();
- clearError();
-
- postJson("/cancel", { reason: "user" })
- .then(function(data) {
- if (data && data.ok === false) {
- throw new Error(extractServerError(data) || "cancel rejected");
- }
- showSuccess("Skipped");
- })
- .catch(function(err) {
- submitted = false;
- submitInFlight = false;
- syncLoadingPanel();
- updateStageUI();
- var message = err instanceof Error ? err.message : String(err);
- setError("Failed to cancel — " + (message || "the agent may have moved on"));
- });
- }
-
- btnSend.addEventListener("click", function() {
- if (stage !== "results") return;
- requestSummary(getSelectedIndices());
- });
-
- if (btnSendRaw) {
- btnSendRaw.addEventListener("click", function() {
- var selected = getSelectedIndices();
- if (selected.length === 0) return;
- submitPayload({ selected: selected, rawResults: true }, "Results sent")
- .catch(function(err) {
- var message = err instanceof Error ? err.message : String(err);
- setError("Failed to send results — " + (message || "the agent may have moved on"));
- });
- });
- }
-
- if (btnSummaryBack) {
- btnSummaryBack.addEventListener("click", function() {
- if (exitRegeneratingState()) {
- resetTimer();
- return;
- }
- if (stage !== "summary-review") return;
- clearError();
- stage = "results";
- updateStageUI();
- resetTimer();
- });
- }
-
- if (btnSummaryRegenerate) {
- btnSummaryRegenerate.addEventListener("click", function() {
- requestSummary(getSelectedIndices(), getFeedbackText());
- resetTimer();
- });
- }
-
- function openPreviewModal() {
- var draft = getSummaryDraftText();
- if (!draft || !previewModal || !previewModalBody) return;
- var rendered = typeof marked !== "undefined" && marked.parse
- ? marked.parse(draft, { breaks: true })
- : "" + escHtml(draft) + "
";
- previewModalBody.innerHTML = sanitizeMarkdownHtml(rendered);
- if (previewModalModel) {
- previewModalModel.innerHTML = '';
- for (var i = 0; i < summaryModels.length; i++) {
- var m = summaryModels[i];
- var opt = document.createElement("option");
- opt.value = m.value;
- opt.textContent = m.label;
- previewModalModel.appendChild(opt);
- }
- previewModalModel.value = getSelectedSummaryModel() || "";
- }
- previewModal.classList.remove("hidden");
- resetTimer();
- }
-
- function closePreviewModal() {
- if (previewModal) previewModal.classList.add("hidden");
- if (previewModalBody) previewModalBody.innerHTML = "";
- hidePreviewPopover();
- }
-
- var popoverSelectedText = "";
-
- function hidePreviewPopover() {
- if (previewPopover) previewPopover.classList.add("hidden");
- if (previewPopoverInput) previewPopoverInput.value = "";
- popoverSelectedText = "";
- }
-
- function showPreviewPopover(text, rect) {
- if (!previewPopover || !previewPopoverQuote || !previewModalBody) return;
- popoverSelectedText = text;
- var display = text.length > 120 ? text.slice(0, 117) + "\u2026" : text;
- previewPopoverQuote.textContent = "\u201c" + display + "\u201d";
- if (previewPopoverInput) previewPopoverInput.value = "";
- previewPopover.classList.remove("hidden");
-
- var bodyRect = previewModalBody.getBoundingClientRect();
- var popH = previewPopover.offsetHeight;
- var top = rect.bottom - bodyRect.top + previewModalBody.scrollTop + 6;
- if (rect.bottom + popH + 20 > bodyRect.bottom) {
- top = rect.top - bodyRect.top + previewModalBody.scrollTop - popH - 6;
- }
- var left = Math.max(8, Math.min(rect.left - bodyRect.left, bodyRect.width - previewPopover.offsetWidth - 8));
- previewPopover.style.top = top + "px";
- previewPopover.style.left = left + "px";
-
- if (previewPopoverInput) previewPopoverInput.focus();
- }
-
- if (btnSummaryPreview) {
- btnSummaryPreview.addEventListener("click", openPreviewModal);
- }
- if (previewModalClose) {
- previewModalClose.addEventListener("click", closePreviewModal);
- }
- if (previewModalRegenerate) {
- previewModalRegenerate.addEventListener("click", function() {
- var selectedModel = previewModalModel ? previewModalModel.value.trim() : "";
- closePreviewModal();
- var modelProvider = getSummaryProvider(selectedModel);
- if (modelProvider && modelProvider !== currentSummaryProvider) {
- setSummaryProvider(modelProvider, selectedModel);
- } else if (summaryModelSelect) {
- summaryModelSelect.value = selectedModel;
- currentSummaryModel = selectedModel;
- }
- requestSummary(getSelectedIndices(), getFeedbackText());
- resetTimer();
- });
- }
- if (previewModalApprove) {
- previewModalApprove.addEventListener("click", function() {
- closePreviewModal();
- doApprove();
- });
- }
- if (previewModalBody) {
- previewModalBody.addEventListener("mouseup", function() {
- var sel = window.getSelection();
- if (!sel || sel.isCollapsed) return;
- var text = sel.toString().trim();
- if (!text) return;
- var range = sel.getRangeAt(0);
- showPreviewPopover(text, range.getBoundingClientRect());
- });
- previewModalBody.addEventListener("mousedown", function(e) {
- if (previewPopover && !previewPopover.contains(e.target)) {
- hidePreviewPopover();
- }
- });
- }
-
- if (previewPopoverRegen) {
- previewPopoverRegen.addEventListener("click", function() {
- var note = previewPopoverInput ? previewPopoverInput.value.trim() : "";
- var quoted = popoverSelectedText;
- hidePreviewPopover();
-
- var feedback = 'Regarding: "' + quoted + '"';
- if (note) feedback += " \u2014 " + note;
-
- var selectedModel = previewModalModel ? previewModalModel.value.trim() : "";
- closePreviewModal();
- var modelProvider = getSummaryProvider(selectedModel);
- if (modelProvider && modelProvider !== currentSummaryProvider) {
- setSummaryProvider(modelProvider, selectedModel);
- } else if (summaryModelSelect) {
- summaryModelSelect.value = selectedModel;
- currentSummaryModel = selectedModel;
- }
- requestSummary(getSelectedIndices(), feedback);
- resetTimer();
- });
- }
-
- if (previewPopoverInput) {
- previewPopoverInput.addEventListener("keydown", function(e) {
- if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
- e.preventDefault();
- if (previewPopoverRegen) previewPopoverRegen.click();
- }
- if (e.key === "Escape") {
- e.preventDefault();
- e.stopImmediatePropagation();
- hidePreviewPopover();
- }
- });
- }
-
- if (previewModal) {
- previewModal.addEventListener("click", function(e) {
- if (e.target === previewModal) closePreviewModal();
- });
- document.addEventListener("keydown", function(e) {
- if (e.key === "Escape" && !previewModal.classList.contains("hidden")) {
- if (previewPopover && !previewPopover.classList.contains("hidden")) {
- e.preventDefault();
- e.stopImmediatePropagation();
- hidePreviewPopover();
- return;
- }
- e.preventDefault();
- e.stopImmediatePropagation();
- closePreviewModal();
- }
- });
- }
-
- if (btnSummaryApprove) {
- btnSummaryApprove.addEventListener("click", function() {
- doApprove();
- resetTimer();
- });
- }
-
- if (summaryInput) {
- summaryInput.addEventListener("input", function() {
- if (!summaryMeta || typeof summaryMeta !== "object") {
- summaryMeta = normalizeSummaryMeta(null, true);
- }
- summaryMeta.edited = true;
- clearError();
- updateStageUI();
- resetTimer();
- });
- }
-
- if (summaryProviderSelect) {
- summaryProviderSelect.addEventListener("change", function() {
- var provider = typeof summaryProviderSelect.value === "string" ? summaryProviderSelect.value : "";
- if (!provider || provider === currentSummaryProvider) return;
- setSummaryProvider(provider, "");
- clearError();
- updateStageUI();
- resetTimer();
- });
- }
-
- if (summaryModelSelect) {
- summaryModelSelect.addEventListener("change", function() {
- currentSummaryModel = typeof summaryModelSelect.value === "string"
- ? summaryModelSelect.value.trim()
- : "";
- clearError();
- resetTimer();
- });
- }
-
- function isInteractiveTarget(target) {
- if (!target || !target.tagName) return false;
- var tag = target.tagName;
- if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT" || tag === "BUTTON" || tag === "A") return true;
- if (typeof target.isContentEditable === "boolean" && target.isContentEditable) return true;
- if (typeof target.closest === "function") {
- return !!target.closest('[contenteditable=""], [contenteditable="true"]');
- }
- return false;
- }
-
- document.addEventListener("keydown", function(e) {
- if (submitted || timerExpired || submitInFlight) return;
-
- var isSummaryInput = summaryInput && e.target === summaryInput;
- if (isSummaryInput && (e.metaKey || e.ctrlKey) && e.key === "Enter") {
- e.preventDefault();
- if (stage === "summary-review") doApprove();
- return;
- }
-
- if (e.key === "Escape") {
- e.preventDefault();
- if (exitRegeneratingState()) {
- return;
- }
- if (stage === "summary-review") {
- stage = "results";
- clearError();
- updateStageUI();
- } else if (stage === "results") {
- doCancel();
- }
- return;
- }
-
- if (isInteractiveTarget(e.target)) return;
-
- if (e.key === "Enter" && !e.metaKey && !e.ctrlKey) {
- if (stage !== "results") return;
- e.preventDefault();
- requestSummary(getSelectedIndices());
- return;
- }
-
- if ((e.metaKey || e.ctrlKey) && e.key === "Enter") {
- if (stage !== "summary-review") return;
- e.preventDefault();
- doApprove();
- return;
- }
-
- if (e.key.toLowerCase() === "a" && !e.metaKey && !e.ctrlKey) {
- e.preventDefault();
- if (stage !== "results") return;
- var boxes = resultCardsEl.querySelectorAll(".result-card input[type=checkbox]");
- var selectable = [];
- boxes.forEach(function(cb) {
- if (cb.disabled) return;
- selectable.push(cb);
- });
- if (selectable.length === 0) return;
- var allChecked = true;
- selectable.forEach(function(cb) { if (!cb.checked) allChecked = false; });
- selectable.forEach(function(cb) {
- cb.checked = !allChecked;
- var parentCard = typeof cb.closest === "function" ? cb.closest(".result-card") : null;
- if (parentCard) parentCard.classList.toggle("checked", cb.checked);
- });
- updateStageUI();
- maybeAutoGenerateSummary();
- resetTimer();
- }
- });
-
- setInterval(function() {
- if (submitted) return;
- postJson("/heartbeat", {}).catch(function() {
- // Heartbeat is best-effort.
- });
- }, 10000);
-
- var lastResizeHeight = 0;
- function checkContentHeight() {
- if (!window.glimpse || typeof window.glimpse.send !== "function") return;
- var h = document.documentElement.scrollHeight || document.body.scrollHeight;
- if (h > 0 && Math.abs(h - lastResizeHeight) > 30) {
- lastResizeHeight = h;
- window.glimpse.send({ type: "resize", height: h });
- }
- }
- setInterval(checkContentHeight, 500);
-
- if (queries.length === 0 && addSearchInput) {
- addSearchInput.focus();
- }
-})();`; /* v9-c96edf658a9d7e1a */
diff --git a/pip-tmp/jiti/pi-web-access-curator-server.2a16f6fa.mjs b/pip-tmp/jiti/pi-web-access-curator-server.2a16f6fa.mjs
deleted file mode 100644
index f624e0939d4c87168522df16c84c4022c87216a8..0000000000000000000000000000000000000000
--- a/pip-tmp/jiti/pi-web-access-curator-server.2a16f6fa.mjs
+++ /dev/null
@@ -1,605 +0,0 @@
-"use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.startCuratorServer = startCuratorServer;var _nodeHttp = _interopRequireDefault(await jitiImport("node:http"));
-var _curatorPage = await jitiImport("./curator-page.js");function _interopRequireDefault(e) {return e && e.__esModule ? e : { default: e };}
-
-
-const STALE_THRESHOLD_MS = 30000;
-const WATCHDOG_INTERVAL_MS = 5000;
-const MAX_BODY_SIZE = 64 * 1024;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-function sendJson(res, status, payload) {
- res.writeHead(status, {
- "Content-Type": "application/json",
- "Cache-Control": "no-store"
- });
- res.end(JSON.stringify(payload));
-}
-
-function parseJSONBody(req) {
- return new Promise((resolve, reject) => {
- let body = "";
- let size = 0;
- req.on("data", (chunk) => {
- size += chunk.length;
- if (size > MAX_BODY_SIZE) {
- req.destroy();
- reject(new Error("Request body too large"));
- return;
- }
- body += chunk.toString();
- });
- req.on("end", () => {
- try {
- resolve(JSON.parse(body));
- } catch (err) {
- const message = err instanceof Error ? err.message : String(err);
- reject(new Error(`Invalid JSON: ${message}`));
- }
- });
- req.on("error", reject);
- });
-}
-
-async function parseBodyOrSend(req, res) {
- try {
- return await parseJSONBody(req);
- } catch (err) {
- const message = err instanceof Error ? err.message : "Invalid body";
- const status = message === "Request body too large" ? 413 : 400;
- sendJson(res, status, { ok: false, error: message });
- return null;
- }
-}
-
-function normalizeSelectedIndices(
-value,
-options)
-{
- if (!Array.isArray(value)) {
- return { ok: false, error: "Invalid selection" };
- }
-
- if (!options.allowEmpty && value.length === 0) {
- return { ok: false, error: "Invalid selection" };
- }
-
- const normalized = [];
- const seen = new Set();
- for (const item of value) {
- if (typeof item !== "number" || !Number.isInteger(item) || item < 0) {
- return { ok: false, error: "Invalid selection" };
- }
- if (item >= options.maxExclusive) {
- return { ok: false, error: "Invalid selection" };
- }
- if (seen.has(item)) {
- continue;
- }
- seen.add(item);
- normalized.push(item);
- }
-
- if (!options.allowEmpty && normalized.length === 0) {
- return { ok: false, error: "Invalid selection" };
- }
-
- return { ok: true, indices: normalized };
-}
-
-function normalizeSummaryMeta(value) {
- if (!value || typeof value !== "object") return null;
- const meta = value;
-
- const model = meta.model;
- if (model !== null && typeof model !== "string") return null;
-
- const durationMs = meta.durationMs;
- if (typeof durationMs !== "number" || !Number.isFinite(durationMs) || durationMs < 0) return null;
-
- const tokenEstimate = meta.tokenEstimate;
- if (typeof tokenEstimate !== "number" || !Number.isFinite(tokenEstimate) || tokenEstimate < 0) return null;
-
- const fallbackUsed = meta.fallbackUsed;
- if (typeof fallbackUsed !== "boolean") return null;
-
- const fallbackReason = meta.fallbackReason;
- if (fallbackReason !== undefined && typeof fallbackReason !== "string") return null;
-
- const edited = meta.edited;
- if (edited !== undefined && typeof edited !== "boolean") return null;
-
- return {
- model,
- durationMs,
- tokenEstimate,
- fallbackUsed,
- fallbackReason,
- edited
- };
-}
-
-function startCuratorServer(
-options,
-callbacks)
-{
- const {
- queries,
- sessionToken,
- timeout,
- availableProviders,
- defaultProvider,
- summaryModels,
- defaultSummaryModel
- } = options;
- let browserConnected = false;
- let lastHeartbeatAt = Date.now();
- let completed = false;
- let watchdog = null;
- let state = "SEARCHING";
- let sseResponse = null;
- const sseBuffer = [];
- let nextQueryIndex = queries.length;
- let summarizeAbortController = null;
- let summarizeRequestSeq = 0;
-
- let sseKeepalive = null;
-
- const abortInFlightSummarize = () => {
- if (!summarizeAbortController) return;
- summarizeAbortController.abort();
- summarizeAbortController = null;
- };
-
- const markCompleted = () => {
- if (completed) return false;
- completed = true;
- state = "COMPLETED";
- if (watchdog) {
- clearInterval(watchdog);
- watchdog = null;
- }
- if (sseKeepalive) {
- clearInterval(sseKeepalive);
- sseKeepalive = null;
- }
- abortInFlightSummarize();
- if (sseResponse) {
- try {sseResponse.end();} catch {}
- sseResponse = null;
- }
- return true;
- };
-
- const touchHeartbeat = () => {
- lastHeartbeatAt = Date.now();
- browserConnected = true;
- };
-
- function validateToken(body, res) {
- if (!body || typeof body !== "object") {
- sendJson(res, 400, { ok: false, error: "Invalid body" });
- return false;
- }
- if (body.token !== sessionToken) {
- sendJson(res, 403, { ok: false, error: "Invalid session" });
- return false;
- }
- return true;
- }
-
- function isAvailableProvider(provider) {
- if (provider === "perplexity") return availableProviders.perplexity;
- if (provider === "exa") return availableProviders.exa;
- if (provider === "gemini") return availableProviders.gemini;
- return false;
- }
-
- function sendSSE(event, data) {
- const payload = `event: ${event}\ndata: ${JSON.stringify(data)}\n\n`;
- const res = sseResponse;
- if (res && !res.writableEnded && res.socket && !res.socket.destroyed) {
- try {res.write(payload);return;} catch {}
- }
- sseBuffer.push(payload);
- }
-
- const pageHtml = (0, _curatorPage.generateCuratorPage)(
- queries,
- sessionToken,
- timeout,
- availableProviders,
- defaultProvider,
- summaryModels,
- defaultSummaryModel
- );
-
- const server = _nodeHttp.default.createServer(async (req, res) => {
- try {
- const method = req.method || "GET";
- const url = new URL(req.url || "/", `http://${req.headers.host || "127.0.0.1"}`);
-
- if (method === "GET" && url.pathname === "/") {
- const token = url.searchParams.get("session");
- if (token !== sessionToken) {
- res.writeHead(403, { "Content-Type": "text/plain" });
- res.end("Invalid session");
- return;
- }
- touchHeartbeat();
- res.writeHead(200, {
- "Content-Type": "text/html; charset=utf-8",
- "Cache-Control": "no-store"
- });
- res.end(pageHtml);
- return;
- }
-
- if (method === "GET" && url.pathname === "/events") {
- const token = url.searchParams.get("session");
- if (token !== sessionToken) {
- res.writeHead(403, { "Content-Type": "text/plain" });
- res.end("Invalid session");
- return;
- }
- if (state === "COMPLETED") {
- sendJson(res, 409, { ok: false, error: "No events available" });
- return;
- }
- if (sseResponse) {
- try {sseResponse.end();} catch {}
- }
- res.writeHead(200, {
- "Content-Type": "text/event-stream",
- "Cache-Control": "no-cache",
- Connection: "keep-alive",
- "X-Accel-Buffering": "no"
- });
- res.flushHeaders();
- if (res.socket) res.socket.setNoDelay(true);
- sseResponse = res;
- if (sseBuffer.length > 0) {
- const pending = sseBuffer.splice(0, sseBuffer.length);
- for (let i = 0; i < pending.length; i++) {
- const msg = pending[i];
- try {
- res.write(msg);
- } catch {
- sseBuffer.unshift(...pending.slice(i));
- break;
- }
- }
- }
- if (sseKeepalive) clearInterval(sseKeepalive);
- sseKeepalive = setInterval(() => {
- if (sseResponse) {
- try {sseResponse.write(":keepalive\n\n");} catch {}
- }
- }, 15000);
- req.on("close", () => {
- if (sseResponse === res) sseResponse = null;
- });
- return;
- }
-
- if (method === "POST" && url.pathname === "/heartbeat") {
- const body = await parseBodyOrSend(req, res);
- if (!body) return;
- if (!validateToken(body, res)) return;
- touchHeartbeat();
- sendJson(res, 200, { ok: true });
- return;
- }
-
- if (method === "POST" && url.pathname === "/provider") {
- const body = await parseBodyOrSend(req, res);
- if (!body) return;
- if (!validateToken(body, res)) return;
- const { provider } = body;
- if (typeof provider !== "string" || provider.length === 0) {
- sendJson(res, 400, { ok: false, error: "Invalid provider" });
- return;
- }
- if (!isAvailableProvider(provider)) {
- sendJson(res, 400, { ok: false, error: `Provider unavailable: ${provider}` });
- return;
- }
- setImmediate(() => callbacks.onProviderChange(provider));
- sendJson(res, 200, { ok: true });
- return;
- }
-
- if (method === "POST" && url.pathname === "/search") {
- const body = await parseBodyOrSend(req, res);
- if (!body) return;
- if (!validateToken(body, res)) return;
- if (state === "COMPLETED") {
- sendJson(res, 409, { ok: false, error: "Session closed" });
- return;
- }
- const { query, provider } = body;
- if (typeof query !== "string" || query.trim().length === 0) {
- sendJson(res, 400, { ok: false, error: "Invalid query" });
- return;
- }
- if (provider !== undefined) {
- if (typeof provider !== "string" || provider.length === 0) {
- sendJson(res, 400, { ok: false, error: "Invalid provider" });
- return;
- }
- if (!isAvailableProvider(provider)) {
- sendJson(res, 400, { ok: false, error: `Provider unavailable: ${provider}` });
- return;
- }
- }
- const qi = nextQueryIndex++;
- touchHeartbeat();
- try {
- const result = await callbacks.onAddSearch(query.trim(), qi, provider);
- sendJson(res, 200, {
- ok: true,
- queryIndex: qi,
- answer: result.answer,
- results: result.results,
- provider: result.provider
- });
- } catch (err) {
- const message = err instanceof Error ? err.message : "Search failed";
- sendJson(res, 200, {
- ok: true,
- queryIndex: qi,
- error: message,
- provider: typeof provider === "string" && provider.length > 0 ? provider : undefined
- });
- }
- return;
- }
-
- if (method === "POST" && url.pathname === "/summarize") {
- const body = await parseBodyOrSend(req, res);
- if (!body) return;
- if (!validateToken(body, res)) return;
- if (state === "COMPLETED") {
- sendJson(res, 409, { ok: false, error: "Session closed" });
- return;
- }
-
- const parsed = normalizeSelectedIndices(body.selected, {
- allowEmpty: false,
- maxExclusive: nextQueryIndex
- });
- if (!parsed.ok) {
- sendJson(res, 400, { ok: false, error: parsed.error });
- return;
- }
-
- let model;
- const bodyModel = body.model;
- if (bodyModel !== undefined) {
- if (typeof bodyModel !== "string") {
- sendJson(res, 400, { ok: false, error: "Invalid model" });
- return;
- }
- const trimmedModel = bodyModel.trim();
- model = trimmedModel.length > 0 ? trimmedModel : undefined;
- }
-
- const bodyFeedback = body.feedback;
- const feedback = typeof bodyFeedback === "string" && bodyFeedback.trim().length > 0 ?
- bodyFeedback.trim() :
- undefined;
-
- abortInFlightSummarize();
- const controller = new AbortController();
- summarizeAbortController = controller;
- const requestId = ++summarizeRequestSeq;
-
- try {
- const result = await callbacks.onSummarize(parsed.indices, controller.signal, model, feedback);
- if (requestId !== summarizeRequestSeq || state === "COMPLETED") {
- sendJson(res, 409, { ok: false, error: "Summarize request superseded" });
- return;
- }
- sendJson(res, 200, {
- ok: true,
- summary: result.summary,
- meta: result.meta
- });
- } catch (err) {
- const message = err instanceof Error ? err.message : "Summary generation failed";
- const status = controller.signal.aborted ? 409 : 500;
- sendJson(res, status, { ok: false, error: message });
- } finally {
- if (summarizeAbortController === controller) {
- summarizeAbortController = null;
- }
- }
- return;
- }
-
- if (method === "POST" && url.pathname === "/rewrite") {
- const body = await parseBodyOrSend(req, res);
- if (!body) return;
- if (!validateToken(body, res)) return;
- if (state === "COMPLETED") {
- sendJson(res, 409, { ok: false, error: "Session closed" });
- return;
- }
- const { query } = body;
- if (typeof query !== "string" || query.trim().length === 0) {
- sendJson(res, 400, { ok: false, error: "Invalid query" });
- return;
- }
- const controller = new AbortController();
- req.on("close", () => controller.abort());
- touchHeartbeat();
- try {
- const rewritten = await callbacks.onRewriteQuery(query.trim(), controller.signal);
- sendJson(res, 200, { ok: true, query: rewritten });
- } catch (err) {
- const message = err instanceof Error ? err.message : "Rewrite failed";
- const status = controller.signal.aborted ? 409 : 500;
- sendJson(res, status, { ok: false, error: message });
- }
- return;
- }
-
- if (method === "POST" && url.pathname === "/submit") {
- const body = await parseBodyOrSend(req, res);
- if (!body) return;
- if (!validateToken(body, res)) return;
-
- const parsed = normalizeSelectedIndices(body.selected, {
- allowEmpty: true,
- maxExclusive: nextQueryIndex
- });
- if (!parsed.ok) {
- sendJson(res, 400, { ok: false, error: parsed.error });
- return;
- }
-
- let summary;
- const bodySummary = body.summary;
- if (bodySummary !== undefined) {
- if (typeof bodySummary !== "string") {
- sendJson(res, 400, { ok: false, error: "Invalid summary" });
- return;
- }
- const trimmedSummary = bodySummary.trim();
- summary = trimmedSummary.length > 0 ? trimmedSummary : undefined;
- }
-
- let summaryMeta;
- const bodySummaryMeta = body.summaryMeta;
- if (bodySummaryMeta !== undefined) {
- const parsedSummaryMeta = normalizeSummaryMeta(bodySummaryMeta);
- if (!parsedSummaryMeta) {
- sendJson(res, 400, { ok: false, error: "Invalid summaryMeta" });
- return;
- }
- summaryMeta = parsedSummaryMeta;
- }
-
- if (state !== "SEARCHING" && state !== "RESULT_SELECTION") {
- sendJson(res, 409, { ok: false, error: "Cannot submit in current state" });
- return;
- }
- if (!markCompleted()) {
- sendJson(res, 409, { ok: false, error: "Session closed" });
- return;
- }
- const rawResults = body.rawResults === true;
- sendJson(res, 200, { ok: true });
- setImmediate(() => callbacks.onSubmit({ selectedQueryIndices: parsed.indices, summary, summaryMeta, rawResults }));
- return;
- }
-
- if (method === "POST" && url.pathname === "/cancel") {
- const body = await parseBodyOrSend(req, res);
- if (!body) return;
- if (!validateToken(body, res)) return;
- if (!markCompleted()) {
- sendJson(res, 200, { ok: true });
- return;
- }
- const { reason } = body;
- sendJson(res, 200, { ok: true });
- const cancelReason = reason === "timeout" ? "timeout" : "user";
- setImmediate(() => callbacks.onCancel(cancelReason));
- return;
- }
-
- res.writeHead(404, { "Content-Type": "text/plain" });
- res.end("Not found");
- } catch (err) {
- const message = err instanceof Error ? err.message : "Server error";
- sendJson(res, 500, { ok: false, error: message });
- }
- });
-
- return new Promise((resolve, reject) => {
- const onError = (err) => {
- reject(new Error(`Curator server failed to start: ${err.message}`));
- };
-
- server.once("error", onError);
- server.listen(0, "127.0.0.1", () => {
- server.off("error", onError);
- const addr = server.address();
- if (!addr || typeof addr === "string") {
- reject(new Error("Curator server: invalid address"));
- return;
- }
- const url = `http://localhost:${addr.port}/?session=${sessionToken}`;
-
- watchdog = setInterval(() => {
- if (completed || !browserConnected) return;
- if (Date.now() - lastHeartbeatAt <= STALE_THRESHOLD_MS) return;
- if (!markCompleted()) return;
- setImmediate(() => callbacks.onCancel("stale"));
- }, WATCHDOG_INTERVAL_MS);
-
- resolve({
- server,
- url,
- close: () => {
- const wasOpen = markCompleted();
- try {server.close();} catch {}
- if (wasOpen) {
- setImmediate(() => callbacks.onCancel("stale"));
- }
- },
- pushResult: (queryIndex, data) => {
- if (completed) return;
- sendSSE("result", { queryIndex, query: queries[queryIndex] ?? "", ...data });
- },
- pushError: (queryIndex, error, provider) => {
- if (completed) return;
- sendSSE("search-error", { queryIndex, query: queries[queryIndex] ?? "", error, provider });
- },
- searchesDone: () => {
- if (completed) return;
- sendSSE("done", {});
- state = "RESULT_SELECTION";
- }
- });
- });
- });
-} /* v9-ab24f6f4c86d3473 */
diff --git a/pip-tmp/jiti/pi-web-access-exa.b5c6a885.mjs b/pip-tmp/jiti/pi-web-access-exa.b5c6a885.mjs
deleted file mode 100644
index 3cb17ee526d681d45556c2fec13dc2b4c5660db4..0000000000000000000000000000000000000000
--- a/pip-tmp/jiti/pi-web-access-exa.b5c6a885.mjs
+++ /dev/null
@@ -1,520 +0,0 @@
-"use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.callExaMcp = callExaMcp;exports.hasExaApiKey = hasExaApiKey;exports.isExaAvailable = isExaAvailable;exports.searchWithExa = searchWithExa;var _nodeFs = await jitiImport("node:fs");
-var _nodeOs = await jitiImport("node:os");
-var _nodePath = await jitiImport("node:path");
-var _activity = await jitiImport("./activity.js");
-
-
-
-const EXA_ANSWER_URL = "https://api.exa.ai/answer";
-const EXA_SEARCH_URL = "https://api.exa.ai/search";
-const EXA_MCP_URL = "https://mcp.exa.ai/mcp";
-const CONFIG_PATH = (0, _nodePath.join)((0, _nodeOs.homedir)(), ".pi", "web-search.json");
-const USAGE_PATH = (0, _nodePath.join)((0, _nodeOs.homedir)(), ".pi", "exa-usage.json");
-
-const MONTHLY_LIMIT = 1000;
-const WARNING_THRESHOLD = 800;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-let cachedConfig = null;
-let warnedMonth = null;
-
-function loadConfig() {
- if (cachedConfig) return cachedConfig;
- if (!(0, _nodeFs.existsSync)(CONFIG_PATH)) {
- cachedConfig = {};
- return cachedConfig;
- }
-
- const raw = (0, _nodeFs.readFileSync)(CONFIG_PATH, "utf-8");
- try {
- cachedConfig = JSON.parse(raw);
- return cachedConfig;
- } catch (err) {
- const message = err instanceof Error ? err.message : String(err);
- throw new Error(`Failed to parse ${CONFIG_PATH}: ${message}`);
- }
-}
-
-function normalizeApiKey(value) {
- if (typeof value !== "string") return null;
- const normalized = value.trim();
- return normalized.length > 0 ? normalized : null;
-}
-
-function getApiKey() {
- return normalizeApiKey(process.env.EXA_API_KEY) ?? normalizeApiKey(loadConfig().exaApiKey);
-}
-
-function getCurrentMonth() {
- return new Date().toISOString().slice(0, 7);
-}
-
-function normalizeUsage(raw) {
- const month = getCurrentMonth();
- if (!raw || typeof raw !== "object") return { month, count: 0 };
- const data = raw;
- const parsedMonth = typeof data.month === "string" ? data.month : month;
- const parsedCount = typeof data.count === "number" && Number.isFinite(data.count) ? data.count : 0;
- if (parsedMonth !== month) return { month, count: 0 };
- return { month: parsedMonth, count: Math.max(0, Math.floor(parsedCount)) };
-}
-
-function readUsage() {
- if (!(0, _nodeFs.existsSync)(USAGE_PATH)) return { month: getCurrentMonth(), count: 0 };
- const raw = (0, _nodeFs.readFileSync)(USAGE_PATH, "utf-8");
- try {
- return normalizeUsage(JSON.parse(raw));
- } catch (err) {
- const message = err instanceof Error ? err.message : String(err);
- throw new Error(`Failed to parse ${USAGE_PATH}: ${message}`);
- }
-}
-
-function writeUsage(usage) {
- const dir = (0, _nodePath.join)((0, _nodeOs.homedir)(), ".pi");
- if (!(0, _nodeFs.existsSync)(dir)) (0, _nodeFs.mkdirSync)(dir, { recursive: true });
- (0, _nodeFs.writeFileSync)(USAGE_PATH, JSON.stringify(usage, null, 2) + "\n");
-}
-
-function reserveRequestBudget() {
- const usage = readUsage();
-
- if (usage.count >= MONTHLY_LIMIT) {
- return { exhausted: true };
- }
-
- const nextCount = usage.count + 1;
- if (nextCount >= WARNING_THRESHOLD && warnedMonth !== usage.month) {
- warnedMonth = usage.month;
- console.error(`Exa usage warning: ${nextCount}/${MONTHLY_LIMIT} monthly requests used.`);
- }
-
- writeUsage({ month: usage.month, count: nextCount });
- return null;
-}
-
-function requestSignal(signal) {
- const timeout = AbortSignal.timeout(60000);
- return signal ? AbortSignal.any([signal, timeout]) : timeout;
-}
-
-function recencyToStartDate(filter) {
- const now = new Date();
- const offsets = {
- day: 1,
- week: 7,
- month: 30,
- year: 365
- };
- const days = offsets[filter] ?? 0;
- return new Date(now.getTime() - days * 86400000).toISOString();
-}
-
-function mapDomainFilter(domainFilter) {
- if (!domainFilter?.length) return {};
- const includeDomains = domainFilter.
- filter((d) => !d.startsWith("-") && d.trim().length > 0).
- map((d) => d.trim());
- const excludeDomains = domainFilter.
- filter((d) => d.startsWith("-")).
- map((d) => d.slice(1).trim()).
- filter(Boolean);
- return {
- ...(includeDomains.length ? { includeDomains } : {}),
- ...(excludeDomains.length ? { excludeDomains } : {})
- };
-}
-
-function normalizeHighlights(value) {
- if (!Array.isArray(value)) return [];
- return value.filter((item) => typeof item === "string" && item.trim().length > 0);
-}
-
-function buildAnswerFromSearchResults(results) {
- if (!results?.length) return "";
- const parts = [];
- for (let i = 0; i < results.length; i++) {
- const item = results[i];
- if (!item?.url) continue;
- const highlights = normalizeHighlights(item.highlights);
- const content = highlights.length > 0 ?
- highlights.join(" ") :
- typeof item.text === "string" ? item.text.trim().slice(0, 1000) : "";
- if (!content) continue;
- const sourceTitle = item.title || `Source ${i + 1}`;
- parts.push(`${content}\nSource: ${sourceTitle} (${item.url})`);
- }
- return parts.join("\n\n");
-}
-
-function mapResults(results) {
- if (!Array.isArray(results)) return [];
- const mapped = [];
- for (let i = 0; i < results.length; i++) {
- const item = results[i];
- if (!item?.url) continue;
- mapped.push({
- title: item.title || `Source ${i + 1}`,
- url: item.url,
- snippet: ""
- });
- }
- return mapped;
-}
-
-function mapInlineContent(results) {
- if (!results?.length) return [];
- return results.
- filter((r) =>
- !!r?.url && typeof r.text === "string" && r.text.length > 0).
- map((r) => ({
- url: r.url,
- title: r.title || "",
- content: r.text,
- error: null
- }));
-}
-
-async function callExaMcp(
-toolName,
-args,
-signal)
-{
- const response = await fetch(EXA_MCP_URL, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- "Accept": "application/json, text/event-stream"
- },
- body: JSON.stringify({
- jsonrpc: "2.0",
- id: 1,
- method: "tools/call",
- params: {
- name: toolName,
- arguments: args
- }
- }),
- signal: requestSignal(signal)
- });
-
- if (!response.ok) {
- const errorText = await response.text();
- throw new Error(`Exa MCP error ${response.status}: ${errorText.slice(0, 300)}`);
- }
-
- const body = await response.text();
- const dataLines = body.split("\n").filter((line) => line.startsWith("data:"));
-
- let parsed = null;
- for (const line of dataLines) {
- const payload = line.slice(5).trim();
- if (!payload) continue;
- try {
- const candidate = JSON.parse(payload);
- if (candidate?.result || candidate?.error) {
- parsed = candidate;
- break;
- }
- } catch {
- }
- }
-
- if (!parsed) {
- try {
- const candidate = JSON.parse(body);
- if (candidate?.result || candidate?.error) {
- parsed = candidate;
- }
- } catch {
- }
- }
-
- if (!parsed) {
- throw new Error("Exa MCP returned an empty response");
- }
-
- if (parsed.error) {
- const code = typeof parsed.error.code === "number" ? ` ${parsed.error.code}` : "";
- const message = parsed.error.message || "Unknown error";
- throw new Error(`Exa MCP error${code}: ${message}`);
- }
-
- if (parsed.result?.isError) {
- const message = parsed.result.content?.
- find((item) => item.type === "text" && typeof item.text === "string")?.
- text?.trim();
- throw new Error(message || "Exa MCP returned an error");
- }
-
- const text = parsed.result?.content?.
- find((item) => item.type === "text" && typeof item.text === "string" && item.text.trim().length > 0)?.
- text;
-
- if (!text) {
- throw new Error("Exa MCP returned empty content");
- }
-
- return text;
-}
-
-function parseMcpResults(text) {
- const blocks = text.split(/(?=^Title: )/m).filter((block) => block.trim().length > 0);
- const parsed = blocks.map((block) => {
- const title = block.match(/^Title: (.+)/m)?.[1]?.trim() ?? "";
- const url = block.match(/^URL: (.+)/m)?.[1]?.trim() ?? "";
- let content = "";
- const textStart = block.indexOf("\nText: ");
- if (textStart >= 0) {
- content = block.slice(textStart + 7).trim();
- } else {
- const hlMatch = block.match(/\nHighlights:\s*\n/);
- if (hlMatch?.index != null) {
- content = block.slice(hlMatch.index + hlMatch[0].length).trim();
- }
- }
- content = content.replace(/\n---\s*$/, "").trim();
- return { title, url, content };
- }).filter((result) => result.url.length > 0);
- return parsed.length > 0 ? parsed : null;
-}
-
-function buildAnswerFromMcpResults(results) {
- if (results.length === 0) return "";
- const parts = [];
- for (let i = 0; i < results.length; i++) {
- const result = results[i];
- const snippet = result.content.replace(/\s+/g, " ").trim().slice(0, 500);
- if (!snippet) continue;
- const sourceTitle = result.title || `Source ${i + 1}`;
- parts.push(`${snippet}\nSource: ${sourceTitle} (${result.url})`);
- }
- return parts.join("\n\n");
-}
-
-function mapMcpInlineContent(results) {
- return results.
- filter((result) => result.content.length > 0).
- map((result) => ({
- url: result.url,
- title: result.title,
- content: result.content,
- error: null
- }));
-}
-
-function buildMcpQuery(query, options) {
- const parts = [query];
- if (options.domainFilter?.length) {
- for (const d of options.domainFilter) {
- parts.push(d.startsWith("-") ? `-site:${d.slice(1)}` : `site:${d}`);
- }
- }
- if (options.recencyFilter) {
- const now = new Date();
- switch (options.recencyFilter) {
- case "day":parts.push("past 24 hours");break;
- case "week":parts.push("past week");break;
- case "month":parts.push(`${now.toLocaleString("en", { month: "long" })} ${now.getFullYear()}`);break;
- case "year":parts.push(String(now.getFullYear()));break;
- }
- }
- return parts.join(" ");
-}
-
-async function searchWithExaMcp(query, options = {}) {
- const enrichedQuery = buildMcpQuery(query, options);
- const activityId = _activity.activityMonitor.logStart({ type: "api", query: enrichedQuery });
-
- try {
- const text = await callExaMcp(
- "web_search_exa",
- {
- query: enrichedQuery,
- numResults: options.numResults ?? 5,
- livecrawl: "fallback",
- type: "auto",
- contextMaxCharacters: options.includeContent ? 50000 : 3000
- },
- options.signal
- );
- const parsedResults = parseMcpResults(text);
- _activity.activityMonitor.logComplete(activityId, 200);
-
- if (!parsedResults) return null;
-
- const response = {
- answer: buildAnswerFromMcpResults(parsedResults),
- results: parsedResults.map((result, index) => ({
- title: result.title || `Source ${index + 1}`,
- url: result.url,
- snippet: ""
- }))
- };
-
- if (options.includeContent) {
- const inlineContent = mapMcpInlineContent(parsedResults);
- if (inlineContent.length > 0) response.inlineContent = inlineContent;
- }
-
- return response;
- } catch (err) {
- const message = err instanceof Error ? err.message : String(err);
- if (message.toLowerCase().includes("abort")) {
- _activity.activityMonitor.logComplete(activityId, 0);
- } else {
- _activity.activityMonitor.logError(activityId, message);
- }
- throw err;
- }
-}
-
-function isExaAvailable() {
- if (getApiKey()) {
- const usage = readUsage();
- return usage.count < MONTHLY_LIMIT;
- }
- return true;
-}
-
-function hasExaApiKey() {
- return !!getApiKey();
-}
-
-async function searchWithExa(query, options = {}) {
- const apiKey = getApiKey();
- if (!apiKey) {
- return searchWithExaMcp(query, options);
- }
-
- const budget = reserveRequestBudget();
- if (budget) return budget;
-
- const useSearch = options.includeContent ||
- !!options.recencyFilter ||
- !!options.domainFilter?.length ||
- !!(options.numResults && options.numResults !== 5);
-
- const activityId = _activity.activityMonitor.logStart({ type: "api", query });
-
- try {
- if (!useSearch) {
- const response = await fetch(EXA_ANSWER_URL, {
- method: "POST",
- headers: {
- "x-api-key": apiKey,
- "Content-Type": "application/json"
- },
- body: JSON.stringify({
- query,
- text: true
- }),
- signal: requestSignal(options.signal)
- });
-
- if (!response.ok) {
- const errorText = await response.text();
- throw new Error(`Exa API error ${response.status}: ${errorText.slice(0, 300)}`);
- }
-
- const data = await response.json();
- _activity.activityMonitor.logComplete(activityId, response.status);
- return {
- answer: data.answer || "",
- results: mapResults(data.citations)
- };
- }
-
- const startDate = options.recencyFilter ? recencyToStartDate(options.recencyFilter) : null;
- const domainFilters = mapDomainFilter(options.domainFilter);
- const response = await fetch(EXA_SEARCH_URL, {
- method: "POST",
- headers: {
- "x-api-key": apiKey,
- "Content-Type": "application/json"
- },
- body: JSON.stringify({
- query,
- type: "auto",
- numResults: options.numResults ?? 5,
- ...domainFilters,
- ...(startDate ? { startPublishedDate: startDate } : {}),
- contents: {
- text: options.includeContent ? true : { maxCharacters: 3000 },
- highlights: true
- }
- }),
- signal: requestSignal(options.signal)
- });
-
- if (!response.ok) {
- const errorText = await response.text();
- throw new Error(`Exa API error ${response.status}: ${errorText.slice(0, 300)}`);
- }
-
- const data = await response.json();
- _activity.activityMonitor.logComplete(activityId, response.status);
-
- const mapped = {
- answer: buildAnswerFromSearchResults(data.results),
- results: mapResults(data.results)
- };
- if (options.includeContent) {
- const inlineContent = mapInlineContent(data.results);
- if (inlineContent.length > 0) mapped.inlineContent = inlineContent;
- }
- return mapped;
- } catch (err) {
- const message = err instanceof Error ? err.message : String(err);
- if (message.toLowerCase().includes("abort")) {
- _activity.activityMonitor.logComplete(activityId, 0);
- } else {
- _activity.activityMonitor.logError(activityId, message);
- }
- throw err;
- }
-} /* v9-af927f0725a120a3 */
diff --git a/pip-tmp/jiti/pi-web-access-extract.baf16c13.mjs b/pip-tmp/jiti/pi-web-access-extract.baf16c13.mjs
deleted file mode 100644
index f59245d1a209ddcdd2b495637830e2bb23c2ebe7..0000000000000000000000000000000000000000
--- a/pip-tmp/jiti/pi-web-access-extract.baf16c13.mjs
+++ /dev/null
@@ -1,641 +0,0 @@
-"use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.extractContent = extractContent;exports.extractHeadingTitle = extractHeadingTitle;exports.fetchAllContent = fetchAllContent;var _readability = await jitiImport("@mozilla/readability");
-var _linkedom = await jitiImport("linkedom");
-var _turndown = _interopRequireDefault(await jitiImport("turndown"));
-var _pLimit = _interopRequireDefault(await jitiImport("p-limit"));
-var _activity = await jitiImport("./activity.js");
-var _rscExtract = await jitiImport("./rsc-extract.js");
-var _pdfExtract = await jitiImport("./pdf-extract.js");
-var _githubExtract = await jitiImport("./github-extract.js");
-var _youtubeExtract = await jitiImport("./youtube-extract.js");
-var _geminiUrlContext = await jitiImport("./gemini-url-context.js");
-var _videoExtract = await jitiImport("./video-extract.js");
-var _utils = await jitiImport("./utils.js");function _interopRequireDefault(e) {return e && e.__esModule ? e : { default: e };}
-
-const DEFAULT_TIMEOUT_MS = 30000;
-const CONCURRENT_LIMIT = 3;
-
-const NON_RECOVERABLE_ERRORS = ["Unsupported content type", "Response too large"];
-const MIN_USEFUL_CONTENT = 500;
-
-function errorMessage(err) {
- return err instanceof Error ? err.message : String(err);
-}
-
-function isConfigParseError(err) {
- return errorMessage(err).startsWith("Failed to parse ");
-}
-
-function isAbortError(err) {
- return errorMessage(err).toLowerCase().includes("abort");
-}
-
-function abortedResult(url) {
- return { url, title: "", content: "", error: "Aborted" };
-}
-
-const turndown = new _turndown.default({
- headingStyle: "atx",
- codeBlockStyle: "fenced"
-});
-
-const fetchLimit = (0, _pLimit.default)(CONCURRENT_LIMIT);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-const JINA_READER_BASE = "https://r.jina.ai/";
-const JINA_TIMEOUT_MS = 30000;
-
-async function extractWithJinaReader(
-url,
-signal)
-{
- const jinaUrl = JINA_READER_BASE + url;
-
- const activityId = _activity.activityMonitor.logStart({ type: "api", query: `jina: ${url}` });
-
- try {
- const res = await fetch(jinaUrl, {
- headers: {
- "Accept": "text/markdown",
- "X-No-Cache": "true"
- },
- signal: AbortSignal.any([
- AbortSignal.timeout(JINA_TIMEOUT_MS),
- ...(signal ? [signal] : [])]
- )
- });
-
- if (!res.ok) {
- _activity.activityMonitor.logComplete(activityId, res.status);
- return null;
- }
-
- const content = await res.text();
- _activity.activityMonitor.logComplete(activityId, res.status);
-
- const contentStart = content.indexOf("Markdown Content:");
- if (contentStart < 0) {
- return null;
- }
-
- const markdownPart = content.slice(contentStart + 17).trim(); // 17 = "Markdown Content:".length
-
- // Check for failed JS rendering or minimal content
- if (markdownPart.length < 100 ||
- markdownPart.startsWith("Loading...") ||
- markdownPart.startsWith("Please enable JavaScript")) {
- return null;
- }
-
- const title = extractHeadingTitle(markdownPart) ?? (new URL(url).pathname.split("/").pop() || url);
- return { url, title, content: markdownPart, error: null };
- } catch (err) {
- const message = err instanceof Error ? err.message : String(err);
- if (message.toLowerCase().includes("abort")) {
- _activity.activityMonitor.logComplete(activityId, 0);
- } else {
- _activity.activityMonitor.logError(activityId, message);
- }
- return null;
- }
-}
-
-function parseTimestamp(ts) {
- const num = Number(ts);
- if (!isNaN(num) && num >= 0) return Math.floor(num);
- const parts = ts.split(":").map(Number);
- if (parts.some((p) => isNaN(p) || p < 0)) return null;
- if (parts.length === 3) return Math.floor(parts[0] * 3600 + parts[1] * 60 + parts[2]);
- if (parts.length === 2) return Math.floor(parts[0] * 60 + parts[1]);
- return null;
-}
-
-
-
-function parseTimestampSpec(ts) {
- const dashIdx = ts.indexOf("-", 1);
- if (dashIdx > 0) {
- const start = parseTimestamp(ts.slice(0, dashIdx));
- const end = parseTimestamp(ts.slice(dashIdx + 1));
- if (start !== null && end !== null && end > start) return { type: "range", start, end };
- }
- const seconds = parseTimestamp(ts);
- return seconds !== null ? { type: "single", seconds } : null;
-}
-
-const DEFAULT_RANGE_FRAMES = 6;
-const MIN_FRAME_INTERVAL = 5;
-
-function computeRangeTimestamps(start, end, maxFrames = DEFAULT_RANGE_FRAMES) {
- if (maxFrames <= 1) return [start];
- const duration = end - start;
- const idealInterval = duration / (maxFrames - 1);
- if (idealInterval < MIN_FRAME_INTERVAL) {
- const timestamps = [];
- for (let t = start; t <= end && timestamps.length < maxFrames; t += MIN_FRAME_INTERVAL) {
- timestamps.push(t);
- }
- return timestamps;
- }
- return Array.from({ length: maxFrames }, (_, i) => Math.round(start + i * idealInterval));
-}
-
-function buildFrameResult(
-url, label, requestedCount,
-frames, error, duration)
-{
- if (frames.length === 0) {
- const msg = error ?? "Frame extraction failed";
- return { url, title: `Frames ${label} (0/${requestedCount})`, content: msg, error: msg };
- }
- return {
- url,
- title: `Frames ${label} (${frames.length}/${requestedCount})`,
- content: `${frames.length} frames extracted from ${label}`,
- error: null,
- frames,
- duration
- };
-}
-
-async function extractLocalFrames(
-filePath, timestamps)
-{
- const results = await Promise.all(timestamps.map(async (t) => {
- const frame = await (0, _videoExtract.extractVideoFrame)(filePath, t);
- if ("error" in frame) return { error: frame.error };
- return { ...frame, timestamp: (0, _utils.formatSeconds)(t) };
- }));
- const frames = results.filter((f) => "data" in f);
- const firstError = results.find((f) => "error" in f);
- return { frames, error: frames.length === 0 && firstError ? firstError.error : null };
-}
-
-function safeVideoInfo(url) {
- try {
- return { info: (0, _videoExtract.isVideoFile)(url) };
- } catch (err) {
- return { info: null, error: errorMessage(err) };
- }
-}
-
-async function extractContent(
-url,
-signal,
-options)
-{
- if (signal?.aborted) {
- return { url, title: "", content: "", error: "Aborted" };
- }
-
- if (options?.frames && !options.timestamp) {
- const frameCount = options.frames;
- const ytInfo = (0, _youtubeExtract.isYouTubeURL)(url);
- if (ytInfo.isYouTube && ytInfo.videoId) {
- const streamInfo = await (0, _youtubeExtract.getYouTubeStreamInfo)(ytInfo.videoId);
- if ("error" in streamInfo) {
- return { url, title: "Frames", content: streamInfo.error, error: streamInfo.error };
- }
- if (streamInfo.duration === null) {
- const error = "Cannot determine video duration. Use a timestamp range instead.";
- return { url, title: "Frames", content: error, error };
- }
- const dur = Math.floor(streamInfo.duration);
- const timestamps = computeRangeTimestamps(0, dur, frameCount);
- const result = await (0, _youtubeExtract.extractYouTubeFrames)(ytInfo.videoId, timestamps, streamInfo);
- const label = `${(0, _utils.formatSeconds)(0)}-${(0, _utils.formatSeconds)(dur)}`;
- return buildFrameResult(url, label, timestamps.length, result.frames, result.error, streamInfo.duration);
- }
-
- const localVideo = safeVideoInfo(url);
- if (localVideo.error) {
- return { url, title: "", content: "", error: localVideo.error };
- }
- if (localVideo.info) {
- const durationResult = await (0, _videoExtract.getLocalVideoDuration)(localVideo.info.absolutePath);
- if (typeof durationResult !== "number") {
- return { url, title: "Frames", content: durationResult.error, error: durationResult.error };
- }
- const dur = Math.floor(durationResult);
- const timestamps = computeRangeTimestamps(0, dur, frameCount);
- const result = await extractLocalFrames(localVideo.info.absolutePath, timestamps);
- const label = `${(0, _utils.formatSeconds)(0)}-${(0, _utils.formatSeconds)(dur)}`;
- return buildFrameResult(url, label, timestamps.length, result.frames, result.error, durationResult);
- }
-
- return { url, title: "", content: "", error: "Frame extraction only works with YouTube and local video files" };
- }
-
- if (options?.timestamp) {
- const spec = parseTimestampSpec(options.timestamp);
- if (!spec) {
- return {
- url,
- title: "",
- content: "",
- error: `Invalid timestamp format: "${options.timestamp}". Use "H:MM:SS", "MM:SS", "85", or "start-end".`
- };
- }
-
- const frameCount = options.frames;
- const ytInfo = (0, _youtubeExtract.isYouTubeURL)(url);
- if (ytInfo.isYouTube && ytInfo.videoId) {
- const streamInfo = await (0, _youtubeExtract.getYouTubeStreamInfo)(ytInfo.videoId);
- if ("error" in streamInfo) {
- if (spec.type === "range") {
- const label = `${(0, _utils.formatSeconds)(spec.start)}-${(0, _utils.formatSeconds)(spec.end)}`;
- return { url, title: `Frames ${label}`, content: streamInfo.error, error: streamInfo.error };
- }
- if (frameCount) {
- const end = spec.seconds + (frameCount - 1) * MIN_FRAME_INTERVAL;
- const label = `${(0, _utils.formatSeconds)(spec.seconds)}-${(0, _utils.formatSeconds)(end)}`;
- return { url, title: `Frames ${label}`, content: streamInfo.error, error: streamInfo.error };
- }
- return { url, title: `Frame at ${options.timestamp}`, content: streamInfo.error, error: streamInfo.error };
- }
-
- if (spec.type === "range") {
- const label = `${(0, _utils.formatSeconds)(spec.start)}-${(0, _utils.formatSeconds)(spec.end)}`;
- if (streamInfo.duration !== null && spec.end > streamInfo.duration) {
- const error = `Timestamp ${(0, _utils.formatSeconds)(spec.end)} exceeds video duration (${(0, _utils.formatSeconds)(Math.floor(streamInfo.duration))})`;
- return { url, title: `Frames ${label}`, content: error, error };
- }
- const timestamps = frameCount ?
- computeRangeTimestamps(spec.start, spec.end, frameCount) :
- computeRangeTimestamps(spec.start, spec.end);
- const result = await (0, _youtubeExtract.extractYouTubeFrames)(ytInfo.videoId, timestamps, streamInfo);
- return buildFrameResult(url, label, timestamps.length, result.frames, result.error, result.duration ?? undefined);
- }
-
- if (frameCount) {
- const end = spec.seconds + (frameCount - 1) * MIN_FRAME_INTERVAL;
- const label = `${(0, _utils.formatSeconds)(spec.seconds)}-${(0, _utils.formatSeconds)(end)}`;
- if (streamInfo.duration !== null && end > streamInfo.duration) {
- const error = `Timestamp ${(0, _utils.formatSeconds)(end)} exceeds video duration (${(0, _utils.formatSeconds)(Math.floor(streamInfo.duration))})`;
- return { url, title: `Frames ${label}`, content: error, error };
- }
- const timestamps = computeRangeTimestamps(spec.seconds, end, frameCount);
- const result = await (0, _youtubeExtract.extractYouTubeFrames)(ytInfo.videoId, timestamps, streamInfo);
- return buildFrameResult(url, label, timestamps.length, result.frames, result.error, result.duration ?? undefined);
- }
-
- if (streamInfo.duration !== null && spec.seconds > streamInfo.duration) {
- const error = `Timestamp ${(0, _utils.formatSeconds)(spec.seconds)} exceeds video duration (${(0, _utils.formatSeconds)(Math.floor(streamInfo.duration))})`;
- return { url, title: `Frame at ${options.timestamp}`, content: error, error };
- }
- const frame = await (0, _youtubeExtract.extractYouTubeFrame)(ytInfo.videoId, spec.seconds, streamInfo);
- if ("error" in frame) {
- return { url, title: `Frame at ${options.timestamp}`, content: frame.error, error: frame.error };
- }
- return { url, title: `Frame at ${options.timestamp}`, content: `Video frame at ${options.timestamp}`, error: null, thumbnail: frame };
- }
-
- const localVideo = safeVideoInfo(url);
- if (localVideo.error) {
- return { url, title: "", content: "", error: localVideo.error };
- }
- if (localVideo.info) {
- if (spec.type === "range") {
- const timestamps = frameCount ?
- computeRangeTimestamps(spec.start, spec.end, frameCount) :
- computeRangeTimestamps(spec.start, spec.end);
- const result = await extractLocalFrames(localVideo.info.absolutePath, timestamps);
- const label = `${(0, _utils.formatSeconds)(spec.start)}-${(0, _utils.formatSeconds)(spec.end)}`;
- return buildFrameResult(url, label, timestamps.length, result.frames, result.error);
- }
-
- if (frameCount) {
- const end = spec.seconds + (frameCount - 1) * MIN_FRAME_INTERVAL;
- const timestamps = computeRangeTimestamps(spec.seconds, end, frameCount);
- const result = await extractLocalFrames(localVideo.info.absolutePath, timestamps);
- const label = `${(0, _utils.formatSeconds)(spec.seconds)}-${(0, _utils.formatSeconds)(end)}`;
- return buildFrameResult(url, label, timestamps.length, result.frames, result.error);
- }
-
- const frame = await (0, _videoExtract.extractVideoFrame)(localVideo.info.absolutePath, spec.seconds);
- if ("error" in frame) {
- return { url, title: `Frame at ${options.timestamp}`, content: frame.error, error: frame.error };
- }
- return { url, title: `Frame at ${options.timestamp}`, content: `Video frame at ${options.timestamp}`, error: null, thumbnail: frame };
- }
-
- return { url, title: "", content: "", error: "Timestamp extraction only works with YouTube and local video files" };
- }
-
- const localVideo = safeVideoInfo(url);
- if (localVideo.error) {
- return { url, title: "", content: "", error: localVideo.error };
- }
- if (localVideo.info) {
- try {
- const result = await (0, _videoExtract.extractVideo)(localVideo.info, signal, options);
- if (signal?.aborted) return abortedResult(url);
- return result ?? { url, title: "", content: "", error: "Video analysis requires Gemini access. Either:\n 1. Sign into gemini.google.com in Chrome (free, uses cookies)\n 2. Set GEMINI_API_KEY in ~/.pi/web-search.json" };
- } catch (err) {
- if (isAbortError(err)) return abortedResult(url);
- return { url, title: "", content: "", error: errorMessage(err) };
- }
- }
-
- try {
- new URL(url);
- } catch {
- return { url, title: "", content: "", error: "Invalid URL" };
- }
-
- try {
- const ghResult = await (0, _githubExtract.extractGitHub)(url, signal, options?.forceClone);
- if (ghResult) return ghResult;
- if (signal?.aborted) return abortedResult(url);
- } catch (err) {
- const message = errorMessage(err);
- if (isAbortError(err)) return abortedResult(url);
- if (isConfigParseError(err)) {
- return { url, title: "", content: "", error: message };
- }
- }
-
- const ytInfo = (0, _youtubeExtract.isYouTubeURL)(url);
- let youtubeEnabled = false;
- try {
- youtubeEnabled = (0, _youtubeExtract.isYouTubeEnabled)();
- } catch (err) {
- return { url, title: "", content: "", error: errorMessage(err) };
- }
- if (ytInfo.isYouTube && youtubeEnabled) {
- try {
- const ytResult = await (0, _youtubeExtract.extractYouTube)(url, signal, options?.prompt, options?.model);
- if (ytResult) return ytResult;
- if (signal?.aborted) return abortedResult(url);
- } catch (err) {
- const message = errorMessage(err);
- if (isAbortError(err)) return abortedResult(url);
- if (isConfigParseError(err)) {
- return { url, title: "", content: "", error: message };
- }
- }
- return {
- url,
- title: "",
- content: "",
- error: "Could not extract YouTube video content. Sign into Google in Chrome for automatic access, or set GEMINI_API_KEY."
- };
- }
-
- if (signal?.aborted) return abortedResult(url);
-
- const httpResult = await extractViaHttp(url, signal, options);
-
- if (signal?.aborted) return abortedResult(url);
- if (!httpResult.error) return httpResult;
- if (NON_RECOVERABLE_ERRORS.some((prefix) => httpResult.error.startsWith(prefix))) return httpResult;
-
- const jinaResult = await extractWithJinaReader(url, signal);
- if (jinaResult) return jinaResult;
- if (signal?.aborted) return abortedResult(url);
-
- let geminiResult = null;
- try {
- geminiResult = (await (0, _geminiUrlContext.extractWithUrlContext)(url, signal)) ?? (
- await (0, _geminiUrlContext.extractWithGeminiWeb)(url, signal));
- } catch (err) {
- if (isAbortError(err)) return abortedResult(url);
- if (isConfigParseError(err)) {
- return { ...httpResult, error: errorMessage(err) };
- }
- }
-
- if (geminiResult) return geminiResult;
- if (signal?.aborted) return abortedResult(url);
-
- const guidance = [
- httpResult.error,
- "",
- "Fallback options:",
- " \u2022 Set GEMINI_API_KEY in ~/.pi/web-search.json",
- " \u2022 Sign into gemini.google.com in Chrome",
- " \u2022 Use web_search to find content about this topic"].
- join("\n");
- return { ...httpResult, error: guidance };
-}
-
-function isLikelyJSRendered(html) {
- // Extract body content
- const bodyMatch = html.match(/]*>([\s\S]*?)<\/body>/i);
- if (!bodyMatch) return false;
-
- const bodyHtml = bodyMatch[1];
-
- // Strip tags to get text content
- const textContent = bodyHtml.
- replace(/
-
-