v0.0.79 - Enhance existing-agent wizard with full config recovery review edit flow and new-agent fallback

This commit is contained in:
Your Name
2026-03-18 10:14:10 -04:00
parent 42fc14a5b3
commit 7675109afc
6 changed files with 592 additions and 16 deletions

View File

@@ -0,0 +1,149 @@
# Enhanced Existing Agent Wizard Flow
## Problem
When choosing "existing agent" in the wizard, the current flow:
1. Asks for nsec
2. Recovers kind 10002 relay list from Nostr
3. Immediately boots the agent
This is insufficient when installing an existing agent on a **new server** because:
- You cannot review or change the admin pubkey
- You cannot review or change the LLM provider/model/API key
- You cannot install a systemd service with a dedicated user
- You cannot see what config was recovered from Nostr
- The agent name is not recovered from the kind 0 profile
## Current Code
- [`existing_agent_flow()`](src/setup_wizard.c:1795) — 22 lines, minimal recovery
- [`recover_existing_config_from_nostr()`](src/setup_wizard.c:792) — only recovers kind 10002 relays
- Returns `SETUP_WIZARD_RC_EXISTING` (2) which does NOT set `bootstrap_mode`
- In `main.c`, existing agents skip `reconcile_startup_events()` unless `first_run` is detected
## Data Available on Nostr for an Existing Agent
| Data | Kind | Storage | Recovery Method |
|------|------|---------|-----------------|
| Relay list | 10002 | Public tags | `query_and_extract_kind10002_relays()` |
| Agent profile/name | 0 | Public JSON content | Query kind 0 by agent pubkey |
| LLM config | 30078 d=llm_config | NIP-44 encrypted to self | `fetch_self_config_plaintext()` |
| Agent config - admin pubkey, DM protocol | 30078 d=agent_config | NIP-44 encrypted to self | `fetch_self_config_plaintext()` |
| Default skill | 31124 d=didactyl-default | Public content | Query kind 31124 by agent pubkey |
| Adoption list | 10123 | Public tags | Query kind 10123 by agent pubkey |
## Proposed Enhanced Flow
```mermaid
flowchart TD
A[Enter nsec] --> B[Connect to default relays]
B --> C[Recover kind 10002 relay list]
C --> D{Relay list found?}
D -->|No| E{Offer to create new agent with this nsec}
E -->|Yes| E2[Jump to new_agent_flow with nsec pre-loaded]
E -->|No| E3[Return to main menu]
D -->|Yes| F[Reconnect with recovered relays]
F --> G[Recover all config from Nostr]
G --> H[Display recovered config summary]
H --> I{Review each setting}
I -->|Keep all| J[Review summary + launch options]
I -->|Change admin| K[Prompt new admin pubkey]
I -->|Change LLM| L[Prompt LLM config]
I -->|Change relays| M[Prompt relay config]
K --> I
L --> I
M --> I
J --> N{Launch option}
N -->|Boot now| O[Return EXISTING]
N -->|Install systemd| P[Install dedicated-user service]
N -->|Quit| Q[Exit]
```
### Step-by-step
#### Step 1: Identity — Enter nsec
Same as current. Derive keys from nsec.
#### Step 2: Recovery — Connect and fetch config from Nostr
1. Init nostr handler with default relays
2. Wait for relay connections
3. Query kind 10002 for relay list — if not found, offer to create a new agent with this nsec (jump to `new_agent_flow` with keys pre-loaded, skipping identity step)
4. Cleanup and re-init with recovered relays
5. Wait for relay connections on recovered relays
6. Query kind 0 for agent profile — extract display_name/name
7. Query kind 30078 d=llm_config — decrypt and parse LLM settings
8. Query kind 30078 d=agent_config — decrypt and parse admin pubkey + DM protocol
9. Cleanup nostr handler
#### Step 3: Review — Present recovered config
Display all recovered values:
```
┌─────────────────────────────────────────────┐
│ Existing Agent -- Recovered Configuration │
├─────────────────────────────────────────────┤
│ Agent name: Simon │
│ Identity: b27072b7fc2edf45... │
│ Admin: a1b2c3d4e5f6... │
│ LLM Provider: ppq │
│ LLM Model: claude-haiku-4.5 │
│ LLM Base URL: https://api.ppq.ai │
│ LLM API Key: sk-...**** │
│ DM Protocol: nip04 │
│ Relays: 5 configured │
└─────────────────────────────────────────────┘
```
Then offer a menu:
```
[a] change Admin pubkey
[l] change LLM provider/model/key
[r] change Relay configuration
[c] continue with these settings
[q] quit
```
Each change option reuses the existing prompt functions (`prompt_admin_pubkey`, `prompt_llm_config`, `prompt_relay_configuration`) but with context-appropriate headers.
After any change, redisplay the summary and menu.
#### Step 4: Launch — Boot or install systemd
Same as the new-agent flow's final step:
```
[b] boot the agent now
[i] install dedicated-user systemd service and boot
[q] quit
```
The systemd install reuses `install_system_service_with_dedicated_user()`.
### Return Codes
- If user chooses "boot now": return `SETUP_WIZARD_RC_EXISTING` (2) — same as current
- If user chooses "install systemd": return `SETUP_WIZARD_RC_EXIT` (1) — agent runs as systemd service
- If user changed config values: the `main()` flow should still work because `recover_missing_runtime_config_from_nostr()` at line 1108 will fill in any gaps, and the existing agent path at line 1163 loads system context from adopted skills
### Key Consideration: bootstrap_mode for changed configs
If the user changes LLM or admin config in the wizard, those changes need to be persisted back to Nostr. Currently, `persist_runtime_config_to_nostr()` is only called when `bootstrap_mode || first_run`.
**Solution**: When the existing-agent wizard detects that config was changed, return `SETUP_WIZARD_RC_BOOTSTRAP` (0) instead of `SETUP_WIZARD_RC_EXISTING` (2). This triggers the full reconcile path which persists the updated config.
## Files to Modify
1. **`src/setup_wizard.c`**:
- Add `recover_full_config_from_nostr()` — fetches kind 0, kind 30078 llm_config, kind 30078 agent_config
- Add `query_self_kind0_name()` — queries agent's own kind 0 profile for name
- Add `fetch_and_decrypt_self_config()` — replicates `fetch_self_config_plaintext()` logic from main.c for use in wizard context
- Rewrite `existing_agent_flow()` with the enhanced multi-step flow
- Make `prompt_admin_pubkey()`, `prompt_llm_config()`, `prompt_relay_configuration()` accept a context string parameter for the page header, or add wrapper versions for the existing-agent context
2. **`src/main.c`**:
- Potentially expose `fetch_self_config_plaintext()`, `apply_recalled_llm_config()`, `apply_recalled_agent_config()` as non-static, OR duplicate the logic in setup_wizard.c
- Better approach: move these to a shared location or make them accessible via a header
## Implementation Notes
- The wizard already calls `nostr_handler_init()` / `nostr_handler_cleanup()` for validation queries. The enhanced flow will do the same but with two init/cleanup cycles: first with default relays to get kind 10002, then with recovered relays to get everything else.
- The `prompt_admin_pubkey()` and `prompt_llm_config()` functions currently have hardcoded step headers like "Step 3 of 7". These should be parameterized or have existing-agent variants.
- The `fetch_self_config_plaintext()` function in main.c requires an active nostr handler. The wizard will need to have the handler initialized when calling it.
- API key display should be masked — show only first 4 and last 4 characters.