145 lines
5.0 KiB
C
145 lines
5.0 KiB
C
/*
|
|
* agent_conversations.h — Nostr conversation persistence for agent chat
|
|
*
|
|
* Saves and loads agent chat conversations as NIP-78 (kind 30078) addressable
|
|
* events. Each conversation is stored with:
|
|
* d-tag: "{uuid}" (no prefix — matches ai.html so conversations are
|
|
* shared between sovereign_browser and the client)
|
|
* t-tag: "client-ai-chat-v1"
|
|
*
|
|
* The event content is NIP-44 encrypted (self-to-self) JSON:
|
|
* { "schema": 1, "title": "...", "messages": [ {role, content, tool_calls, tool_call_id}, ... ] }
|
|
*
|
|
* Reuses the NIP-44 encryption + event signing + relay publishing patterns
|
|
* from settings_sync.c and bookmarks.c.
|
|
*
|
|
* See plans/cross-project-agent-sync.md (Workstream 3) for the full design.
|
|
*/
|
|
|
|
#ifndef AGENT_CONVERSATIONS_H
|
|
#define AGENT_CONVERSATIONS_H
|
|
|
|
#include <glib.h>
|
|
|
|
/* cJSON is in the vendored nostr_core_lib */
|
|
#include "../nostr_core_lib/cjson/cJSON.h"
|
|
|
|
/* nostr_signer_t is needed for init */
|
|
#include "nostr_core/nostr_signer.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/* The Nostr kind for arbitrary custom app data (NIP-78). */
|
|
#define AGENT_CONV_KIND 30078
|
|
|
|
/* The t-tag that identifies these conversation events. Matches ai.html
|
|
* so conversations are shared between sovereign_browser and the client. */
|
|
#define AGENT_CONV_T_TAG "client-ai-chat-v1"
|
|
|
|
/* The prefix for the d-tag. Empty — the d-tag is just the UUID, matching
|
|
* ai.html's d:{conversation-id} format. Kept as a macro for compatibility
|
|
* with build_d_tag()/d_tag_to_id(). */
|
|
#define AGENT_CONV_D_PREFIX ""
|
|
|
|
/*
|
|
* Initialize the conversation persistence module. Stores the signer + pubkey
|
|
* references for save/load/delete operations.
|
|
*
|
|
* signer — the user's nostr_signer_t (NULL for read-only/no-login)
|
|
* pubkey_hex — the user's hex pubkey (64 chars, may be NULL)
|
|
*
|
|
* Call after login.
|
|
*/
|
|
void agent_conversations_init(nostr_signer_t *signer,
|
|
const char *pubkey_hex);
|
|
|
|
/*
|
|
* Update the signer reference (e.g. after switching identity).
|
|
*/
|
|
void agent_conversations_set_signer(nostr_signer_t *signer,
|
|
const char *pubkey_hex);
|
|
|
|
/*
|
|
* List all saved conversations from the local SQLite cache.
|
|
*
|
|
* Queries kind 30078 events by the user's pubkey that have the
|
|
* t-tag "client-ai-chat-v1". Extracts the conversation id
|
|
* (from the d-tag, which is just the UUID), title (from the
|
|
* decrypted content), and updated_at (from created_at).
|
|
*
|
|
* Returns a newly allocated cJSON array of summary objects:
|
|
* [{"id":"...", "title":"...", "updated_at":N}, ...]
|
|
* Returns an empty array on error or if no conversations exist.
|
|
* Caller must cJSON_Delete() the result.
|
|
*/
|
|
cJSON *agent_conversations_list(void);
|
|
|
|
/*
|
|
* Save the current agent chat session to Nostr as a kind 30078 event.
|
|
*
|
|
* conversation_id — the conversation id (UUID). If NULL, a new UUID is
|
|
* generated and the d-tag becomes just "{uuid}"
|
|
* (no prefix, matching ai.html).
|
|
* title — the conversation title. If NULL, derived from the
|
|
* first user message (truncated to 60 chars).
|
|
*
|
|
* Fetches the current session's messages via agent_chat_store, NIP-44
|
|
* encrypts them, builds a kind 30078 event with the d-tag and t-tag,
|
|
* signs it, publishes to bootstrap relays, and stores in SQLite.
|
|
*
|
|
* Returns a newly allocated string with the conversation id (caller must
|
|
* g_free), or NULL on error.
|
|
*/
|
|
char *agent_conversations_save(const char *conversation_id,
|
|
const char *title);
|
|
|
|
/*
|
|
* Load a conversation from Nostr (local SQLite cache) into the agent chat
|
|
* store as the current session.
|
|
*
|
|
* conversation_id — the conversation id (the UUID used as the d-tag).
|
|
*
|
|
* Fetches the kind 30078 event with d-tag "{id}", NIP-44 decrypts
|
|
* the content, parses the messages, creates a new agent chat session,
|
|
* and populates it with the parsed messages.
|
|
*
|
|
* Returns 0 on success, -1 on error.
|
|
*/
|
|
int agent_conversations_load(const char *conversation_id);
|
|
|
|
/*
|
|
* Rename a conversation — update its title in the local SQLite cache
|
|
* and re-publish the kind 30078 event with the new title.
|
|
*
|
|
* conversation_id — the conversation id (the UUID used as the d-tag).
|
|
* new_title — the new title (must be non-NULL and non-empty).
|
|
*
|
|
* Loads the existing event, decrypts the content, replaces the title,
|
|
* re-encrypts, signs a new kind 30078 event with the same d-tag, stores
|
|
* it in SQLite, and publishes to bootstrap relays.
|
|
*
|
|
* Returns 0 on success, -1 on error.
|
|
*/
|
|
int agent_conversations_rename(const char *conversation_id,
|
|
const char *new_title);
|
|
|
|
/*
|
|
* Delete a conversation from Nostr.
|
|
*
|
|
* conversation_id — the conversation id (the UUID used as the d-tag).
|
|
*
|
|
* Publishes a kind 5 deletion event referencing the kind 30078 event id,
|
|
* and removes the event from the local SQLite cache.
|
|
*
|
|
* Returns 0 on success, -1 on error.
|
|
*/
|
|
int agent_conversations_delete(const char *conversation_id);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* AGENT_CONVERSATIONS_H */
|