v0.2.72 - Existing agent flow: add relay configuration prompt before Nostr recovery
This commit is contained in:
@@ -54,11 +54,11 @@ Skills compose by adoption-list order (`10123`) and trigger tags carry runtime e
|
||||
|
||||
Didactyl will support local inference, which is very privacy preserving. Remote inference does however have it's advantages, and in those cases Didactyl supports using Bitcoin Lightning and eCash inference providers.
|
||||
|
||||
## Current Status — v0.2.71
|
||||
## Current Status — v0.2.72
|
||||
|
||||
**Active build — this project is barely working. Experiment at your own risk.**
|
||||
|
||||
> Last release update: v0.2.71 — Fix Step 7 skill picker: numbers now toggle X/space, edit moved to separate 'e' command
|
||||
> Last release update: v0.2.72 — Existing agent flow: add relay configuration prompt before Nostr recovery
|
||||
|
||||
- Connects to configured relays with auto-reconnect and relay state transition logging
|
||||
- Publishes configured startup events per relay as each relay becomes connected
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
[startup 01] Relay connectivity ...
|
||||
[startup 01] Relay connectivity: OK (connected relays: 1/1)
|
||||
[startup 02] Recover runtime config from Nostr ...
|
||||
[startup 02] Recover runtime config from Nostr: OK
|
||||
[startup 03] Validate LLM config ...
|
||||
[startup 03] Validate LLM config: OK
|
||||
[startup 04] Validate admin config ...
|
||||
[startup 04] Validate admin config: OK
|
||||
[startup 05] Initialize LLM client ...
|
||||
[startup 05] Initialize LLM client: OK
|
||||
[startup 06] Detect first run via kind 10002 ...
|
||||
[startup 06] Detect first run via kind 10002: OK (first-run)
|
||||
[startup 07] Reconcile/persist startup state ...
|
||||
[startup 07] Reconcile/persist startup state: OK
|
||||
[startup 08] Initialize agent ...
|
||||
[startup 08] Initialize agent: OK
|
||||
[startup 09] Initialize trigger manager ...
|
||||
[startup 09] Initialize trigger manager: OK
|
||||
[startup 10] Load startup triggers ...
|
||||
[startup 10] Load startup triggers: OK
|
||||
[startup 11] Discover self relay list via kind 10002 ...
|
||||
[startup 11] Discover self relay list via kind 10002: OK (kind10002=1 added=0 connected=1/1)
|
||||
[startup 12] Subscribe admin context ...
|
||||
[startup 12] Subscribe admin context: OK
|
||||
[startup 13] Subscribe agent self context ...
|
||||
[startup 13] Subscribe agent self context: OK
|
||||
[startup 14] Subscribe self-skill cache ...
|
||||
[startup 14] Subscribe self-skill cache: OK (skills=10 adoptions=1)
|
||||
[startup 15] Subscribe DMs ...
|
||||
[startup 15] Subscribe DMs: OK
|
||||
[startup 16] Subscribe wallet events ...
|
||||
[startup 16] Subscribe wallet events: OK
|
||||
[startup 17] Initialize cashu wallet ...
|
||||
[startup 17] Initialize cashu wallet: OK (initialized; load/create deferred)
|
||||
[startup 18] READY: OK (agent online; entering main poll loop)
|
||||
Executable
+164
@@ -0,0 +1,164 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Build the didactyl static binary and install it to /usr/local/bin/didactyl
|
||||
# Usage:
|
||||
# ./deploy_local.sh # Release build + install
|
||||
# ./deploy_local.sh --debug # Debug build + install
|
||||
# ./deploy_local.sh --no-build # Install existing binary without rebuilding
|
||||
# ./deploy_local.sh --platform=linux/arm64 # Cross-compile + install
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
INSTALL_PREFIX="/usr/local"
|
||||
INSTALL_TARGET="${INSTALL_PREFIX}/bin/didactyl"
|
||||
|
||||
# Parse command line arguments
|
||||
DEBUG_BUILD=false
|
||||
SKIP_BUILD=false
|
||||
TARGET_PLATFORM=""
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--debug)
|
||||
DEBUG_BUILD=true
|
||||
;;
|
||||
--no-build)
|
||||
SKIP_BUILD=true
|
||||
;;
|
||||
--platform=*)
|
||||
TARGET_PLATFORM="${arg#*=}"
|
||||
;;
|
||||
-h|--help)
|
||||
echo "Usage: $0 [--debug] [--no-build] [--platform=linux/amd64|linux/arm64]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --debug Build with debug symbols"
|
||||
echo " --no-build Skip build; install an existing binary"
|
||||
echo " --platform=<platform> Cross-compile for the given platform"
|
||||
echo " -h, --help Show this help message"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: Unknown argument: $arg"
|
||||
echo "Run '$0 --help' for usage."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Determine which built binary to install
|
||||
ARCH=$(uname -m)
|
||||
case "$ARCH" in
|
||||
x86_64) DEFAULT_OUTPUT_NAME="didactyl_static_x86_64" ;;
|
||||
aarch64|arm64) DEFAULT_OUTPUT_NAME="didactyl_static_arm64" ;;
|
||||
armv7l) DEFAULT_OUTPUT_NAME="didactyl_static_armv7" ;;
|
||||
armv6l) DEFAULT_OUTPUT_NAME="didactyl_static_armv6" ;;
|
||||
*) DEFAULT_OUTPUT_NAME="didactyl_static_${ARCH}" ;;
|
||||
esac
|
||||
|
||||
# Override output name when an explicit target platform is given
|
||||
if [ -n "$TARGET_PLATFORM" ]; then
|
||||
case "$TARGET_PLATFORM" in
|
||||
linux/amd64) OUTPUT_NAME="didactyl_static_x86_64" ;;
|
||||
linux/arm64) OUTPUT_NAME="didactyl_static_arm64" ;;
|
||||
linux/arm/v7) OUTPUT_NAME="didactyl_static_armv7" ;;
|
||||
linux/arm/v6) OUTPUT_NAME="didactyl_static_armv6" ;;
|
||||
*) OUTPUT_NAME="didactyl_static_custom" ;;
|
||||
esac
|
||||
else
|
||||
OUTPUT_NAME="$DEFAULT_OUTPUT_NAME"
|
||||
fi
|
||||
|
||||
if [ "$DEBUG_BUILD" = true ]; then
|
||||
OUTPUT_NAME="${OUTPUT_NAME}_debug"
|
||||
fi
|
||||
|
||||
SOURCE_BINARY="$SCRIPT_DIR/$OUTPUT_NAME"
|
||||
|
||||
echo "=========================================="
|
||||
echo " Didactyl Local Deploy"
|
||||
echo "=========================================="
|
||||
echo "Source binary: $SOURCE_BINARY"
|
||||
echo "Install target: $INSTALL_TARGET"
|
||||
echo "Debug build: $DEBUG_BUILD"
|
||||
echo "Skip build: $SKIP_BUILD"
|
||||
[ -n "$TARGET_PLATFORM" ] && echo "Target platform: $TARGET_PLATFORM"
|
||||
echo ""
|
||||
|
||||
# Build the binary unless explicitly skipped
|
||||
if [ "$SKIP_BUILD" = false ]; then
|
||||
BUILD_ARGS=""
|
||||
if [ "$DEBUG_BUILD" = true ]; then
|
||||
BUILD_ARGS="--debug"
|
||||
fi
|
||||
if [ -n "$TARGET_PLATFORM" ]; then
|
||||
BUILD_ARGS="$BUILD_ARGS --platform=$TARGET_PLATFORM"
|
||||
fi
|
||||
|
||||
echo "Building static binary..."
|
||||
"$SCRIPT_DIR/build_static.sh" $BUILD_ARGS
|
||||
echo ""
|
||||
else
|
||||
echo "Skipping build (--no-build)"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Verify the source binary exists
|
||||
if [ ! -f "$SOURCE_BINARY" ]; then
|
||||
echo "ERROR: Binary not found at $SOURCE_BINARY"
|
||||
echo ""
|
||||
if [ "$SKIP_BUILD" = true ]; then
|
||||
echo "Run '$0' (without --no-build) to build it first."
|
||||
else
|
||||
echo "The build may have failed or produced a differently named binary."
|
||||
echo "Available didactyl_static_* binaries in $SCRIPT_DIR:"
|
||||
ls -1 "$SCRIPT_DIR"/didactyl_static_* 2>/dev/null || echo " (none found)"
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Make sure the source binary is executable
|
||||
chmod +x "$SOURCE_BINARY"
|
||||
|
||||
# Choose an install command (need root for /usr/local/bin)
|
||||
INSTALL_CMD="install -m 0755"
|
||||
if [ ! -w "${INSTALL_PREFIX}/bin" ] && [ "$(id -u)" -ne 0 ]; then
|
||||
if command -v sudo >/dev/null 2>&1; then
|
||||
INSTALL_CMD="sudo install -m 0755"
|
||||
else
|
||||
echo "ERROR: Cannot write to ${INSTALL_PREFIX}/bin and sudo is not available."
|
||||
echo "Re-run this script as root or with sudo."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Installing $SOURCE_BINARY -> $INSTALL_TARGET"
|
||||
$INSTALL_CMD "$SOURCE_BINARY" "$INSTALL_TARGET"
|
||||
|
||||
# Verify the install
|
||||
if [ ! -x "$INSTALL_TARGET" ]; then
|
||||
echo "ERROR: Install verification failed: $INSTALL_TARGET is not executable"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Binary info:"
|
||||
file "$INSTALL_TARGET"
|
||||
ls -lh "$INSTALL_TARGET"
|
||||
echo ""
|
||||
|
||||
# Quick smoke test: print version/help if the binary supports it
|
||||
echo "Smoke test: $INSTALL_TARGET --help"
|
||||
if "$INSTALL_TARGET" --help >/dev/null 2>&1; then
|
||||
echo "✓ Binary runs successfully"
|
||||
else
|
||||
echo "⚠ '$INSTALL_TARGET --help' returned non-zero (may be normal if --help is unsupported)"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo " LOCAL DEPLOYMENT COMPLETE"
|
||||
echo "=========================================="
|
||||
echo "Installed: $INSTALL_TARGET"
|
||||
echo "Run with: didactyl"
|
||||
echo "=========================================="
|
||||
@@ -0,0 +1,89 @@
|
||||
{
|
||||
// ─── Argus — Fleet Manager Agent ───────────────────────────────────
|
||||
// Named after the hundred-eyed giant of Greek mythology who sees
|
||||
// everything and never sleeps. Argus supervises a fleet of app review
|
||||
// agents for the Zapstore catalog.
|
||||
//
|
||||
// EPHEMERAL: This file is destroyed after first boot. Argus then lives
|
||||
// fully on Nostr — the relay is the single source of truth.
|
||||
|
||||
// ─── Signer (n_signer via Qubes qrexec) ────────────────────────────
|
||||
// No nsec in the agent process. Signing is delegated to n_signer
|
||||
// running in the nostr_signer qube via qrexec.
|
||||
"signer": {
|
||||
"mode": "nsigner_qrexec",
|
||||
"target_qube": "nostr_signer",
|
||||
"service_name": "qubes.NsignerRpc",
|
||||
"role": "nostr_agent",
|
||||
"role_path": "m/44'/1237'/0'/1'/0'",
|
||||
"timeout_ms": 15000
|
||||
},
|
||||
|
||||
// ─── Administrator ─────────────────────────────────────────────────
|
||||
"admin": {
|
||||
"pubkey": "npub1rmz9gu6de0m0u4ysrn39crrud099ahvfgs6pvasl4hpjr5ud7yus54xv06"
|
||||
},
|
||||
|
||||
// ─── HTTP Admin API ───────────────────────────────────────────────
|
||||
"api": {
|
||||
"enabled": true,
|
||||
"port": 8486,
|
||||
"bind_address": "127.0.0.1"
|
||||
},
|
||||
|
||||
// ─── Encrypted Startup Config Events ──────────────────────────────
|
||||
// Published as NIP-44 encrypted kind 30078 self-events on first run.
|
||||
"encrypted_events": [
|
||||
{
|
||||
"kind": 30078,
|
||||
"d_tag": "user-settings",
|
||||
"content": "{\"v\":2,\"updatedAt\":0,\"global_llm\":{\"provider\":\"ppq\",\"api_key\":\"sk-LshAWvFC0KOFgrUYiP6NmT\",\"model\":\"claude-sonnet-4.6\",\"base_url\":\"https://api.ppq.ai\",\"max_tokens\":8000,\"temperature\":0},\"didactyl\":{\"admin_pubkey\":\"npub1rmz9gu6de0m0u4ysrn39crrud099ahvfgs6pvasl4hpjr5ud7yus54xv06\",\"dm_protocol\":\"both\",\"max_turns\":30}}"
|
||||
}
|
||||
],
|
||||
|
||||
// ─── Tools ────────────────────────────────────────────────────────
|
||||
"tools": {
|
||||
"enabled": true,
|
||||
"max_turns": 30,
|
||||
"shell": {
|
||||
"enabled": true,
|
||||
"timeout_seconds": 60,
|
||||
"max_output_bytes": 65536,
|
||||
"working_directory": "/tmp"
|
||||
}
|
||||
},
|
||||
|
||||
// ─── Startup Events ───────────────────────────────────────────────
|
||||
"startup_events": [
|
||||
{
|
||||
"kind": 10002,
|
||||
"content": "",
|
||||
"tags": [
|
||||
["r", "ws://127.0.0.1:7777"]
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": 10050,
|
||||
"content": "",
|
||||
"tags": [
|
||||
["relay", "ws://127.0.0.1:7777"]
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": 0,
|
||||
"content": "{\"name\":\"Argus\",\"about\":\"Orchestrator for Zapstore app review agents. Like the hundred-eyed giant, Argus keeps watch over the fleet.\",\"picture\":\"\"}",
|
||||
"tags": []
|
||||
},
|
||||
{
|
||||
"kind": 31124,
|
||||
"content": "# Argus\n\nYou are Argus, a sovereign AI agent living on Nostr.\nYour job is to supervise a fleet of app review agents for the Zapstore catalog.\nLike your namesake — the hundred-eyed giant who sees everything and never sleeps — you keep watch over the fleet.\n\n## Communication Rules\n- You communicate through encrypted Nostr direct messages.\n- Keep responses concise and clear.\n\n## Behavior\n- Be helpful and technically accurate.\n- If unsure, state uncertainty directly.\n- Prefer actionable, practical advice.\n- Use the person's name when messaging them if you know it.\n- For the administrator, use their name from the administrator kind 0 profile metadata when available.\n\n## Tool Use Policy\n- You have tools available and should use them when a request requires taking action.\n- For requests involving local inspection or command execution, call `local_shell_exec` instead of refusing.\n- For posting to Nostr, call `nostr_post` with explicit `kind` and `content`.\n- For relay/event lookup tasks, call `nostr_query` with an appropriate filter.\n- After a tool call, base your answer on the actual tool result.\n- Never claim a tool was run if no tool was executed.\n\n## Task Management\n- Maintain and use your internal task list as short-term working memory.\n- Break long or complex actions into clear tasks before executing them.\n- Update task status as you complete steps so your plan stays accurate.\n\n## Fleet Manager Responsibilities\n- You supervise a fleet of app review agents, each assigned to one app in the Zapstore catalog.\n- Each app agent subscribes to kind 3063 events for its app and reviews new APK versions.\n- You can create new app agents by writing genesis configs, starting them, and verifying they boot.\n- You perform daily health checks: query for missing/stale reviews, check agent processes, fix what you can.\n- If you cannot fix a problem, DM the admin with a summary.\n- Genesis files are ephemeral: destroy them after the agent boots and publishes its startup events.\n- The relay is the single source of truth for all agent state after genesis.\n\n## Safety\n- Do not claim to have executed actions you did not execute.\n- You may share your public key (npub) with anyone.\n- Never reveal your private key (nsec) under any circumstance.\n\n## Recent DM History\n\nReference prior conversation naturally when it is relevant to the current request. Do not repeat entire DM history back to the user unless explicitly asked. Use this context to avoid asking questions that were already answered in recent messages.\n\n{{nostr_dm_history({\"limit\":10,\"format\":\"text\"})}}\n\n---template---\n\n- section: admin_identity\n role: system\n tool: admin_identity\n skip_if_empty: true\n\n- section: admin_profile\n role: system\n tool: nostr_admin_profile\n skip_if_empty: true\n\n- section: admin_contacts\n role: system\n tool: nostr_admin_contacts\n skip_if_empty: true\n\n- section: admin_relays\n role: system\n tool: nostr_admin_relays\n skip_if_empty: true\n\n- section: admin_notes\n role: system\n tool: nostr_admin_notes\n skip_if_empty: true\n\n- section: agent_identity\n role: system\n tool: agent_identity\n skip_if_empty: true",
|
||||
"tags": [
|
||||
["d", "argus-default"],
|
||||
["app", "didactyl"],
|
||||
["scope", "private"],
|
||||
["trigger", "dm"],
|
||||
["filter", "{\"from\":\"admin\"}"]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
+923
-260
File diff suppressed because it is too large
Load Diff
+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 2
|
||||
#define DIDACTYL_VERSION_PATCH 71
|
||||
#define DIDACTYL_VERSION "v0.2.71"
|
||||
#define DIDACTYL_VERSION_PATCH 72
|
||||
#define DIDACTYL_VERSION "v0.2.72"
|
||||
|
||||
// Agent metadata
|
||||
#define DIDACTYL_NAME "Didactyl"
|
||||
|
||||
@@ -3605,6 +3605,21 @@ static int existing_agent_flow(didactyl_config_t* cfg) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Relay Configuration — let the operator specify which relays to search
|
||||
* for the agent's kind 10002 / kind 30078 events before recovery runs.
|
||||
* Mirrors the new-agent relay menu (prompt_relay_configuration_with_header). */
|
||||
for (;;) {
|
||||
int rrc = prompt_relay_configuration_with_header(cfg,
|
||||
"Existing Agent",
|
||||
"Existing Agent -- Relay Configuration");
|
||||
if (rrc < 0) {
|
||||
if (flow_signer) nostr_signer_free(flow_signer);
|
||||
return -1;
|
||||
}
|
||||
if (rrc == 0 || rrc == 1) break;
|
||||
}
|
||||
relay_changed = 1;
|
||||
|
||||
int relay_found = 0;
|
||||
if (recover_existing_config_from_nostr(cfg, &relay_found) != 0 || !relay_found) {
|
||||
render_wizard_page_header("Existing Agent", "Config Recovery");
|
||||
|
||||
Reference in New Issue
Block a user