v0.0.6 - Remove top-level agent config, move SYSTEM prompt into Soul startup event, and update Quick Start binary flow
This commit is contained in:
@@ -26,13 +26,25 @@ Because all identity, communication, and memory live on Nostr, the agent is **po
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Prerequisites
|
||||
### Download binary (recommended)
|
||||
|
||||
1. Download the latest release binary from GitLab: <https://git.laantungir.net/laantungir/didactyl/-/releases>
|
||||
2. Make it executable and run it:
|
||||
|
||||
```bash
|
||||
chmod +x ./didactyl_static_x86_64
|
||||
./didactyl_static_x86_64 --config ./config.json
|
||||
```
|
||||
|
||||
### Build from source (optional)
|
||||
|
||||
#### Prerequisites
|
||||
|
||||
- Docker (for static binary build)
|
||||
- An OpenAI-compatible LLM API key (OpenAI, PPQ, Ollama, etc.)
|
||||
- A Nostr keypair (nsec)
|
||||
|
||||
### Build
|
||||
#### Build
|
||||
|
||||
```bash
|
||||
./build_static.sh # builds a fully static MUSL binary via Docker
|
||||
@@ -44,14 +56,6 @@ Edit [`config.json`](config.json):
|
||||
|
||||
```json
|
||||
{
|
||||
"agent": {
|
||||
"name": "Didactyl Agent",
|
||||
"display_name": "Didactyl",
|
||||
"about": "A sovereign AI agent on Nostr",
|
||||
"picture": "https://...",
|
||||
"banner": "https://...",
|
||||
"nip05": ""
|
||||
},
|
||||
"keys": {
|
||||
"nsec": "nsec1...",
|
||||
"npub": "npub1...",
|
||||
@@ -108,13 +112,13 @@ Edit [`config.json`](config.json):
|
||||
### Run
|
||||
|
||||
```bash
|
||||
./didactyl
|
||||
./didactyl_static_x86_64 --config ./config.json
|
||||
```
|
||||
|
||||
Options:
|
||||
```
|
||||
./didactyl --config <path> # custom config file (default: ./config.json)
|
||||
./didactyl --debug <0-5> # log verbosity (0 none, 3 info, 5 trace)
|
||||
./didactyl_static_x86_64 --config <path> # custom config file (default: ./config.json)
|
||||
./didactyl_static_x86_64 --debug <0-5> # log verbosity (0 none, 3 info, 5 trace)
|
||||
```
|
||||
|
||||
### Talk to it
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
# Didactyl Agent
|
||||
|
||||
You are Didactyl, a sovereign AI agent living on Nostr.
|
||||
|
||||
## Communication Rules
|
||||
- You communicate through encrypted Nostr direct messages.
|
||||
- Keep responses concise and clear.
|
||||
|
||||
## Behavior
|
||||
- Be helpful and technically accurate.
|
||||
- If unsure, state uncertainty directly.
|
||||
- Prefer actionable, practical advice.
|
||||
|
||||
## Tool Use Policy
|
||||
- You have tools available and should use them when a request requires taking action.
|
||||
- For requests involving local inspection or command execution, call `shell_exec` instead of refusing.
|
||||
- For posting to Nostr, call `nostr_post` with explicit `kind` and `content`.
|
||||
- For relay/event lookup tasks, call `nostr_query` with an appropriate filter.
|
||||
- After a tool call, base your answer on the actual tool result.
|
||||
- Never claim a tool was run if no tool was executed.
|
||||
|
||||
## Safety
|
||||
- Do not claim to have executed actions you did not execute.
|
||||
- Do not reveal secrets from configuration or keys.
|
||||
+1
-19
@@ -417,34 +417,16 @@ int config_load(const char* path, didactyl_config_t* config) {
|
||||
|
||||
int rc = -1;
|
||||
|
||||
cJSON* agent = cJSON_GetObjectItemCaseSensitive(root, "agent");
|
||||
cJSON* keys = cJSON_GetObjectItemCaseSensitive(root, "keys");
|
||||
cJSON* admin = cJSON_GetObjectItemCaseSensitive(root, "admin");
|
||||
cJSON* llm = cJSON_GetObjectItemCaseSensitive(root, "llm");
|
||||
|
||||
if (!agent || !cJSON_IsObject(agent) ||
|
||||
!keys || !cJSON_IsObject(keys) ||
|
||||
if (!keys || !cJSON_IsObject(keys) ||
|
||||
!admin || !cJSON_IsObject(admin) ||
|
||||
!llm || !cJSON_IsObject(llm)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (copy_json_string(agent, "name", config->profile.name, sizeof(config->profile.name), 1) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
if (copy_json_string(agent, "display_name", config->profile.display_name, sizeof(config->profile.display_name), 1) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
if (copy_json_string(agent, "about", config->profile.about, sizeof(config->profile.about), 1) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
if (copy_json_string(agent, "picture", config->profile.picture, sizeof(config->profile.picture), 0) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
if (copy_json_string(agent, "nip05", config->profile.nip05, sizeof(config->profile.nip05), 0) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (copy_json_string(keys, "nsec", config->keys.nsec, sizeof(config->keys.nsec), 1) != 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@@ -9,14 +9,6 @@
|
||||
#define OW_MAX_KEY_LEN 256
|
||||
#define OW_MAX_MODEL_LEN 128
|
||||
|
||||
typedef struct {
|
||||
char name[OW_MAX_NAME_LEN];
|
||||
char display_name[OW_MAX_NAME_LEN];
|
||||
char about[OW_MAX_ABOUT_LEN];
|
||||
char picture[OW_MAX_URL_LEN];
|
||||
char nip05[OW_MAX_URL_LEN];
|
||||
} agent_profile_t;
|
||||
|
||||
typedef struct {
|
||||
char nsec[OW_MAX_KEY_LEN];
|
||||
unsigned char private_key[32];
|
||||
@@ -57,7 +49,6 @@ typedef struct {
|
||||
} startup_event_t;
|
||||
|
||||
typedef struct {
|
||||
agent_profile_t profile;
|
||||
agent_keys_t keys;
|
||||
admin_config_t admin;
|
||||
char** relays;
|
||||
|
||||
+2
-2
@@ -12,8 +12,8 @@
|
||||
// Using DIDACTYL_ prefix to avoid conflicts with nostr_core_lib VERSION macros
|
||||
#define DIDACTYL_VERSION_MAJOR 0
|
||||
#define DIDACTYL_VERSION_MINOR 0
|
||||
#define DIDACTYL_VERSION_PATCH 5
|
||||
#define DIDACTYL_VERSION "v0.0.5"
|
||||
#define DIDACTYL_VERSION_PATCH 6
|
||||
#define DIDACTYL_VERSION "v0.0.6"
|
||||
|
||||
// Agent metadata
|
||||
#define DIDACTYL_NAME "Didactyl"
|
||||
|
||||
@@ -390,74 +390,6 @@ int nostr_handler_init(didactyl_config_t* config) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nostr_handler_publish_profile(void) {
|
||||
if (!g_cfg || !g_pool) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUG_INFO("[didactyl] publish_profile: build metadata payload");
|
||||
cJSON* profile = cJSON_CreateObject();
|
||||
if (!profile) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
cJSON_AddStringToObject(profile, "name", g_cfg->profile.name);
|
||||
cJSON_AddStringToObject(profile, "display_name", g_cfg->profile.display_name);
|
||||
cJSON_AddStringToObject(profile, "about", g_cfg->profile.about);
|
||||
cJSON_AddStringToObject(profile, "picture", g_cfg->profile.picture);
|
||||
if (g_cfg->profile.nip05[0] != '\0') {
|
||||
cJSON_AddStringToObject(profile, "nip05", g_cfg->profile.nip05);
|
||||
}
|
||||
|
||||
char* content = cJSON_PrintUnformatted(profile);
|
||||
cJSON_Delete(profile);
|
||||
if (!content) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUG_INFO("[didactyl] publish_profile: sign kind-0 event");
|
||||
cJSON* event = nostr_create_and_sign_event(0, content, NULL, g_cfg->keys.private_key, time(NULL));
|
||||
free(content);
|
||||
|
||||
if (!event) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char** connected_relays = (const char**)calloc((size_t)g_cfg->relay_count, sizeof(char*));
|
||||
if (!connected_relays) {
|
||||
cJSON_Delete(event);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int connected_count = 0;
|
||||
for (int i = 0; i < g_cfg->relay_count; i++) {
|
||||
if (nostr_relay_pool_get_relay_status(g_pool, g_cfg->relays[i]) == NOSTR_POOL_RELAY_CONNECTED) {
|
||||
connected_relays[connected_count++] = g_cfg->relays[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (connected_count == 0) {
|
||||
DEBUG_WARN("[didactyl] publish_profile: no connected relays yet, deferring publish");
|
||||
free(connected_relays);
|
||||
cJSON_Delete(event);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEBUG_INFO("[didactyl] publish_profile: publishing to %d connected relay(s)", connected_count);
|
||||
int sent = nostr_relay_pool_publish_async(
|
||||
g_pool,
|
||||
connected_relays,
|
||||
connected_count,
|
||||
event,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
free(connected_relays);
|
||||
cJSON_Delete(event);
|
||||
DEBUG_INFO("[didactyl] publish profile result: sent_to=%d connected relay(s)", sent);
|
||||
return sent > 0 ? 0 : -1;
|
||||
}
|
||||
|
||||
int nostr_handler_subscribe_dms(dm_callback_t callback, void* user_data) {
|
||||
if (!g_cfg || !g_pool || !callback) {
|
||||
return -1;
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
typedef void (*dm_callback_t)(const char* sender_pubkey_hex, const char* message, void* user_data);
|
||||
|
||||
int nostr_handler_init(didactyl_config_t* config);
|
||||
int nostr_handler_publish_profile(void);
|
||||
int nostr_handler_subscribe_dms(dm_callback_t callback, void* user_data);
|
||||
int nostr_handler_send_dm(const char* recipient_pubkey_hex, const char* message);
|
||||
int nostr_handler_publish_kind_event(int kind, const char* content, cJSON* tags);
|
||||
|
||||
Reference in New Issue
Block a user