156 lines
4.6 KiB
TypeScript
156 lines
4.6 KiB
TypeScript
import { Client } from 'pg';
|
|
import * as dotenv from 'dotenv';
|
|
import * as path from 'path';
|
|
import * as fs from 'fs';
|
|
|
|
// Load env variables
|
|
dotenv.config({ path: path.join(__dirname, '../.env.local') });
|
|
|
|
const connectionString = process.env.DATABASE_URL;
|
|
|
|
if (!connectionString) {
|
|
console.error("DATABASE_URL is not set in .env.local");
|
|
process.exit(1);
|
|
}
|
|
|
|
async function main() {
|
|
const client = new Client({ connectionString });
|
|
await client.connect();
|
|
|
|
console.log("Connected to PostgreSQL database!");
|
|
|
|
const projectId = 'be169fe8-d381-422b-8e9c-d2e513a8f902';
|
|
const threadId = 'a584c700-7ae2-4fad-a906-b8daf80fcace';
|
|
|
|
// 1. Fetch project info
|
|
const projectRes = await client.query(
|
|
"SELECT id, slug, data FROM fs_projects WHERE id = $1",
|
|
[projectId]
|
|
);
|
|
if (projectRes.rows.length === 0) {
|
|
console.error(`Project ${projectId} not found.`);
|
|
await client.end();
|
|
process.exit(1);
|
|
}
|
|
const project = projectRes.rows[0];
|
|
console.log(`Fetched project: ${project.data.name || project.slug}`);
|
|
|
|
// 2. Fetch thread messages
|
|
const messagesRes = await client.query(
|
|
"SELECT id, created_at, data FROM fs_chat_messages WHERE thread_id = $1 ORDER BY created_at ASC",
|
|
[threadId]
|
|
);
|
|
const messages = messagesRes.rows;
|
|
console.log(`Fetched ${messages.length} messages for thread ${threadId}`);
|
|
|
|
// Group messages into turns (User -> Assistant pairs)
|
|
const turns = [];
|
|
let userMsg = null;
|
|
|
|
for (const msg of messages) {
|
|
const role = msg.data.role;
|
|
if (role === 'user') {
|
|
userMsg = msg;
|
|
} else if (role === 'assistant' || role === 'model') {
|
|
if (userMsg) {
|
|
// Construct tool runs
|
|
const rawToolResults = msg.data._rawToolResults || [];
|
|
const toolCalls = msg.data.toolCalls || [];
|
|
|
|
const actionsRun = rawToolResults.map((tr: any) => {
|
|
let stdout = tr.result;
|
|
let ok = true;
|
|
let status = "success";
|
|
|
|
try {
|
|
const parsedRes = JSON.parse(tr.result);
|
|
if (parsedRes.ok === false) {
|
|
ok = false;
|
|
status = "error";
|
|
}
|
|
} catch (e) {}
|
|
|
|
return {
|
|
tool_name: tr.name,
|
|
tool_call_id: tr.id || `tc-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`, // fallback
|
|
input_args: tr.args || {},
|
|
execution_outcome: {
|
|
ok,
|
|
status,
|
|
stdout
|
|
}
|
|
};
|
|
});
|
|
|
|
// Reconstruct Google sent payload
|
|
const payloadSent = {
|
|
endpoint_url: "https://us-central1-aiplatform.googleapis.com/v1/projects/gen-lang-client-0980079410/locations/us-central1/publishers/google/models/gemini-3.1-pro-preview:generateContent",
|
|
system_instruction: "Configured via VIBN Coder System Prompt (coder.ts / buildSystemPrompt)",
|
|
contents: [
|
|
{
|
|
role: "user",
|
|
parts: [
|
|
{
|
|
text: userMsg.data.content
|
|
}
|
|
]
|
|
}
|
|
]
|
|
};
|
|
|
|
// Reconstruct Google received payload
|
|
const payloadReceived = {
|
|
timestamp_utc: msg.created_at.toISOString(),
|
|
raw_candidates: {
|
|
content: {
|
|
role: "model",
|
|
parts: [
|
|
{
|
|
thought: null,
|
|
text: msg.data.content
|
|
}
|
|
]
|
|
}
|
|
}
|
|
};
|
|
|
|
turns.push({
|
|
turn_metadata: {
|
|
message_id: userMsg.id,
|
|
timestamp_utc: userMsg.created_at.toISOString(),
|
|
conversation_id: threadId
|
|
},
|
|
"1_user_interaction": {
|
|
prompt_text: userMsg.data.content
|
|
},
|
|
"2_payload_sent_to_google": payloadSent,
|
|
"3_payload_received_from_google": payloadReceived,
|
|
"4_platform_executions_and_telemetry": {
|
|
actions_run: actionsRun
|
|
},
|
|
"5_git_version_control_diffs": []
|
|
});
|
|
|
|
userMsg = null; // reset for next turn
|
|
}
|
|
}
|
|
}
|
|
|
|
const report = {
|
|
audit_version: "2026-06-04T1.0-ULTIMATE",
|
|
project_id: projectId,
|
|
exported_at: new Date().toISOString(),
|
|
target_timestamp_utc: messages[messages.length - 1]?.created_at.toISOString() || new Date().toISOString(),
|
|
total_turns_audited: turns.length,
|
|
turns
|
|
};
|
|
|
|
const outputPath = path.join(__dirname, '../../recreated_telemetry_audit_report.json');
|
|
fs.writeFileSync(outputPath, JSON.stringify(report, null, 2));
|
|
console.log(`Successfully generated telemetry audit report and saved to: ${outputPath}`);
|
|
|
|
await client.end();
|
|
}
|
|
|
|
main().catch(console.error);
|