import {
  readChainIndex,
  resolveChainsDir
} from "./chunk-XMHBH5H6.js";
import {
  buildExtensionsBlockForConsolidation,
  runPostConsolidationMaterialize
} from "./chunk-C5HUWVH2.js";
import "./chunk-EJI5XIBB.js";
import {
  FallbackLlmClient
} from "./chunk-VX2IUQFE.js";
import "./chunk-S3IP6R6K.js";
import "./chunk-L2EXJQJP.js";
import "./chunk-7SI52C65.js";
import "./chunk-UZB5KHKX.js";
import "./chunk-KWBPHZUU.js";
import "./chunk-URB2WSKZ.js";
import "./chunk-IXEJRKCZ.js";
import "./chunk-DT5TVLJE.js";
import "./chunk-MCC6KDQF.js";
import "./chunk-YNJHCGDT.js";
import "./chunk-NN2DKE4T.js";
import "./chunk-VQXK37XA.js";
import "./chunk-PFV5C235.js";
import "./chunk-RULE4VG5.js";
import "./chunk-SCU65EZI.js";
import "./chunk-XJKFSSDW.js";
import "./chunk-DM2T26WE.js";
import "./chunk-QSVPYQPG.js";
import "./chunk-FVQJYWH7.js";
import "./chunk-4DJQYKMN.js";
import "./chunk-G7D6GZ5J.js";
import "./chunk-FAAFWE4G.js";
import "./chunk-MARWOCVP.js";
import {
  log
} from "./chunk-2ODBA7MQ.js";
import {
  isRecord
} from "./chunk-DGXUHMOV.js";
import {
  listJsonFiles,
  readJsonFile
} from "./chunk-LPSF4OQH.js";
import "./chunk-A6XUJE5D.js";
import "./chunk-PZ5AY32C.js";

