openclaw/src/config/types.agent-defaults.ts

362 lines
16 KiB
TypeScript
Raw Normal View History

import type { ChannelId } from "../channels/plugins/types.js";
import type { AgentModelConfig, AgentSandboxConfig } from "./types.agents-shared.js";
2026-01-14 01:08:15 +00:00
import type {
BlockStreamingChunkConfig,
BlockStreamingCoalesceConfig,
HumanDelayConfig,
TypingMode,
} from "./types.base.js";
import type { MemorySearchConfig } from "./types.tools.js";
export type AgentModelEntryConfig = {
alias?: string;
/** Provider-specific API parameters (e.g., GLM-4.7 thinking mode). */
params?: Record<string, unknown>;
/** Enable streaming for this model (default: true, false for Ollama to avoid SDK issue #1205). */
streaming?: boolean;
2026-01-14 01:08:15 +00:00
};
export type AgentModelListConfig = {
primary?: string;
fallbacks?: string[];
};
export type AgentContextPruningConfig = {
2026-01-21 19:44:20 +00:00
mode?: "off" | "cache-ttl";
/** TTL to consider cache expired (duration string, default unit: minutes). */
ttl?: string;
2026-01-14 01:08:15 +00:00
keepLastAssistants?: number;
softTrimRatio?: number;
hardClearRatio?: number;
minPrunableToolChars?: number;
tools?: {
allow?: string[];
deny?: string[];
};
softTrim?: {
maxChars?: number;
headChars?: number;
tailChars?: number;
};
hardClear?: {
enabled?: boolean;
placeholder?: string;
};
};
export type CliBackendConfig = {
/** CLI command to execute (absolute path or on PATH). */
command: string;
/** Base args applied to every invocation. */
args?: string[];
/** Output parsing mode (default: json). */
output?: "json" | "text" | "jsonl";
/** Output parsing mode when resuming a CLI session. */
resumeOutput?: "json" | "text" | "jsonl";
/** Prompt input mode (default: arg). */
input?: "arg" | "stdin";
/** Max prompt length for arg mode (if exceeded, stdin is used). */
maxPromptArgChars?: number;
/** Extra env vars injected for this CLI. */
env?: Record<string, string>;
/** Env vars to remove before launching this CLI. */
clearEnv?: string[];
/** Flag used to pass model id (e.g. --model). */
modelArg?: string;
/** Model aliases mapping (config model id → CLI model id). */
modelAliases?: Record<string, string>;
/** Flag used to pass session id (e.g. --session-id). */
sessionArg?: string;
/** Extra args used when resuming a session (use {sessionId} placeholder). */
sessionArgs?: string[];
/** Alternate args to use when resuming a session (use {sessionId} placeholder). */
resumeArgs?: string[];
/** When to pass session ids. */
sessionMode?: "always" | "existing" | "none";
/** JSON fields to read session id from (in order). */
sessionIdFields?: string[];
/** Flag used to pass system prompt. */
systemPromptArg?: string;
/** System prompt behavior (append vs replace). */
systemPromptMode?: "append" | "replace";
/** When to send system prompt. */
systemPromptWhen?: "first" | "always" | "never";
/** Flag used to pass image paths. */
imageArg?: string;
/** How to pass multiple images. */
imageMode?: "repeat" | "list";
/** Serialize runs for this CLI. */
serialize?: boolean;
/** Runtime reliability tuning for this backend's process lifecycle. */
reliability?: {
/** No-output watchdog tuning (fresh vs resumed runs). */
watchdog?: {
/** Fresh/new sessions (non-resume). */
fresh?: {
/** Fixed watchdog timeout in ms (overrides ratio when set). */
noOutputTimeoutMs?: number;
/** Fraction of overall timeout used when fixed timeout is not set. */
noOutputTimeoutRatio?: number;
/** Lower bound for computed watchdog timeout. */
minMs?: number;
/** Upper bound for computed watchdog timeout. */
maxMs?: number;
};
/** Resume sessions. */
resume?: {
/** Fixed watchdog timeout in ms (overrides ratio when set). */
noOutputTimeoutMs?: number;
/** Fraction of overall timeout used when fixed timeout is not set. */
noOutputTimeoutRatio?: number;
/** Lower bound for computed watchdog timeout. */
minMs?: number;
/** Upper bound for computed watchdog timeout. */
maxMs?: number;
};
};
};
2026-01-14 01:08:15 +00:00
};
export type AgentDefaultsConfig = {
/** Primary model and fallbacks (provider/model). Accepts string or {primary,fallbacks}. */
model?: AgentModelConfig;
/** Optional image-capable model and fallbacks (provider/model). Accepts string or {primary,fallbacks}. */
imageModel?: AgentModelConfig;
/** Optional image-generation model and fallbacks (provider/model). Accepts string or {primary,fallbacks}. */
imageGenerationModel?: AgentModelConfig;
feat: add PDF analysis tool with native provider support (#31319) * feat: add PDF analysis tool with native provider support New `pdf` tool for analyzing PDF documents with model-powered analysis. Architecture: - Native PDF path: sends raw PDF bytes directly to providers that support inline document input (Anthropic via DocumentBlockParam, Google Gemini via inlineData with application/pdf MIME type) - Extraction fallback: for providers without native PDF support, extracts text via pdfjs-dist and rasterizes pages to images via @napi-rs/canvas, then sends through the standard vision/text completion path Key features: - Single PDF (`pdf` param) or multiple PDFs (`pdfs` array, up to 10) - Page range selection (`pages` param, e.g. "1-5", "1,3,7-9") - Model override (`model` param) and file size limits (`maxBytesMb`) - Auto-detects provider capability and falls back gracefully - Same security patterns as image tool (SSRF guards, sandbox support, local path roots, workspace-only policy) Config (agents.defaults): - pdfModel: primary/fallbacks (defaults to imageModel, then session model) - pdfMaxBytesMb: max PDF file size (default: 10) - pdfMaxPages: max pages to process (default: 20) Model catalog: - Extended ModelInputType to include "document" alongside "text"/"image" - Added modelSupportsDocument() capability check Files: - src/agents/tools/pdf-tool.ts - main tool factory - src/agents/tools/pdf-tool.helpers.ts - helpers (page range, config, etc.) - src/agents/tools/pdf-native-providers.ts - direct API calls for Anthropic/Google - src/agents/tools/pdf-tool.test.ts - 43 tests covering all paths - Modified: model-catalog.ts, openclaw-tools.ts, config schema/types/labels/help * fix: prepare pdf tool for merge (#31319) (thanks @tyler6204)
2026-03-01 22:39:12 -08:00
/** Optional PDF-capable model and fallbacks (provider/model). Accepts string or {primary,fallbacks}. */
pdfModel?: AgentModelConfig;
/** Maximum PDF file size in megabytes (default: 10). */
pdfMaxBytesMb?: number;
/** Maximum number of PDF pages to process (default: 20). */
pdfMaxPages?: number;
2026-01-14 01:08:15 +00:00
/** Model catalog with optional aliases (full provider/model keys). */
models?: Record<string, AgentModelEntryConfig>;
/** Agent working directory (preferred). Used as the default cwd for agent runs. */
workspace?: string;
/** Optional repository root for system prompt runtime line (overrides auto-detect). */
repoRoot?: string;
2026-01-14 01:08:15 +00:00
/** Skip bootstrap (BOOTSTRAP.md creation, etc.) for pre-configured deployments. */
skipBootstrap?: boolean;
/** Max chars for injected bootstrap files before truncation (default: 20000). */
bootstrapMaxChars?: number;
/** Max total chars across all injected bootstrap files (default: 150000). */
bootstrapTotalMaxChars?: number;
/**
* Agent-visible bootstrap truncation warning mode:
* - off: do not inject warning text
* - once: inject once per unique truncation signature (default)
* - always: inject on every run with truncation
*/
bootstrapPromptTruncationWarning?: "off" | "once" | "always";
2026-01-14 01:08:15 +00:00
/** Optional IANA timezone for the user (used in system prompt; defaults to host timezone). */
userTimezone?: string;
/** Time format in system prompt: auto (OS preference), 12-hour, or 24-hour. */
timeFormat?: "auto" | "12" | "24";
/**
* Envelope timestamp timezone: "utc" (default), "local", "user", or an IANA timezone string.
*/
envelopeTimezone?: string;
/**
* Include absolute timestamps in message envelopes ("on" | "off", default: "on").
*/
envelopeTimestamp?: "on" | "off";
/**
* Include elapsed time in message envelopes ("on" | "off", default: "on").
*/
envelopeElapsed?: "on" | "off";
/** Optional context window cap (used for runtime estimates + status %). */
2026-01-14 01:08:15 +00:00
contextTokens?: number;
/** Optional CLI backends for text-only fallback (claude-cli, etc.). */
cliBackends?: Record<string, CliBackendConfig>;
/** Opt-in: prune old tool results from the LLM context to reduce token usage. */
contextPruning?: AgentContextPruningConfig;
/** Compaction tuning and pre-compaction memory flush behavior. */
compaction?: AgentCompactionConfig;
/** Embedded Pi runner hardening and compatibility controls. */
embeddedPi?: {
/**
* How embedded Pi should trust workspace-local `.pi/config/settings.json`.
* - sanitize (default): apply project settings except shellPath/shellCommandPrefix
* - ignore: ignore project settings entirely
* - trusted: trust project settings as-is
*/
projectSettingsPolicy?: "trusted" | "sanitize" | "ignore";
};
2026-01-14 01:08:15 +00:00
/** Vector memory search configuration (per-agent overrides supported). */
memorySearch?: MemorySearchConfig;
/** Default thinking level when no /think directive is present. */
thinkingDefault?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "adaptive";
2026-01-14 01:08:15 +00:00
/** Default verbose level when no /verbose directive is present. */
2026-01-17 05:33:27 +00:00
verboseDefault?: "off" | "on" | "full";
2026-01-14 01:08:15 +00:00
/** Default elevated level when no /elevated directive is present. */
2026-01-22 05:32:13 +00:00
elevatedDefault?: "off" | "on" | "ask" | "full";
2026-01-14 01:08:15 +00:00
/** Default block streaming level when no override is present. */
blockStreamingDefault?: "off" | "on";
/**
* Block streaming boundary:
* - "text_end": end of each assistant text content block (before tool calls)
* - "message_end": end of the whole assistant message (may include tool blocks)
*/
blockStreamingBreak?: "text_end" | "message_end";
/** Soft block chunking for streamed replies (min/max chars, prefer paragraph/newline). */
blockStreamingChunk?: BlockStreamingChunkConfig;
/**
* Block reply coalescing (merge streamed chunks before send).
* idleMs: wait time before flushing when idle.
*/
blockStreamingCoalesce?: BlockStreamingCoalesceConfig;
/** Human-like delay between block replies. */
humanDelay?: HumanDelayConfig;
timeoutSeconds?: number;
/** Max inbound media size in MB for agent-visible attachments (text note or future image attach). */
mediaMaxMb?: number;
/**
* Max image side length (pixels) when sanitizing base64 image payloads in transcripts/tool results.
* Default: 1200.
*/
imageMaxDimensionPx?: number;
2026-01-14 01:08:15 +00:00
typingIntervalSeconds?: number;
/** Typing indicator start mode (never|instant|thinking|message). */
typingMode?: TypingMode;
/** Periodic background heartbeat runs. */
heartbeat?: {
/** Heartbeat interval (duration string, default unit: minutes; default: 30m). */
every?: string;
2026-01-21 20:30:29 +00:00
/** Optional active-hours window (local time); heartbeats run only inside this window. */
activeHours?: {
/** Start time (24h, HH:MM). Inclusive. */
start?: string;
/** End time (24h, HH:MM). Exclusive. Use "24:00" for end-of-day. */
end?: string;
/** Timezone for the window ("user", "local", or IANA TZ id). Default: "user". */
timezone?: string;
};
2026-01-14 01:08:15 +00:00
/** Heartbeat model override (provider/model). */
model?: string;
2026-01-19 15:42:07 -05:00
/** Session key for heartbeat runs ("main" or explicit session key). */
session?: string;
2026-01-24 13:17:02 +00:00
/** Delivery target ("last", "none", or a channel id). */
target?: "last" | "none" | ChannelId;
/** Direct/DM delivery policy. Default: "allow". */
directPolicy?: "allow" | "block";
/** Optional delivery override (E.164 for WhatsApp, chat id for Telegram). Supports :topic:NNN suffix for Telegram topics. */
2026-01-14 01:08:15 +00:00
to?: string;
/** Optional account id for multi-account channels. */
accountId?: string;
/** Override the heartbeat prompt body (default: "Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK."). */
2026-01-14 01:08:15 +00:00
prompt?: string;
/** Max chars allowed after HEARTBEAT_OK before delivery (default: 30). */
ackMaxChars?: number;
/** Suppress tool error warning payloads during heartbeat runs. */
suppressToolErrorWarnings?: boolean;
/**
* If true, run heartbeat turns with lightweight bootstrap context.
* Lightweight mode keeps only HEARTBEAT.md from workspace bootstrap files.
*/
lightContext?: boolean;
/**
* If true, run heartbeat turns in an isolated session with no prior
* conversation history. The heartbeat only sees its bootstrap context
* (HEARTBEAT.md when lightContext is also enabled). Dramatically reduces
* per-heartbeat token cost by avoiding the full session transcript.
*/
isolatedSession?: boolean;
2026-01-14 01:08:15 +00:00
/**
* When enabled, deliver the model's reasoning payload for heartbeat runs (when available)
* as a separate message prefixed with `Reasoning:` (same as `/reasoning on`).
*
* Default: false (only the final heartbeat payload is delivered).
*/
includeReasoning?: boolean;
};
/** Max concurrent agent runs across all conversations. Default: 1 (sequential). */
maxConcurrent?: number;
/** Sub-agent defaults (spawned via sessions_spawn). */
subagents?: {
/** Max concurrent sub-agent runs (global lane: "subagent"). Default: 1. */
maxConcurrent?: number;
/** Maximum depth allowed for sessions_spawn chains. Default behavior: 1 (no nested spawns). */
Agents: add nested subagent orchestration controls and reduce subagent token waste (#14447) * Agents: add subagent orchestration controls * Agents: add subagent orchestration controls (WIP uncommitted changes) * feat(subagents): add depth-based spawn gating for sub-sub-agents * feat(subagents): tool policy, registry, and announce chain for nested agents * feat(subagents): system prompt, docs, changelog for nested sub-agents * fix(subagents): prevent model fallback override, show model during active runs, and block context overflow fallback Bug 1: When a session has an explicit model override (e.g., gpt/openai-codex), the fallback candidate logic in resolveFallbackCandidates silently appended the global primary model (opus) as a backstop. On reinjection/steer with a transient error, the session could fall back to opus which has a smaller context window and crash. Fix: when storedModelOverride is set, pass fallbacksOverride ?? [] instead of undefined, preventing the implicit primary backstop. Bug 2: Active subagents showed 'model n/a' in /subagents list because resolveModelDisplay only read entry.model/modelProvider (populated after run completes). Fix: fall back to modelOverride/providerOverride fields which are populated at spawn time via sessions.patch. Bug 3: Context overflow errors (prompt too long, context_length_exceeded) could theoretically escape runEmbeddedPiAgent and be treated as failover candidates in runWithModelFallback, causing a switch to a model with a smaller context window. Fix: in runWithModelFallback, detect context overflow errors via isLikelyContextOverflowError and rethrow them immediately instead of trying the next model candidate. * fix(subagents): track spawn depth in session store and fix announce routing for nested agents * Fix compaction status tracking and dedupe overflow compaction triggers * fix(subagents): enforce depth block via session store and implement cascade kill * fix: inject group chat context into system prompt * fix(subagents): always write model to session store at spawn time * Preserve spawnDepth when agent handler rewrites session entry * fix(subagents): suppress announce on steer-restart * fix(subagents): fallback spawned session model to runtime default * fix(subagents): enforce spawn depth when caller key resolves by sessionId * feat(subagents): implement active-first ordering for numeric targets and enhance task display - Added a test to verify that subagents with numeric targets follow an active-first list ordering. - Updated `resolveSubagentTarget` to sort subagent runs based on active status and recent activity. - Enhanced task display in command responses to prevent truncation of long task descriptions. - Introduced new utility functions for compacting task text and managing subagent run states. * fix(subagents): show model for active runs via run record fallback When the spawned model matches the agent's default model, the session store's override fields are intentionally cleared (isDefault: true). The model/modelProvider fields are only populated after the run completes. This left active subagents showing 'model n/a'. Fix: store the resolved model on SubagentRunRecord at registration time, and use it as a fallback in both display paths (subagents tool and /subagents command) when the session store entry has no model info. Changes: - SubagentRunRecord: add optional model field - registerSubagentRun: accept and persist model param - sessions-spawn-tool: pass resolvedModel to registerSubagentRun - subagents-tool: pass run record model as fallback to resolveModelDisplay - commands-subagents: pass run record model as fallback to resolveModelDisplay * feat(chat): implement session key resolution and reset on sidebar navigation - Added functions to resolve the main session key and reset chat state when switching sessions from the sidebar. - Updated the `renderTab` function to handle session key changes when navigating to the chat tab. - Introduced a test to verify that the session resets to "main" when opening chat from the sidebar navigation. * fix: subagent timeout=0 passthrough and fallback prompt duplication Bug 1: runTimeoutSeconds=0 now means 'no timeout' instead of applying 600s default - sessions-spawn-tool: default to undefined (not 0) when neither timeout param is provided; use != null check so explicit 0 passes through to gateway - agent.ts: accept 0 as valid timeout (resolveAgentTimeoutMs already handles 0 → MAX_SAFE_TIMEOUT_MS) Bug 2: model fallback no longer re-injects the original prompt as a duplicate - agent.ts: track fallback attempt index; on retries use a short continuation message instead of the full original prompt since the session file already contains it from the first attempt - Also skip re-sending images on fallback retries (already in session) * feat(subagents): truncate long task descriptions in subagents command output - Introduced a new utility function to format task previews, limiting their length to improve readability. - Updated the command handler to use the new formatting function, ensuring task descriptions are truncated appropriately. - Adjusted related tests to verify that long task descriptions are now truncated in the output. * refactor(subagents): update subagent registry path resolution and improve command output formatting - Replaced direct import of STATE_DIR with a utility function to resolve the state directory dynamically. - Enhanced the formatting of command output for active and recent subagents, adding separators for better readability. - Updated related tests to reflect changes in command output structure. * fix(subagent): default sessions_spawn to no timeout when runTimeoutSeconds omitted The previous fix (75a791106) correctly handled the case where runTimeoutSeconds was explicitly set to 0 ("no timeout"). However, when models omit the parameter entirely (which is common since the schema marks it as optional), runTimeoutSeconds resolved to undefined. undefined flowed through the chain as: sessions_spawn → timeout: undefined (since undefined != null is false) → gateway agent handler → agentCommand opts.timeout: undefined → resolveAgentTimeoutMs({ overrideSeconds: undefined }) → DEFAULT_AGENT_TIMEOUT_SECONDS (600s = 10 minutes) This caused subagents to be killed at exactly 10 minutes even though the user's intent (via TOOLS.md) was for subagents to run without a timeout. Fix: default runTimeoutSeconds to 0 (no timeout) when neither runTimeoutSeconds nor timeoutSeconds is provided by the caller. Subagent spawns are long-running by design and should not inherit the 600s agent-command default timeout. * fix(subagent): accept timeout=0 in agent-via-gateway path (second 600s default) * fix: thread timeout override through getReplyFromConfig dispatch path getReplyFromConfig called resolveAgentTimeoutMs({ cfg }) with no override, always falling back to the config default (600s). Add timeoutOverrideSeconds to GetReplyOptions and pass it through as overrideSeconds so callers of the dispatch chain can specify a custom timeout (0 = no timeout). This complements the existing timeout threading in agentCommand and the cron isolated-agent runner, which already pass overrideSeconds correctly. * feat(model-fallback): normalize OpenAI Codex model references and enhance fallback handling - Added normalization for OpenAI Codex model references, specifically converting "gpt-5.3-codex" to "openai-codex" before execution. - Updated the `resolveFallbackCandidates` function to utilize the new normalization logic. - Enhanced tests to verify the correct behavior of model normalization and fallback mechanisms. - Introduced a new test case to ensure that the normalization process works as expected for various input formats. * feat(tests): add unit tests for steer failure behavior in openclaw-tools - Introduced a new test file to validate the behavior of subagents when steer replacement dispatch fails. - Implemented tests to ensure that the announce behavior is restored correctly and that the suppression reason is cleared as expected. - Enhanced the subagent registry with a new function to clear steer restart suppression. - Updated related components to support the new test scenarios. * fix(subagents): replace stop command with kill in slash commands and documentation - Updated the `/subagents` command to replace `stop` with `kill` for consistency in controlling sub-agent runs. - Modified related documentation to reflect the change in command usage. - Removed legacy timeoutSeconds references from the sessions-spawn-tool schema and tests to streamline timeout handling. - Enhanced tests to ensure correct behavior of the updated commands and their interactions. * feat(tests): add unit tests for readLatestAssistantReply function - Introduced a new test file for the `readLatestAssistantReply` function to validate its behavior with various message scenarios. - Implemented tests to ensure the function correctly retrieves the latest assistant message and handles cases where the latest message has no text. - Mocked the gateway call to simulate different message histories for comprehensive testing. * feat(tests): enhance subagent kill-all cascade tests and announce formatting - Added a new test to verify that the `kill-all` command cascades through ended parents to active descendants in subagents. - Updated the subagent announce formatting tests to reflect changes in message structure, including the replacement of "Findings:" with "Result:" and the addition of new expectations for message content. - Improved the handling of long findings and stats in the announce formatting logic to ensure concise output. - Refactored related functions to enhance clarity and maintainability in the subagent registry and tools. * refactor(subagent): update announce formatting and remove unused constants - Modified the subagent announce formatting to replace "Findings:" with "Result:" and adjusted related expectations in tests. - Removed constants for maximum announce findings characters and summary words, simplifying the announcement logic. - Updated the handling of findings to retain full content instead of truncating, ensuring more informative outputs. - Cleaned up unused imports in the commands-subagents file to enhance code clarity. * feat(tests): enhance billing error handling in user-facing text - Added tests to ensure that normal text mentioning billing plans is not rewritten, preserving user context. - Updated the `isBillingErrorMessage` and `sanitizeUserFacingText` functions to improve handling of billing-related messages. - Introduced new test cases for various scenarios involving billing messages to ensure accurate processing and output. - Enhanced the subagent announce flow to correctly manage active descendant runs, preventing premature announcements. * feat(subagent): enhance workflow guidance and auto-announcement clarity - Added a new guideline in the subagent system prompt to emphasize trust in push-based completion, discouraging busy polling for status updates. - Updated documentation to clarify that sub-agents will automatically announce their results, improving user understanding of the workflow. - Enhanced tests to verify the new guidance on avoiding polling loops and to ensure the accuracy of the updated prompts. * fix(cron): avoid announcing interim subagent spawn acks * chore: clean post-rebase imports * fix(cron): fall back to child replies when parent stays interim * fix(subagents): make active-run guidance advisory * fix(subagents): update announce flow to handle active descendants and enhance test coverage - Modified the announce flow to defer announcements when active descendant runs are present, ensuring accurate status reporting. - Updated tests to verify the new behavior, including scenarios where no fallback requester is available and ensuring proper handling of finished subagents. - Enhanced the announce formatting to include an `expectFinal` flag for better clarity in the announcement process. * fix(subagents): enhance announce flow and formatting for user updates - Updated the announce flow to provide clearer instructions for user updates based on active subagent runs and requester context. - Refactored the announcement logic to improve clarity and ensure internal context remains private. - Enhanced tests to verify the new message expectations and formatting, including updated prompts for user-facing updates. - Introduced a new function to build reply instructions based on session context, improving the overall announcement process. * fix: resolve prep blockers and changelog placement (#14447) (thanks @tyler6204) * fix: restore cron delivery-plan import after rebase (#14447) (thanks @tyler6204) * fix: resolve test failures from rebase conflicts (#14447) (thanks @tyler6204) * fix: apply formatting after rebase (#14447) (thanks @tyler6204)
2026-02-14 22:03:45 -08:00
maxSpawnDepth?: number;
/** Maximum active children a single requester session may spawn. Default behavior: 5. */
maxChildrenPerAgent?: number;
Session management improvements and dashboard API (#50101) * fix: make cleanup "keep" persist subagent sessions indefinitely * feat: expose subagent session metadata in sessions list * fix: include status and timing in sessions_list tool * fix: hide injected timestamp prefixes in chat ui * feat: push session list updates over websocket * feat: expose child subagent sessions in subagents list * feat: add admin http endpoint to kill sessions * Emit session.message websocket events for transcript updates * Estimate session costs in sessions list * Add direct session history HTTP and SSE endpoints * Harden dashboard session events and history APIs * Add session lifecycle gateway methods * Add dashboard session API improvements * Add dashboard session model and parent linkage support * fix: tighten dashboard session API metadata * Fix dashboard session cost metadata * Persist accumulated session cost * fix: stop followup queue drain cfg crash * Fix dashboard session create and model metadata * fix: stop guessing session model costs * Gateway: cache OpenRouter pricing for configured models * Gateway: add timeout session status * Fix subagent spawn test config loading * Gateway: preserve operator scopes without device identity * Emit user message transcript events and deduplicate plugin warnings * feat: emit sessions.changed lifecycle event on subagent spawn Adds a session-lifecycle-events module (similar to transcript-events) that emits create events when subagents are spawned. The gateway server.impl.ts listens for these events and broadcasts sessions.changed with reason=create to SSE subscribers, so dashboards can pick up new subagent sessions without polling. * Gateway: allow persistent dashboard orchestrator sessions * fix: preserve operator scopes for token-authenticated backend clients Backend clients (like agent-dashboard) that authenticate with a valid gateway token but don't present a device identity were getting their scopes stripped. The scope-clearing logic ran before checking the device identity decision, so even when evaluateMissingDeviceIdentity returned 'allow' (because roleCanSkipDeviceIdentity passed for token-authed operators), scopes were already cleared. Fix: also check decision.kind before clearing scopes, so token-authenticated operators keep their requested scopes. * Gateway: allow operator-token session kills * Fix stale active subagent status after follow-up runs * Fix dashboard image attachments in sessions send * Fix completed session follow-up status updates * feat: stream session tool events to operator UIs * Add sessions.steer gateway coverage * Persist subagent timing in session store * Fix subagent session transcript event keys * Fix active subagent session status in gateway * bump session label max to 512 * Fix gateway send session reactivation * fix: publish terminal session lifecycle state * feat: change default session reset to effectively never - Change DEFAULT_RESET_MODE from "daily" to "idle" - Change DEFAULT_IDLE_MINUTES from 60 to 0 (0 = disabled/never) - Allow idleMinutes=0 through normalization (don't clamp to 1) - Treat idleMinutes=0 as "no idle expiry" in evaluateSessionFreshness - Default behavior: mode "idle" + idleMinutes 0 = sessions never auto-reset - Update test assertion for new default mode * fix: prep session management followups (#50101) (thanks @clay-datacurve) --------- Co-authored-by: Tyler Yust <TYTYYUST@YAHOO.COM>
2026-03-18 20:12:30 -07:00
/** Auto-archive sub-agent sessions after N minutes (default: 60, set 0 to disable). */
2026-01-14 01:08:15 +00:00
archiveAfterMinutes?: number;
/** Default model selection for spawned sub-agents (string or {primary,fallbacks}). */
model?: AgentModelConfig;
/** Default thinking level for spawned sub-agents (e.g. "off", "low", "medium", "high"). */
thinking?: string;
/** Default run timeout in seconds for spawned sub-agents (0 = no timeout). */
runTimeoutSeconds?: number;
/** Gateway timeout in ms for sub-agent announce delivery calls (default: 90000). */
announceTimeoutMs?: number;
2026-01-14 01:08:15 +00:00
};
/** Optional sandbox settings for non-main sessions. */
sandbox?: AgentSandboxConfig;
2026-01-14 01:08:15 +00:00
};
export type AgentCompactionMode = "default" | "safeguard";
export type AgentCompactionPostIndexSyncMode = "off" | "async" | "await";
export type AgentCompactionIdentifierPolicy = "strict" | "off" | "custom";
export type AgentCompactionQualityGuardConfig = {
/** Enable compaction summary quality audits and regeneration retries. Default: false. */
enabled?: boolean;
/** Maximum regeneration retries after a failed quality audit. Default: 1 when enabled. */
maxRetries?: number;
};
2026-01-14 01:08:15 +00:00
export type AgentCompactionConfig = {
/** Compaction summarization mode. */
mode?: AgentCompactionMode;
/** Pi reserve tokens target before floor enforcement. */
reserveTokens?: number;
/** Pi keepRecentTokens budget used for cut-point selection. */
keepRecentTokens?: number;
2026-01-14 01:08:15 +00:00
/** Minimum reserve tokens enforced for Pi compaction (0 disables the floor). */
reserveTokensFloor?: number;
/** Max share of context window for history during safeguard pruning (0.10.9, default 0.5). */
maxHistoryShare?: number;
/** Additional compaction-summary instructions that can preserve language or persona continuity. */
customInstructions?: string;
/** Preserve this many most-recent user/assistant turns verbatim in compaction summary context. */
recentTurnsPreserve?: number;
/** Identifier-preservation instruction policy for compaction summaries. */
identifierPolicy?: AgentCompactionIdentifierPolicy;
/** Custom identifier-preservation instructions used when identifierPolicy is "custom". */
identifierInstructions?: string;
/** Optional quality-audit retries for safeguard compaction summaries. */
qualityGuard?: AgentCompactionQualityGuardConfig;
/** Post-compaction session memory index sync mode. */
postIndexSync?: AgentCompactionPostIndexSyncMode;
2026-01-14 01:08:15 +00:00
/** Pre-compaction memory flush (agentic turn). Default: enabled. */
memoryFlush?: AgentCompactionMemoryFlushConfig;
/**
* H2/H3 section names from AGENTS.md to inject after compaction.
* Defaults to ["Session Startup", "Red Lines"] when unset.
* Set to [] to disable post-compaction context injection entirely.
*/
postCompactionSections?: string[];
/** Optional model override for compaction summarization (e.g. "openrouter/anthropic/claude-sonnet-4-5").
* When set, compaction uses this model instead of the agent's primary model.
* Falls back to the primary model when unset. */
model?: string;
feat: make compaction timeout configurable via agents.defaults.compaction.timeoutSeconds (#46889) * feat: make compaction timeout configurable via agents.defaults.compaction.timeoutSeconds The hardcoded 5-minute (300s) compaction timeout causes large sessions to enter a death spiral where compaction repeatedly fails and the session grows indefinitely. This adds agents.defaults.compaction.timeoutSeconds to allow operators to override the compaction safety timeout. Default raised to 900s (15min) which is sufficient for sessions up to ~400k tokens. The resolved timeout is also used for the session write lock duration so locks don't expire before compaction completes. Fixes #38233 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * test: add resolveCompactionTimeoutMs tests Cover config resolution edge cases: undefined config, missing compaction section, valid seconds, fractional values, zero, negative, NaN, and Infinity. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: add timeoutSeconds to compaction Zod schema The compaction object schema uses .strict(), so setting the new timeoutSeconds config option would fail validation at startup. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: enforce integer constraint on compaction timeoutSeconds schema Prevents sub-second values like 0.5 which would floor to 0ms and cause immediate compaction timeout. Matches pattern of other integer timeout fields in the schema. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: clamp compaction timeout to Node timer-safe maximum Values above ~2.1B ms overflow Node's setTimeout to 1ms, causing immediate timeout. Clamp to MAX_SAFE_TIMEOUT_MS matching the pattern in agents/timeout.ts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: add FIELD_LABELS entry for compaction timeoutSeconds Maintains label/help parity invariant enforced by schema.help.quality.test.ts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: align compaction timeouts with abort handling * fix: land compaction timeout handling (#46889) (thanks @asyncjason) --------- Co-authored-by: Jason Separovic <jason@wilma.dog> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-03-14 23:34:48 -07:00
/** Maximum time in seconds for a single compaction operation (default: 900). */
timeoutSeconds?: number;
2026-01-14 01:08:15 +00:00
};
export type AgentCompactionMemoryFlushConfig = {
/** Enable the pre-compaction memory flush (default: true). */
enabled?: boolean;
/** Run the memory flush when context is within this many tokens of the compaction threshold. */
softThresholdTokens?: number;
/**
* Force a memory flush when transcript size reaches this threshold
* (bytes, or byte-size string like "2mb"). Set to 0 to disable.
*/
forceFlushTranscriptBytes?: number | string;
2026-01-14 01:08:15 +00:00
/** User prompt used for the memory flush turn (NO_REPLY is enforced if missing). */
prompt?: string;
/** System prompt appended for the memory flush turn. */
systemPrompt?: string;
};