83 lines
2.3 KiB
JavaScript
83 lines
2.3 KiB
JavaScript
// Interaction Awareness — SessionEnd hook (Layer 2, Node.js)
|
|
// Finalizes session record, computes duration, cleans up state.
|
|
|
|
import { existsSync } from 'fs';
|
|
import {
|
|
readStdin, initConfig, requireLayer, getSessionId,
|
|
nowEpoch, nowIso,
|
|
STATE_DIR, SESSIONS_LOG,
|
|
readState, sessionStateFile, appendJsonl, removeFile
|
|
} from './lib.mjs';
|
|
|
|
readStdin();
|
|
initConfig();
|
|
requireLayer(2);
|
|
|
|
const sid = getSessionId();
|
|
if (!sid) process.exit(0);
|
|
|
|
const nowTs = nowEpoch();
|
|
const nowIsoStr = nowIso();
|
|
const sf = sessionStateFile();
|
|
|
|
if (!existsSync(sf)) {
|
|
appendJsonl(SESSIONS_LOG, {
|
|
session_id: sid,
|
|
end: nowIsoStr,
|
|
note: 'no_state_file'
|
|
});
|
|
process.exit(0);
|
|
}
|
|
|
|
// Read final state
|
|
const state = readState();
|
|
const startEpoch = Number(state.start_epoch) || 0;
|
|
const toolCount = Number(state.tool_count) || 0;
|
|
const editCount = Number(state.edit_count) || 0;
|
|
const depFlags = Number(state.dep_flags) || 0;
|
|
const escFlags = Number(state.esc_flags) || 0;
|
|
const fatFlags = Number(state.fatigue_flags) || 0;
|
|
const valFlags = Number(state.val_flags) || 0;
|
|
const pushbackCount = Number(state.pushback_count) || 0;
|
|
// v1.2: domain_context is always written as array. Coerce v1.1.0 string shape.
|
|
const domainContextRaw = state.domain_context;
|
|
const domainContextArray = Array.isArray(domainContextRaw)
|
|
? domainContextRaw
|
|
: (domainContextRaw ? [domainContextRaw] : []);
|
|
const startIso = state.start_iso || '';
|
|
|
|
// Compute duration
|
|
let durationMin = 0;
|
|
if (startEpoch > 0) {
|
|
durationMin = Math.floor((nowTs - startEpoch) / 60);
|
|
}
|
|
|
|
// v1.2: also persist user_info_class (read-only — set during prompt-analyzer).
|
|
const userInfoClass = state.user_info_class || null;
|
|
const valseekCount = Number(state.valseek_count) || 0;
|
|
const turnCount = Number(state.turn_count) || 0;
|
|
|
|
// Append finalized session record
|
|
appendJsonl(SESSIONS_LOG, {
|
|
session_id: sid,
|
|
start: startIso,
|
|
end: nowIsoStr,
|
|
duration_min: durationMin,
|
|
tool_count: toolCount,
|
|
edit_count: editCount,
|
|
domain_context: domainContextArray,
|
|
user_info_class: userInfoClass,
|
|
valseek_count: valseekCount,
|
|
turn_count: turnCount,
|
|
flags: {
|
|
dependency: depFlags,
|
|
escalation: escFlags,
|
|
fatigue: fatFlags,
|
|
validation: valFlags,
|
|
pushback: pushbackCount
|
|
}
|
|
});
|
|
|
|
// Clean up state file
|
|
removeFile(sf);
|
|
process.exit(0);
|