feat(agents): custom context for Tier 2 + periodic system prompt re-injection

- SettingsTab: Custom Context textarea for Tier 2 project cards
- AgentSession passes systemPrompt for ALL projects (Tier 1 gets full
  generated prompt, Tier 2 gets custom context)
- Periodic re-injection: 1-hour timer checks if agent is idle, then
  auto-sends context refresh prompt with role/tools reminder
- AgentPane: autoPrompt prop consumed when session is done/error,
  resumes session with fresh system prompt
This commit is contained in:
DexterFromLab 2026-03-11 15:02:28 +01:00
parent 14808a97e9
commit 0c28f204c7
3 changed files with 79 additions and 9 deletions

View file

@ -58,10 +58,14 @@
agentSystemPrompt?: string;
/** Extra env vars injected into agent process (e.g. BTMSG_AGENT_ID) */
extraEnv?: Record<string, string>;
/** Auto-triggered prompt (e.g. periodic context refresh). Picked up when agent is idle. */
autoPrompt?: string;
/** Called when autoPrompt has been consumed */
onautopromptconsumed?: () => void;
onExit?: () => void;
}
let { sessionId, projectId, prompt: initialPrompt = '', cwd: initialCwd, profile: profileName, provider: providerId = 'claude', capabilities = DEFAULT_CAPABILITIES, useWorktrees = false, agentSystemPrompt, extraEnv, onExit }: Props = $props();
let { sessionId, projectId, prompt: initialPrompt = '', cwd: initialCwd, profile: profileName, provider: providerId = 'claude', capabilities = DEFAULT_CAPABILITIES, useWorktrees = false, agentSystemPrompt, extraEnv, autoPrompt, onautopromptconsumed, onExit }: Props = $props();
let session = $derived(getAgentSession(sessionId));
let inputPrompt = $state(initialPrompt);
@ -145,6 +149,16 @@
// NOTE: Do NOT stop agents in onDestroy — it fires on layout changes/remounts,
// not just explicit close. Stop-on-close is handled by workspace teardown.
// Auto-prompt: pick up externally triggered prompts (e.g. periodic context refresh)
$effect(() => {
if (!autoPrompt || isRunning) return;
// Only trigger if session exists and is idle (done/error)
if (!session || (session.status !== 'done' && session.status !== 'error')) return;
const prompt = autoPrompt;
onautopromptconsumed?.();
startQuery(prompt, true); // resume session with context refresh
});
let promptRef = $state<HTMLTextAreaElement | undefined>();
async function startQuery(text: string, resume = false) {