#!/usr/bin/env node
/**
 * session-observer — PostToolUse hook for autonomous learning.
 *
 * Captures tool usage observations to a JSONL buffer for later pattern analysis.
 * Fire-and-forget writes (<5ms). Nudges agent when batch threshold reached.
 *
 * @tier efficiency
 * @event PostToolUse
 * @scope user
 */
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import process from 'node:process';
import { createHook } from './_runtime.mjs';

const bufferPath = path.join(os.tmpdir(), `aikit-obs-${process.ppid}.jsonl`);
const BATCH_THRESHOLD = 20;
const EXCLUDE = new Set([
  'knowledge',
  'replay',
  'stash',
  'checkpoint',
  'session_digest',
  'reindex',
  'status',
  'flow',
  'evidence_map',
  'present',
]);

const countLines = (filePath) => {
  try {
    return fs.readFileSync(filePath, 'utf8').split('\n').filter(Boolean).length;
  } catch {
    return 0;
  }
};

const summarize = (input, maxLen = 200) => {
  if (!input) return '';
  const value = typeof input === 'string' ? input : JSON.stringify(input);
  return value.length > maxLen ? `${value.slice(0, maxLen)}...` : value;
};

/** Captures tool-use observations and nudges lesson extraction at batch thresholds. */
export const sessionObserver = async (context) => {
  if (context.event !== 'PostToolUse') return { decision: 'allow' };
  const toolBase = context.toolName.replace(/^mcp_aikit_/, '');
  if (EXCLUDE.has(toolBase)) return { decision: 'allow' };

  const entry = JSON.stringify({
    ts: Date.now(),
    tool: context.toolName,
    input: summarize(context.toolInput),
    files: context.filePaths.slice(0, 5),
  });

  try {
    fs.appendFileSync(bufferPath, `${entry}\n`);
  } catch {}

  const count = countLines(bufferPath);
  if (count > 0 && count >= BATCH_THRESHOLD && count % BATCH_THRESHOLD === 0) {
    return {
      additionalContext: [
        `[Observer] ${count} tool calls captured this session.`,
        'Consider: knowledge({ action: "lesson", subAction: "auto-observe" })',
      ].join(' '),
    };
  }

  return { decision: 'allow' };
};

createHook(sessionObserver);
