Commit Graph

4 Commits

Author SHA1 Message Date
Teknium 2ffed55c32 feat: server-side ui_meta on profiles.list/configure (#85440)
* feat: server-side ui_meta on profiles.list/configure

Roster UIs built on profiles.* have per-profile presentation state
(avatar, accent color, display title, pet) with nowhere server-side to
live — client plugin storage paints a different roster on every
machine. profiles.configure now accepts ui_meta (merged key-wise into
profile.yaml's ui_meta block via the existing atomic_yaml_write path,
null deletes a key, 64KB cap since it rides every roster paint) and
profiles.list returns the block per row. Consumers namespace under
their own key. No new files or config; profiles without the block are
unchanged.

* test: stop primary-runtime-restore tests probing live endpoints

_make_agent left the compressor's lazy context-length resolution
unmocked; for reachable base_urls (the nous portal test) the endpoint's
32K answer for the empty test model trips agent_init's 64K floor and
fails the suite on network behavior. Pin get_model_context_length in
the fixture.
2026-08-13 10:07:39 -07:00
Teknium f795812c16 feat: profiles.describe/profiles.configure ws RPC for profile editors (#85216)
profiles.list/create (#85093) let plugins enumerate and create profiles
but not read or modify an existing profile's configuration over ws.
profiles.describe returns the full editor snapshot (description, SOUL.md,
model pin, per-skill enablement via the disabled-list model, per-toolset
enablement via the tools.enabled_toolsets pin); profiles.configure
applies any subset (description via write_profile_meta, soul, model via
_write_profile_model, disabled_skills replace-semantics via
save_disabled_skills, enabled_toolsets replace-semantics with empty-list
clearing the pin) independently and best-effort, reporting per-section
results. Both scoped via the HERMES_HOME override and pool-dispatched.
2026-08-13 03:12:10 -07:00
Teknium 9460cc11d4 fix: profiles.create mirrors launch credentials so new profiles can run (#85111)
A profile created through the headless ws door (profiles.create, #85093)
was born with no inference provider: create_profile() seeds a comment-only
.env, never copies auth.json, and a fresh profile has no config.yaml. Its
first message failed with 'No inference provider configured' and the flow
has no interactive setup step to recover with.

New mirror_credentials param (default true): copy the launch profile's
.env (only over the seeded stub — never clobber cloned secrets) and
auth.json (only when absent), both chmod 600, and inherit
model.provider/model.default when the caller gave no explicit pin and no
config was cloned. mirror_credentials:false preserves the old isolated
behavior byte-for-byte. Result gains a mirrored:{env,auth,model_inherited}
receipt. CLI and REST create paths untouched.
2026-08-13 00:25:04 -07:00
Teknium 89a84e1ae6 feat: profiles.list/profiles.create ws RPC + plugin session-navigation doors (#85093)
Desktop plugins reach the backend exclusively through the generic ws
JSON-RPC door (host.request), but profile enumeration/creation only
existed on the dashboard REST router, which plugins cannot reach — so
anything 'one chat per agent profile'-shaped (bot rosters, profile
pickers, team panes) was impossible to build as a plugin.

- tui_gateway/methods_profiles.py: new @method handlers
  * profiles.list — profiles + optional last_session preview per profile
    (mirrors session.list's kanban/tool deny-list; best-effort per-profile
    state.db probe degrades to null instead of failing the call)
  * profiles.create — ws twin of POST /api/profiles (clone_from/clone_all/
    no_skills/description), plus optional SOUL.md content and a best-effort
    model+provider pin; mirrors the CLI flow (seed skills, safe alias)
  Both run on the RPC pool, not the WS reader thread (list_profiles walks
  skill trees; create copies bundles).
- SDK: host.openSession(id, { profile, intent }) — open a stored session
  the way core surfaces do, soft-swapping to the owning profile's backend
  first (ensureGatewayProfile), and host.newChat(profile) — fresh draft in
  a named profile (same door as the sidebar's per-profile '+').
- Docs: desktop-plugin-sdk.md gains both surfaces.

First consumer: a Grok Bot-style 'Bots' roster plugin (one persistent
chat per agent profile with a New Agent dialog) built on exactly these
four doors.
2026-08-12 23:33:58 -07:00