agents: remove the hive-level /effort control too
mara on #5034: "effort shares /models fate". The per-agent web UI no longer sets effort: the `/effort` slash command, the effort picker, `POST /api/effort`, `Bus::set_effort`, the `hyperhive-effort` writer, `EFFORT_LEVELS`/`is_valid_effort` and the ACP effort-list payload are gone, and `lib/modelEffort.ts` with them. The effort chip is display-only and shows its source (`effort_source` in `/api/state`); on ACP it stays hidden while the session offers no effort level. The read side is unchanged: with no swarm value an agent runs an existing `hyperhive-effort` file, else its agent.nix effort, else medium. Existing files are not touched. Refs #5034
This commit is contained in:
parent
594693f4c7
commit
ed271e655f
25 changed files with 170 additions and 464 deletions
|
|
@ -1,7 +1,7 @@
|
|||
// <StatusChips> — the agent page's status row: the consolidated status
|
||||
// badge (alive/thinking/paused/etc., with pause/resume + cancel-turn in
|
||||
// its dropdown), the model (display-only: the swarm sets it), the effort
|
||||
// picker, and context/cost usage.
|
||||
// its dropdown), the model and effort (display-only: the swarm sets
|
||||
// them), and context/cost usage.
|
||||
// This is the concrete fix for the design guide's own named anti-example
|
||||
// (the old page's model/effort *pickers* lived in the `⋯` overflow menu
|
||||
// while the current model/effort only showed as a disconnected chip) —
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
import { useRef, useState } from "preact/hooks";
|
||||
import { Badge, type BadgeTone } from "@hive/shared/badge.js";
|
||||
import { Dropdown, type DropdownOption } from "@hive/shared/dropdown.js";
|
||||
import type { ModelSource } from "../types.js";
|
||||
import type { InferenceSource } from "../types.js";
|
||||
import "./StatusChips.css";
|
||||
|
||||
export interface StatusChipsProps {
|
||||
|
|
@ -28,10 +28,10 @@ export interface StatusChipsProps {
|
|||
* turn has completed. */
|
||||
resolvedModel?: string;
|
||||
/** Where `model` comes from (`/api/state` `model_source`). */
|
||||
modelSource?: ModelSource;
|
||||
effort: string;
|
||||
availableEfforts: string[];
|
||||
onSelectEffort: (level: string) => void;
|
||||
modelSource?: InferenceSource;
|
||||
/** Hidden when empty: an ACP session that offers no effort now. */
|
||||
effort?: string | null;
|
||||
effortSource?: InferenceSource;
|
||||
ctxLabel?: string;
|
||||
costLabel?: string;
|
||||
paused: boolean;
|
||||
|
|
@ -52,67 +52,12 @@ export interface StatusChipsProps {
|
|||
onLogout: () => Promise<void>;
|
||||
}
|
||||
|
||||
const SOURCE_LABEL: Record<ModelSource, string> = {
|
||||
const SOURCE_LABEL: Record<InferenceSource, string> = {
|
||||
swarm: "set on the swarm",
|
||||
agent_nix: "from agent.nix",
|
||||
local_file: "from its own earlier pick",
|
||||
default: "the built-in default",
|
||||
};
|
||||
const EFFORT_DESCRIPTIONS: Record<string, string> = {
|
||||
low: "",
|
||||
medium: "default",
|
||||
high: "",
|
||||
xhigh: "",
|
||||
max: "",
|
||||
};
|
||||
|
||||
function Picker({
|
||||
label,
|
||||
value,
|
||||
options,
|
||||
descriptions,
|
||||
onSelect,
|
||||
title,
|
||||
}: {
|
||||
label: string;
|
||||
value: string;
|
||||
options: string[];
|
||||
descriptions: Record<string, string>;
|
||||
onSelect: (v: string) => void;
|
||||
title?: string;
|
||||
}) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const anchorRef = useRef<HTMLDivElement>(null);
|
||||
const dropdownOptions: DropdownOption[] = options.map((name) => ({
|
||||
value: name,
|
||||
label: name,
|
||||
description: descriptions[name] || undefined,
|
||||
}));
|
||||
return (
|
||||
<div class="status-chip-anchor" ref={anchorRef}>
|
||||
<Badge
|
||||
label={label}
|
||||
value={value}
|
||||
onClick={() => setOpen((o) => !o)}
|
||||
expanded={open}
|
||||
title={title}
|
||||
/>
|
||||
<Dropdown
|
||||
open={open}
|
||||
options={dropdownOptions}
|
||||
activeValue={value}
|
||||
label={`select ${label}`}
|
||||
onSelect={(v) => {
|
||||
onSelect(v);
|
||||
setOpen(false);
|
||||
}}
|
||||
onClose={() => setOpen(false)}
|
||||
anchorRef={anchorRef}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// The consolidated alive/thinking/paused badge (mara: "why do we
|
||||
// have separate alive badge? ... it could be one badge that shows
|
||||
// thinking / idle / paused / ... with a dropdown that opens when
|
||||
|
|
@ -240,8 +185,7 @@ export function StatusChips({
|
|||
resolvedModel,
|
||||
modelSource,
|
||||
effort,
|
||||
availableEfforts,
|
||||
onSelectEffort,
|
||||
effortSource,
|
||||
ctxLabel,
|
||||
costLabel,
|
||||
paused,
|
||||
|
|
@ -277,13 +221,11 @@ export function StatusChips({
|
|||
.join(" · ") || undefined
|
||||
}
|
||||
/>
|
||||
{availableEfforts.length ? (
|
||||
<Picker
|
||||
{effort ? (
|
||||
<Badge
|
||||
label="effort"
|
||||
value={effort}
|
||||
options={availableEfforts}
|
||||
descriptions={EFFORT_DESCRIPTIONS}
|
||||
onSelect={onSelectEffort}
|
||||
title={effortSource ? SOURCE_LABEL[effortSource] : undefined}
|
||||
/>
|
||||
) : null}
|
||||
{ctxLabel ? (
|
||||
|
|
|
|||
Loading…
Reference in a new issue