// hook-speak.js — 从 Claude/Codex Stop hook payload 中提取 assistant 文本
// 用法: node hook-speak.js <source> < payload.json
const fs = require("fs");
const crypto = require("crypto");

const MAX_LEN = 5000;

const source = process.argv[2] || "claude";
const stateFile =
  process.env.IVOX_HOOK_STATE_FILE ||
  (process.env.HOME || "~") + "/.config/ivox/hook.last";

const input = fs.readFileSync(0, "utf8");
const payload = parseJSON(input) || {};

let text = payload.last_assistant_message || "";

if (text) {
  rememberSpoken(source, payload, text);
}

if (text.length > MAX_LEN) {
  text = text.slice(0, MAX_LEN);
}

process.stdout.write(text);

// ========== helpers ==========

function parseJSON(str) {
  try { return JSON.parse(str); } catch { return null; }
}

function rememberSpoken(source, payload, text) {
  saveState(stateFile, stateKey(source, payload, text));
}

function stateKey(source, payload, text) {
  const turnId =
    payload["turn-id"] || payload.turn_id || payload.turnId || "";
  return [source, turnId || hashText(text)].join(":");
}

function saveState(file, value) {
  if (!file) return;
  try {
    fs.mkdirSync(require("path").dirname(file), { recursive: true });
    fs.writeFileSync(file, value, "utf8");
  } catch {}
}

function hashText(text) {
  return crypto.createHash("sha1").update(text, "utf8").digest("hex");
}