// src/causal-consolidation.ts
import { createHash } from "crypto";
import path from "path";
async function readAllTrajectories(memoryDir, causalTrajectoryStoreDir) {
  const root = causalTrajectoryStoreDir ? path.join(memoryDir, causalTrajectoryStoreDir) : path.join(memoryDir, "state", "causal-trajectories");
  const trajectoriesDir = path.join(root, "trajectories");
  const files = await listJsonFiles(trajectoriesDir).catch(() => []);
  const results = [];
  for (const filePath of files) {
    try {
      const raw = await readJsonFile(filePath);
      if (isRecord(raw) && typeof raw.trajectoryId === "string") {
        results.push(raw);
      }
    } catch {
    }
  }
  return results;
}
function formatCausalContext(trajectories, chainIndex, maxChars = 8e3) {
  const bySession = /* @__PURE__ */ new Map();
  for (const t of trajectories) {
    const list = bySession.get(t.sessionKey) ?? [];
    list.push(t);
    bySession.set(t.sessionKey, list);
  }
  const lines = [];
  lines.push(`## Causal Trajectories (${trajectories.length} across ${bySession.size} sessions)`);
  lines.push("");
  for (const [sessionKey, sessionTrajs] of bySession) {
    lines.push(`### Session: ${sessionKey}`);
    for (const t of sessionTrajs.slice(0, 5)) {
      const outcome = t.outcomeKind === "success" ? "+" : t.outcomeKind === "failure" ? "-" : "~";
      lines.push(`[${outcome}] Goal: ${t.goal}`);
      lines.push(`    Action: ${t.actionSummary}`);
      lines.push(`    Outcome: ${t.outcomeSummary}`);
      if (t.followUpSummary) lines.push(`    Follow-up: ${t.followUpSummary}`);
      if (t.entityRefs?.length) lines.push(`    Entities: ${t.entityRefs.join(", ")}`);
    }
    lines.push("");
  }
  const edgeCount = Object.keys(chainIndex.edges).length;
  if (edgeCount > 0) {
    lines.push(`## Cross-Session Causal Chains (${edgeCount} connections)`);
    lines.push("");
    const trajectoryMap = new Map(trajectories.map((t) => [t.trajectoryId, t]));
    const shown = /* @__PURE__ */ new Set();
    for (const [edgeId, edge] of Object.entries(chainIndex.edges)) {
      if (shown.size >= 10) break;
      const from = trajectoryMap.get(edge.fromTrajectoryId);
      const to = trajectoryMap.get(edge.toTrajectoryId);
      if (!from || !to) continue;
      lines.push(`${edge.edgeType}: "${from.goal}" (${from.sessionKey}) \u2192 "${to.goal}" (${to.sessionKey})`);
      shown.add(edgeId);
    }
    lines.push("");
  }
  const result = lines.join("\n");
  return result.length > maxChars ? result.slice(0, maxChars) + "\n[truncated]" : result;
}
var CONSOLIDATION_PROMPT = `You are analyzing a user's causal trajectory history across multiple sessions. Trajectories record what the user tried to do (goal), what they did (action), and what happened (outcome).

Your job is to identify:
1. BEHAVIORAL RULES: Recurring patterns where the same approach consistently succeeds or fails. These should be actionable guidance for future sessions.
2. PREFERENCES: What the user cares about, prefers, or consistently chooses \u2014 even if never explicitly stated. Infer preferences from what they repeatedly do, retry until successful, or always include in their workflow.

IMPORTANT:
- Look for CROSS-SESSION patterns \u2014 things that repeat across different sessions are more significant than within-session patterns.
- A user who retries the same goal across sessions has a strong implicit preference for that outcome.
- Consistent action choices reveal preferences even when the user never says "I prefer X."
- Frame preferences as "The user would prefer responses that..." when applicable.

Output valid JSON only:
{
  "rules": [
    {"content": "actionable rule text", "category": "rule|principle", "confidence": 0.0-1.0, "evidence": ["trajectory IDs"]}
  ],
  "preferences": [
    {"statement": "The user would prefer...", "confidence": 0.0-1.0, "evidence": ["trajectory IDs"]}
  ]
}

If no clear patterns exist, return {"rules": [], "preferences": []}.`;
async function consolidateWithLlm(context, llm, agentId) {
  const response = await llm.chatCompletion(
    [
      { role: "system", content: CONSOLIDATION_PROMPT },
      { role: "user", content: context }
    ],
    { temperature: 0.2, maxTokens: 2e3, agentId }
  );
  if (!response?.content) {
    return { rules: [], preferences: [] };
  }
  try {
    let jsonStr = response.content.trim();
    const fenceMatch = jsonStr.match(/```(?:json)?\s*\n?([\s\S]*?)\n?\s*```/);
    if (fenceMatch) jsonStr = fenceMatch[1];
    const parsed = JSON.parse(jsonStr);
    return {
      rules: Array.isArray(parsed.rules) ? parsed.rules.filter(
        (r) => typeof r.content === "string" && r.content.length > 5
      ) : [],
      preferences: Array.isArray(parsed.preferences) ? parsed.preferences.filter(
        (p) => typeof p.statement === "string" && p.statement.length > 5
      ) : []
    };
  } catch {
    log.warn("[cmc] failed to parse LLM consolidation response");
    return { rules: [], preferences: [] };
  }
}
function stablePatternId(content) {
  const digest = createHash("sha256").update(`causal-pattern\0${content}`).digest("hex").slice(0, 16);
  return `causal-pattern:${digest}`;
}
function llmResultToCandidates(result) {
  const candidates = [];
  for (const rule of result.rules) {
    const category = rule.category === "principle" ? "principle" : "rule";
    candidates.push({
      id: stablePatternId(rule.content),
      sourceType: "causal-pattern",
      subject: rule.content.slice(0, 80),
      category,
      content: rule.content,
      score: Math.min(1, rule.confidence ?? 0.7),
      rationale: "LLM-identified causal pattern from cross-session trajectory analysis",
      outcome: null,
      provenance: (rule.evidence ?? []).slice(0, 5),
      agent: null,
      workflow: null
    });
  }
  return candidates;
}
async function deriveCausalPromotionCandidates(options) {
  try {
    const trajectories = await readAllTrajectories(options.memoryDir, options.causalTrajectoryStoreDir);
    if (trajectories.length < options.config.minRecurrence) return [];
    const chainsDir = resolveChainsDir(options.memoryDir, options.causalTrajectoryStoreDir);
    const chainIndex = await readChainIndex(chainsDir);
    let context = formatCausalContext(trajectories, chainIndex);
    if (options.pluginConfig) {
      const extBlock = await buildExtensionsBlockForConsolidation(options.pluginConfig);
      if (extBlock.length > 0) {
        context += "\n\n" + extBlock;
      }
    }
    const llm = new FallbackLlmClient(options.gatewayConfig, {
      workspaceDir: options.pluginConfig?.workspaceDir ?? options.workspaceDir
    });
    if (!llm.isAvailable(options.gatewayAgentId)) {
      log.debug("[cmc] no LLM available for consolidation \u2014 skipping");
      return [];
    }
    const result = await consolidateWithLlm(context, llm, options.gatewayAgentId);
    const candidates = llmResultToCandidates(result);
    log.debug(`[cmc] LLM consolidation produced ${candidates.length} rule(s) and ${result.preferences.length} preference(s)`);
    return candidates;
  } catch (error) {
    log.warn(`[cmc] consolidation failed (non-fatal): ${error instanceof Error ? error.message : String(error)}`);
    return [];
  }
}
async function synthesizeCausalPreferencesViaLlm(options) {
  try {
    const trajectories = await readAllTrajectories(options.memoryDir, options.causalTrajectoryStoreDir);
    if (trajectories.length < (options.minTrajectories ?? 2)) return null;
    const chainsDir = resolveChainsDir(options.memoryDir, options.causalTrajectoryStoreDir);
    const chainIndex = await readChainIndex(chainsDir);
    const context = formatCausalContext(trajectories, chainIndex);
    const llm = new FallbackLlmClient(options.gatewayConfig, {
      workspaceDir: options.workspaceDir
    });
    if (!llm.isAvailable(options.gatewayAgentId)) return null;
    const result = await consolidateWithLlm(context, llm, options.gatewayAgentId);
    if (result.preferences.length === 0 && result.rules.length === 0) return null;
    const lines = ["## Behavioral Insights (from Causal Chain Analysis)", ""];
    for (const pref of result.preferences) {
      lines.push(`- ${pref.statement}`);
    }
    for (const rule of result.rules) {
      lines.push(`- ${rule.content}`);
    }
    lines.push("");
    return lines.join("\n");
  } catch (error) {
    log.warn(`[cmc] preference synthesis failed (non-fatal): ${error instanceof Error ? error.message : String(error)}`);
    return null;
  }
}
async function materializeAfterCausalConsolidation(options) {
  return runPostConsolidationMaterialize("[cmc]", options);
}
export {
  deriveCausalPromotionCandidates,
  materializeAfterCausalConsolidation,
  synthesizeCausalPreferencesViaLlm
};
//# sourceMappingURL=causal-consolidation.js.map