Repository navigation
Web-first setup wizard, external-auth support, workspace templates and best-practice guides - #500
Conversation
…ps the full wizard
…he slim init started is not started twice
…, connection provenance - Default Claude models live in one block at the top of nerve/config.py (agent.model is now claude-opus-5-5; a test fails on any other literal). - The Sources step can sign the Telegram message sync in from the browser (phone, code, two-step password); nerve setup-telegram stays as fallback. - Every credential the setup page reports carries its source (file, environment, config repository, channel gateway); managed values are read-only and documented for operators in docs/setup.md.
…ed connections, plain copy
… the worker TASK.md template
SOUL, AGENTS, TOOLS and MEMORY for both modes are now short operating rules
distilled from docs/personal-best-practices.md and docs/worker-best-practices.md,
each file one job, no slogans; the guides stay linked from AGENTS.md. The worker
gets a TASK.md template with the guide's anatomy, an onboarding-pending marker
and a {{TASK_DESCRIPTION}} slot. Sizes: personal AGENTS 11.9 → 7.0 KB,
worker AGENTS 8.6 → 6.9 KB, MEMORY and SOUL roughly halved.
…orker guide in the onboarding prompt apply_mode renders TASK.md from the worker template (browser, --terminal and --non-interactive share the writer); onboarding-pending is keyed on the marker, legacy raw files still recognised; the first-boot onboarding session receives docs/worker-best-practices.md in full (read from the checkout, packaged copy as fallback, identity-tested) and is told to fill every section in place and delete the marker last. Goldens and docs follow.
…sk/cron state machine; no memory backend named
…emantics match the code
… workers; onboarding ends with a walkthrough and next steps
…ocker host view on Linux); port-probe test models the gateway's SO_REUSEADDR listener
…rkspace path; test models the Linux permission case
|
Environment-only credential: the checks see it, the API clients do not This PR makes The two client factories still pass Reproduction on f36703a: $ ANTHROPIC_API_KEY=sk-ant-envkey123 uv run python -c '
from nerve.config import NerveConfig
c = NerveConfig.from_dict({})
print(c.credential_available(), c.resolve_anthropic_api_key())
cl = c.create_anthropic_client()
print(repr(cl.api_key), cl.base_url)'
True sk-ant-envkey123
'' https://api.anthropic.comThese callers pass the new check and then build a client with no key:
Prompt rewrite (prompt_rewrite.py#L101), source condensing (registry.py#L41) and the Suggested fix: in both factories, pass The endpoint is the other half. |
|
Follow-up for a later PR: worker starter templates Not a blocker for this PR. The worker Mode step shows three pills: "Monitor a build", "Review pull requests" and "Watch logs" (copy.ts#L79-L92, ModeStep.tsx#L105-L111). Each pill replaces the full task description with one fixed paragraph that names Proposal:
Maybe this should even be combined with the Automation page? |
| "max_turns": 50, | ||
| "max_concurrent": 32, | ||
| "thinking": "max", | ||
| "effort": "max", |
There was a problem hiding this comment.
The default effort should be xhigh imo. max is a bad default on the 5.5 models, expensive and slow for no real gains.
The same default is also in AgentConfig.effort = "max" (config.py#L952), which applies to every install that has no agent.effort. A DEFAULT_EFFORT = "xhigh" in the default-model constants block at the top of config.py could serve both. The four settings.yaml goldens change with it.
There was a problem hiding this comment.
| const configured = detail.openai_api_key.configured; | ||
| const managed = secretManaged(detail.openai_api_key) !== null; | ||
|
|
||
| const [choice, setChoice] = useState<Choice>(() => (configured ? 'embeddings' : 'without')); |
There was a problem hiding this comment.
"Use embeddings" should be the default choice here, not "No embeddings".
It should also work with no input on a hosted instance. There the person has no OpenAI key to paste, so Nerve must get the embedding endpoint and credential from the platform:
- The embedding client has
https://api.openai.com/v1hard-coded and takes its key only fromopenai_api_key(memu_bridge.py#L1669-L1675). It needs a configurable OpenAI-compatible base URL, the same way Add anthropic_base_url so every model request can use one Anthropic-compatible endpoint #484 addsanthropic_base_urlfor the Anthropic calls. - When the platform supplies the endpoint and the credential, this step should show embeddings as on and managed, as it does now for a managed
openai_api_key.
There was a problem hiding this comment.
Done in daace27: the step opens on "Use embeddings" (a step that was answered without a key still shows that answer). The hosted case — an OpenAI-compatible embedding base URL and credential supplied by the platform, shown as managed — is a follow-up alongside the base-URL change in #484.
Generated by Nerve
|
Went through the wizard and the restart process and it all works very smoothly, it's great. Just need to lock down certain sections for the hosted mode and it's great. Also maybe in the future an MCP step would make sense as well? |
…client factories take the key the checks accept, environment included
|
Fixed in 829c4ca: both client factories now pass
|
Summary
Setup moves into the browser.
nerve initnow asks only what the terminal has to know — server or Docker, workspace, port, bind — writes the machine layer, starts the daemon and hands over to a setup page. Everything else (mode, model provider, profile, memory, channels, sources, automation, agents) is a server-authoritative checklist in the web UI that works for local accounts and for instances with external authentication. The workspace brain-file templates are rewritten from two new best-practice guides, and the worker guide is injected in full into the worker's first-boot onboarding session.What changed
Setup backend and API
nerve/setup_writer.py) produces identical files for the browser flow,nerve init --terminalandnerve init --non-interactive; golden fixtures pin the output.nerve/setup_checklist.py): each step's status comes from config, workspace and DB facts; only skips, answers and restart debts are stored.GET /api/setup,PUT /api/setup/{mode|provider|profile|memory|channels|sources|automation|agents}with PATCH semantics, skip/unskip, provider test, model catalog, channel token verification, Telegram pairing,POST /api/setup/finish,POST /api/system/restartwith a boot generation in/health.blocked, never nagged.nerve/config.py(DEFAULT_MODELis Opus 5.5; a test fails if a model id is hardcoded elsewhere); the picker lists what the key's catalog advertises.nerve setup-telegramdoes.file,environment,config-repo,gateway), so pre-configured connections render read-only with an explanation andnerve doctorprints the source.CLI and installer
nerve init(flags--terminal,--deployment,--workspace,--port,--bind localhost|lan,--no-start,--no-browser,--no-clipboard,--yes); re-running on a configured install prints status and exits 0.install.shno longer starts the daemon twice (status probe captured before it is searched).Web
Workspace templates, guides and onboarding
docs/personal-best-practices.mdanddocs/worker-best-practices.md: practices with the reasoning and an adoptable example; the worker guide is built around the task/cron state machine. No memory backend is named.TASK.mdskeleton with an onboarding marker). Byte budgets keep the injected prompt small.TASK.mdis rendered from the template with the task description; the onboarding prompt carries the full worker guide, decides which built-in jobs to enable, and ends with a walkthrough of everything it did plus next steps for the operator.task-plannerand quiet hours are off by default; onboarding enables the planner when the worker should plan through the approval loop.docs/setup.md,docs/api.md,docs/cron.md,docs/worker-guide.md,docs/plans.md,docs/config.md; several statements aligned with the code (skill-plan approval spawns an implementation session;plan_revisereturns to the proposing session;locksemantics; quiet hours).Deliberate deviations
nerve init --non-interactiveoutput for personal mode is byte-for-byte unchanged. For worker mode it now writes quiet hours off andtask-plannerdisabled (the goldens were regenerated for that reason).nerve init --terminalin worker mode has no cron step, so it writes the worker's optional jobs disabled; documented indocs/cron.mdanddocs/worker-guide.md.Testing
pytest: full suite green;vitest: green;npm run build; lint at the existing baseline.NERVE_AUTH_MODE=externaldriven by the actor header; installer checklist in a scratch HOME.Follow-ups (not in this PR)
nerve/tasks/escalation.py::check_escalationshas no caller, so quiet hours gate nothing at runtime; the docs now say what the setting does today.docs/cron.mddocuments atargetfield andsession_mode: mainthe code does not read.