% SPDX-License-Identifier: LicenseRef-Sovereign-Leviathan-SL-AGPL3-001 % Licensing: see LICENSE in the repository root. %%%------------------------------------------------------------------- %%% @doc Wire-format conversions for every entity in the data model. %%% %%% This is the single place a record from `include/hyperkitty.hrl' %%% is turned into a JSON-able map. Keeping it centralized means the %%% API layer, the event payloads, and the audit view all render a %%% given entity identically -- there is exactly one `#browser_tab{}' %%% -> map projection, not one per call site. %%% @end %%%------------------------------------------------------------------- -module(hk_schema). -include("hyperkitty.hrl"). -export([to_map/1]). to_map(#agent{} = A) -> #{ agent_id => A#agent.agent_id, objective => opt_map(A#agent.objective), state => A#agent.state, capabilities => A#agent.capabilities, action_count => A#agent.action_count, started_at_ms => A#agent.started_at_ms, updated_at_ms => A#agent.updated_at_ms, limits => A#agent.limits, result => term_or_null(A#agent.result), failure_reason => term_or_null(A#agent.failure_reason) }; to_map(#agent_objective{} = O) -> #{ objective_id => O#agent_objective.objective_id, agent_id => O#agent_objective.agent_id, description => O#agent_objective.description, success_criteria => bin_or_null(O#agent_objective.success_criteria), created_at_ms => O#agent_objective.created_at_ms }; to_map(#browser_session{} = S) -> #{ session_id => S#browser_session.session_id, owner_agent_id => bin_or_null(S#browser_session.owner_agent_id), profile => S#browser_session.profile, status => S#browser_session.status, tabs => S#browser_session.tabs, created_at_ms => S#browser_session.created_at_ms, updated_at_ms => S#browser_session.updated_at_ms }; to_map(#browser_tab{} = T) -> #{ tab_id => T#browser_tab.tab_id, session_id => T#browser_tab.session_id, url => bin_or_null(T#browser_tab.url), title => bin_or_null(T#browser_tab.title), status => T#browser_tab.status, created_at_ms => T#browser_tab.created_at_ms, updated_at_ms => T#browser_tab.updated_at_ms }; to_map(#search_job{} = J) -> #{ job_id => J#search_job.job_id, owner_agent_id => bin_or_null(J#search_job.owner_agent_id), query => J#search_job.query, stage => J#search_job.stage, max_iterations => J#search_job.max_iterations, iteration => J#search_job.iteration, results => J#search_job.results, created_at_ms => J#search_job.created_at_ms, updated_at_ms => J#search_job.updated_at_ms }; to_map(#search_result{} = R) -> #{ result_id => R#search_result.result_id, job_id => R#search_result.job_id, url => R#search_result.url, normalized_url => R#search_result.normalized_url, title => bin_or_null(R#search_result.title), snippet => bin_or_null(R#search_result.snippet), rank => term_or_null(R#search_result.rank), source_document_id => bin_or_null(R#search_result.source_document_id), created_at_ms => R#search_result.created_at_ms }; to_map(#source_document{} = D) -> #{ document_id => D#source_document.document_id, url => D#source_document.url, fetched_at_ms => D#source_document.fetched_at_ms, content_type => bin_or_null(D#source_document.content_type), extracted_text => bin_or_null(D#source_document.extracted_text), citation_map => D#source_document.citation_map }; to_map(#message{} = M) -> #{ message_id => M#message.message_id, sender => M#message.sender, recipient => M#message.recipient, timestamp => M#message.timestamp, conversation_id => M#message.conversation_id, message_type => M#message.message_type, payload => M#message.payload, status => M#message.status }; to_map(#operation{} = Op) -> #{ operation_id => Op#operation.operation_id, request_id => Op#operation.request_id, kind => Op#operation.kind, status => Op#operation.status, subject => case Op#operation.subject of {Type, Id} -> #{type => Type, id => Id}; undefined -> null end, error => term_or_null(Op#operation.error), created_at_ms => Op#operation.created_at_ms, updated_at_ms => Op#operation.updated_at_ms }. %%% internal opt_map(undefined) -> null; opt_map(Record) -> to_map(Record). bin_or_null(undefined) -> null; bin_or_null(B) -> B. term_or_null(undefined) -> null; term_or_null(T) -> T.