[nexus] feat(20-01): expand HermesLocalConfigFields with model, toolsets, persistSession, timeoutSec

- Add Model field (both create + edit modes) using CreateConfigValues.model
- Add Toolsets field (both create + edit modes) using extraArgs in create, adapterConfig.toolsets in edit
- Add Persist Session checkbox (edit mode only) wired to adapterConfig.persistSession
- Add Timeout (seconds) field (edit mode only) wired to adapterConfig.timeoutSec
- Restructure component to use fragment with conditional hideInstructionsFile guard
- TypeScript compiles cleanly
This commit is contained in:
Mikkel Georgsen 2026-04-01 12:00:30 +02:00 committed by Nexus Dev
parent ab2e1d1ce3
commit cef656264e

View file

@ -1,49 +1,128 @@
import type { AdapterConfigFieldsProps } from "../types"; import type { AdapterConfigFieldsProps } from "../types";
import { import {
Field, Field,
DraftInput, DraftInput,
} from "../../components/agent-config-primitives"; } from "../../components/agent-config-primitives";
import { ChoosePathButton } from "../../components/PathInstructionsModal"; import { ChoosePathButton } from "../../components/PathInstructionsModal";
const inputClass = const inputClass =
"w-full rounded-md border border-border px-2.5 py-1.5 bg-transparent outline-none text-sm font-mono placeholder:text-muted-foreground/40"; "w-full rounded-md border border-border px-2.5 py-1.5 bg-transparent outline-none text-sm font-mono placeholder:text-muted-foreground/40";
const instructionsFileHint = const instructionsFileHint =
"Absolute path to a markdown file (e.g. AGENTS.md) that defines this agent's behavior. Injected into the system prompt at runtime."; "Absolute path to a markdown file (e.g. AGENTS.md) that defines this agent's behavior. Injected into the system prompt at runtime.";
export function HermesLocalConfigFields({ export function HermesLocalConfigFields({
isCreate, isCreate,
values, values,
set, set,
config, config,
eff, eff,
mark, mark,
hideInstructionsFile, hideInstructionsFile,
}: AdapterConfigFieldsProps) { }: AdapterConfigFieldsProps) {
if (hideInstructionsFile) return null; return (
return ( <>
<Field label="Agent instructions file" hint={instructionsFileHint}> {!hideInstructionsFile && (
<div className="flex items-center gap-2"> <Field label="Agent instructions file" hint={instructionsFileHint}>
<DraftInput <div className="flex items-center gap-2">
value={ <DraftInput
isCreate value={
? values!.instructionsFilePath ?? "" isCreate
: eff( ? values!.instructionsFilePath ?? ""
"adapterConfig", : eff(
"instructionsFilePath", "adapterConfig",
String(config.instructionsFilePath ?? ""), "instructionsFilePath",
) String(config.instructionsFilePath ?? ""),
} )
onCommit={(v) => }
isCreate onCommit={(v) =>
? set!({ instructionsFilePath: v }) isCreate
: mark("adapterConfig", "instructionsFilePath", v || undefined) ? set!({ instructionsFilePath: v })
} : mark("adapterConfig", "instructionsFilePath", v || undefined)
immediate }
className={inputClass} immediate
placeholder="/absolute/path/to/AGENTS.md" className={inputClass}
/> placeholder="/absolute/path/to/AGENTS.md"
<ChoosePathButton /> />
</div> <ChoosePathButton />
</Field> </div>
); </Field>
} )}
<Field
label="Model"
hint="Provider/model format (e.g. anthropic/claude-sonnet-4). Leave blank to use Hermes default."
>
<DraftInput
value={
isCreate
? values!.model ?? ""
: eff("adapterConfig", "model", String(config.model ?? ""))
}
onCommit={(v) =>
isCreate
? set!({ model: v })
: mark("adapterConfig", "model", v || undefined)
}
immediate
className={inputClass}
placeholder="anthropic/claude-sonnet-4"
/>
</Field>
<Field
label="Toolsets"
hint="Comma-separated toolset names (e.g. terminal,file,web). Leave blank for defaults."
>
<DraftInput
value={
isCreate
? values!.extraArgs ?? ""
: eff("adapterConfig", "toolsets", String(config.toolsets ?? ""))
}
onCommit={(v) =>
isCreate
? set!({ extraArgs: v })
: mark("adapterConfig", "toolsets", v || undefined)
}
immediate
className={inputClass}
placeholder="terminal,file,web"
/>
</Field>
{!isCreate && (
<>
<Field
label="Persist session"
hint="Keep conversation history between heartbeat runs."
>
<label className="flex items-center gap-2 cursor-pointer">
<input
type="checkbox"
className="h-4 w-4 rounded border-border accent-primary"
checked={eff("adapterConfig", "persistSession", config.persistSession !== false)}
onChange={(e) =>
mark("adapterConfig", "persistSession", e.target.checked)
}
/>
<span className="text-sm text-muted-foreground">Enabled</span>
</label>
</Field>
<Field
label="Timeout (seconds)"
hint="Maximum execution time per heartbeat run."
>
<DraftInput
value={String(
eff("adapterConfig", "timeoutSec", Number(config.timeoutSec ?? 300)),
)}
onCommit={(v) =>
mark("adapterConfig", "timeoutSec", Number(v) || 300)
}
immediate
className={inputClass}
placeholder="300"
/>
</Field>
</>
)}
</>
);
}