[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
parent 6e93e12750
commit 223188a3c2

View file

@ -1,49 +1,128 @@
import type { AdapterConfigFieldsProps } from "../types";
import {
Field,
DraftInput,
} from "../../components/agent-config-primitives";
import { ChoosePathButton } from "../../components/PathInstructionsModal";
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";
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.";
export function HermesLocalConfigFields({
isCreate,
values,
set,
config,
eff,
mark,
hideInstructionsFile,
}: AdapterConfigFieldsProps) {
if (hideInstructionsFile) return null;
return (
<Field label="Agent instructions file" hint={instructionsFileHint}>
<div className="flex items-center gap-2">
<DraftInput
value={
isCreate
? values!.instructionsFilePath ?? ""
: eff(
"adapterConfig",
"instructionsFilePath",
String(config.instructionsFilePath ?? ""),
)
}
onCommit={(v) =>
isCreate
? set!({ instructionsFilePath: v })
: mark("adapterConfig", "instructionsFilePath", v || undefined)
}
immediate
className={inputClass}
placeholder="/absolute/path/to/AGENTS.md"
/>
<ChoosePathButton />
</div>
</Field>
);
}
import type { AdapterConfigFieldsProps } from "../types";
import {
Field,
DraftInput,
} from "../../components/agent-config-primitives";
import { ChoosePathButton } from "../../components/PathInstructionsModal";
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";
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.";
export function HermesLocalConfigFields({
isCreate,
values,
set,
config,
eff,
mark,
hideInstructionsFile,
}: AdapterConfigFieldsProps) {
return (
<>
{!hideInstructionsFile && (
<Field label="Agent instructions file" hint={instructionsFileHint}>
<div className="flex items-center gap-2">
<DraftInput
value={
isCreate
? values!.instructionsFilePath ?? ""
: eff(
"adapterConfig",
"instructionsFilePath",
String(config.instructionsFilePath ?? ""),
)
}
onCommit={(v) =>
isCreate
? set!({ instructionsFilePath: v })
: mark("adapterConfig", "instructionsFilePath", v || undefined)
}
immediate
className={inputClass}
placeholder="/absolute/path/to/AGENTS.md"
/>
<ChoosePathButton />
</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>
</>
)}
</>
);
}