export const SQLITE_BUSY_TIMEOUT_MS = 5_000; export const DEFAULT_QUERY_LIMIT = 1_000; export const MAX_QUERY_LIMIT = 10_000; export const SERVICE_MAX_BODY_BYTES = 1_048_576; export const SERVICE_MAX_RESPONSE_BYTES = 4_194_304; export const METRIC_IDENTITY_MAX_CHARACTERS = 160; export const METRIC_ATTRIBUTES_MAX_SERIALIZED_CHARACTERS = 16_384; export const METRIC_ATTRIBUTES_MAX_DEPTH = 12; export const BENCHMARK_IDENTITY_MAX_CHARACTERS = 160; export const BENCHMARK_MAX_TEXT_CHARACTERS = 2_048; export const BENCHMARK_MAX_MODELS_PER_SOURCE = 250; export const BENCHMARK_MAX_OBSERVATIONS_PER_SNAPSHOT = 2_000; export const BENCHMARK_STORE_QUERY_LIMIT = BENCHMARK_MAX_OBSERVATIONS_PER_SNAPSHOT * 2 + 1; export const BENCHMARK_DEFAULT_QUERY_LIMIT = 100; export const BENCHMARK_TUI_MAX_CANDIDATES = 20; export const BENCHMARK_TUI_MAX_PROVENANCE_PER_CANDIDATE = 2; export const BENCHMARK_MAX_QUERY_LIMIT = 500; export const BENCHMARK_SOURCE_MAX_RESPONSE_BYTES = 2_097_152; export const BENCHMARK_SOURCE_MAX_TOTAL_RESPONSE_BYTES = 6_291_456; export const BENCHMARK_REFRESH_INTERVAL_MS = 24 * 60 * 60 * 1_000; export const MODEL_CATALOG_MAX_RESPONSE_BYTES = 8_388_608; export const MODEL_CATALOG_MAX_ENTRIES = 8_000; export const MODEL_CATALOG_STORE_QUERY_LIMIT = MODEL_CATALOG_MAX_ENTRIES + 1; export const MODEL_CATALOG_DEFAULT_QUERY_LIMIT = 100; export const MODEL_CATALOG_MAX_QUERY_LIMIT = 500; export const MODEL_CATALOG_REQUEST_TIMEOUT_MS = 10_000; export const MODEL_CATALOG_FRESHNESS_MS = 24 * 60 * 60 * 1_000; export const PI_USAGE_IMPORT_MAX_FILES = 200; export const PI_USAGE_IMPORT_MAX_FILE_BYTES = 16_777_216; export const PI_USAGE_IMPORT_MAX_TOTAL_BYTES = 67_108_864; export const PI_USAGE_IMPORT_MAX_ENTRIES = 20_000; export const PI_USAGE_IMPORT_MAX_RECORDS = 5_000; export const PI_USAGE_IMPORT_MAX_DURATION_MS = 30_000; export const MODEL_OBSERVATION_IDENTITY_MAX_CHARACTERS = 160; export const MODEL_AGGREGATE_MAX_ROWS = 10_000; export const MODEL_AGGREGATE_MAX_GROUPS = 500; export const MODEL_RANKING_MAX_SOURCES = 4; export const MODEL_RANKING_DEFAULT_QUALITY_WEIGHT = 3; export const MODEL_RANKING_DEFAULT_COST_WEIGHT = 2; export const MODEL_RANKING_DEFAULT_LATENCY_WEIGHT = 1; export const MODEL_RANKING_DEFAULT_CONTEXT_WEIGHT = 1; export const MODEL_RANKING_DEFAULT_RELIABILITY_WEIGHT = 2; /** A low-effort turn tolerates a cheaper model, so its cost weight is amplified; a high-effort turn tolerates spending more for quality, so its cost weight is dampened. Medium is neutral (matches pre-effort-axis behavior exactly). */ export const MODEL_RANKING_EFFORT_COST_MULTIPLIER_LOW = 1.5; export const MODEL_RANKING_EFFORT_COST_MULTIPLIER_MEDIUM = 1; export const MODEL_RANKING_EFFORT_COST_MULTIPLIER_HIGH = 0.5; /** Cursor-style uplift gate: a recommendation requires the top candidate to clear a real utility margin over the current model, never just "ranked #1". */ export const MODEL_RANKING_UPLIFT_MIN_UTILITY_DELTA = 0.05; export const MODEL_RANKING_UPLIFT_MIN_CONFIDENCE = 0.5; export const MODEL_OBSERVATION_FRESH_MS = 7 * 24 * 60 * 60 * 1_000; export const EFFORT_DIMENSION_WEIGHT_TOKEN_COUNT = 0.1; export const EFFORT_DIMENSION_WEIGHT_CODE_PRESENCE = 0.2; export const EFFORT_DIMENSION_WEIGHT_REASONING_MARKERS = 0.2; export const EFFORT_DIMENSION_WEIGHT_TECHNICAL_TERMS = 0.15; export const EFFORT_DIMENSION_WEIGHT_SIMPLE_INDICATORS = 0.1; export const EFFORT_DIMENSION_WEIGHT_MULTI_STEP_PATTERNS = 0.05; export const EFFORT_DIMENSION_WEIGHT_QUESTION_COMPLEXITY = 0.05; export const EFFORT_DIMENSION_WEIGHT_TOOL_CALL_MIX = 0.15; /** Below this many estimated tokens, a short user message is itself simple-indicator evidence. */ export const EFFORT_TOKEN_SIMPLE_THRESHOLD = 15; /** Above this many estimated tokens, a long user message is itself complexity evidence. */ export const EFFORT_TOKEN_COMPLEX_THRESHOLD = 400; export const EFFORT_LOW_MEDIUM_BOUNDARY = 0.2; export const EFFORT_MEDIUM_HIGH_BOUNDARY = 0.45; /** 2+ reasoning-marker phrases in the user's own message force "high" regardless of the weighted score -- mirrors LiteLLM's complexity_router reasoning override. */ export const EFFORT_REASONING_MARKER_OVERRIDE_COUNT = 2; /** Prior-turn tool-call counts at or below this are simple-indicator evidence (e.g. a single read, or no tools at all). */ export const EFFORT_TOOL_CALL_LOW_THRESHOLD = 1; /** Prior-turn tool-call counts at or above this are complexity evidence (sustained multi-tool engineering work). */ export const EFFORT_TOOL_CALL_HIGH_THRESHOLD = 4; export const EFFORT_CLASSIFICATION_MAX_TEXT_CHARACTERS = 20_000; export const EFFORT_CLASSIFICATION_MAX_TOOL_NAMES = 200; export const MAINTENANCE_INTERVAL_MS = 15 * 60 * 1_000; export const TELEMETRY_POLL_INTERVAL_MS = 60_000; export const TELEMETRY_STALE_AFTER_MS = 120_000; export const OTLP_EXPORT_MAX_QUEUE_SIZE = 1_000; export const OTLP_EXPORT_BATCH_SIZE = 100; export const OTLP_EXPORT_INTERVAL_MS = 5_000; export const OTLP_EXPORT_TIMEOUT_MS = 3_000; export const OTLP_EXPORT_MAX_RETRIES = 1; export const FOOTER_CONTEXT_ACCENT_FRACTION = 0.5; export const FOOTER_CONTEXT_WARNING_FRACTION = 0.7; export const FOOTER_CONTEXT_ERROR_FRACTION = 0.9; export const FOOTER_BAR_MIN_WIDTH = 4; export const FOOTER_BAR_MAX_WIDTH = 8; export const FOOTER_WIDE_TERMINAL_WIDTH = 100; export const FOOTER_COMPACTION_RENDER_INTERVAL_MS = 500; /** Half-period of the compacting liveness indicator; equal to the render tick so it visibly alternates every repaint. */ export const FOOTER_COMPACTION_BLINK_HALF_PERIOD_MS = 500; export const MILLISECONDS_PER_SECOND = 1_000; export const MILLISECONDS_PER_MINUTE = 60 * MILLISECONDS_PER_SECOND; export const MILLISECONDS_PER_HOUR = 60 * MILLISECONDS_PER_MINUTE; export const PAPYRUS_CONTEXT_INJECTION_CHANNEL = "papyrus.context-injection.v1"; export const PAPYRUS_CONTEXT_INJECTION_SCHEMA = "papyrus.context-injection/v1"; /** Matches Papyrus's own constants by convention; Jittor does not depend on the Papyrus package. */ export const PAPYRUS_TASK_FOCUS_CHANNEL = "papyrus.task-focus.v1"; export const PAPYRUS_TASK_FOCUS_SCHEMA = "papyrus.task-focus/v1"; export const TASK_FOCUS_EVENT_MAX_AGE_MS = 5 * MILLISECONDS_PER_MINUTE; export const TASK_FOCUS_ID_MAX_LENGTH = 200; export const TASK_COST_QUERY_LIMIT = 10_000; export const CACHE_ECONOMICS_QUERY_LIMIT = 10_000; export const CACHE_ECONOMICS_MAX_MODEL_GROUPS = 500; /** Bounds the per-task rollup the same way CACHE_ECONOMICS_MAX_MODEL_GROUPS bounds the per-model one -- applied post-hoc (sorted by activity, then sliced) rather than at row-intake time, since realistic task cardinality in one window is small. */ export const CACHE_ECONOMICS_MAX_TASK_GROUPS = 500; /** Bounds the stable-prefix-churn time series; the most recent points are kept (oldest dropped first) since a trend view cares most about what's recent. */ export const CACHE_ECONOMICS_MAX_STABLE_PREFIX_POINTS = 500; export const CACHE_ECONOMICS_MAX_MISSED_OPPORTUNITIES = 100; /** How soon after a context-prefix reset (session/provider/model change) a same-session cache-write still counts as a candidate cache-loss consequence of that reset, not an unrelated later write. */ export const CACHE_ECONOMICS_LOSS_CORRELATION_WINDOW_MS = 5 * MILLISECONDS_PER_MINUTE; /** models.dev (and Jittor's catalog) quote pricing per one million tokens; catalog-estimate math divides by this to get a per-token rate. */ export const CATALOG_PRICE_TOKEN_UNIT = 1_000_000; /** models.dev's own long-context pricing convention: a request whose context exceeds this many tokens uses ModelCatalogPricing.contextOver200k instead of the flat/tiered rate. */ export const CATALOG_LONG_CONTEXT_THRESHOLD_TOKENS = 200_000; /** A `metrics prune --before` cutoff newer than this must pass `force: true`. Guards against accidentally wiping recent/live data with a too-recent cutoff (e.g. "now"), while still allowing routine cleanup of genuinely old rows without ceremony. */ export const PRUNE_MIN_AGE_MS = 24 * MILLISECONDS_PER_HOUR; export const CONTEXT_OBSERVATION_MAX_CHARACTERS = 10_000_000; export const CONTEXT_OBSERVATION_MAX_AGE_MS = 5 * MILLISECONDS_PER_MINUTE; export const CONTEXT_ASSESSMENT_QUERY_LIMIT = 10_000; export const CONTEXT_EVENT_DEDUP_LIMIT = 1_000; export const CONTEXT_ASSESSMENT_DEFAULT_WINDOW_MS = 24 * MILLISECONDS_PER_HOUR; export const MILLISECONDS_PER_DAY = 24 * MILLISECONDS_PER_HOUR; export const JITTOR_STATE_DIRECTORY = "jittor"; export const JITTOR_EXTENSION_SETTINGS_FILENAME = "extension.json"; export const DATABASE_FILENAME = "jittor.db"; export const TOKEN_FILENAME = "auth-token"; export const HANDLE_FILENAME = "daemon.json"; export const SYSTEMD_UNIT_NAME = "jittor.service"; export const USAGE_CHART_HEIGHT = 8; export const USAGE_Y_AXIS_WIDTH = 7; /** * A single flat "most recent N rows" query lets one heavy provider/model monopolize the entire * budget within the query window, silently starving every other series out of the chart no matter * which time frame is selected (a real bug: a single long, heavy session can fill 10k rows within * a few hours, hiding a whole other provider's usage from a day earlier even in the Monthly view). * The usage/cost dashboard instead fetches per distinct scope (see distinctScopes), bounded by * these two limits; the worst-case total row volume (40 * 250 = 10,000) matches the old flat cap, * but is now fairly distributed across every active series instead of claimable by just one. */ export const USAGE_MAX_DISTINCT_SCOPES = 40; export const USAGE_PER_SCOPE_QUERY_LIMIT = 250; export const USAGE_RENDER_MAX_SERIES = 20; export const HUMAN_STATUS_MAX_SOURCES = 20; export const HUMAN_TEXT_FIELD_MAX_CHARACTERS = 160; export const CLI_METRICS_HUMAN_MAX_ROWS = 50; export const CLI_AVAILABLE_ROUTES_MAX = 200; /** Bounded rolling window for the compaction duration estimator; older samples are never fetched. */ export const COMPACTION_DURATION_ESTIMATE_MAX_SAMPLES = 20; /** Below this many samples the estimate stays explicit cold-start uncertainty rather than a guess. */ export const COMPACTION_DURATION_ESTIMATE_MIN_SAMPLES = 3; export const MAX_USAGE_BUCKETS = 120; /** Defense-in-depth cap on the SQL-side usage aggregation result: (scopes x metrics x buckets) is already small by construction, but this bounds it explicitly rather than trusting that alone. */ export const USAGE_AGGREGATE_MAX_ROWS = 25_000; export const MAX_DYNAMIC_ROUTES = 100; /** Bounds concurrent in-memory Pi router scopes; the least recently used non-global scope is evicted. */ export const ROUTER_MAX_SESSION_SCOPES = 500; export const ROUTER_SESSION_ID_MAX_CHARACTERS = 128; /** Hard cap on registered session_identities rows; oldest-seen identity is evicted beyond this. */ export const SESSION_IDENTITY_MAX_ROWS = 2_000; /** Bounds one metrics.record_batch call; a real per-turn event batch (usage, headers, local-run metrics) is a handful of rows, never thousands. */ export const METRIC_BATCH_MAX_OBSERVATIONS = 100; export const CODEX_ERROR_MESSAGE_LIMIT = 160; export const CODEX_RETRY_AFTER_MAX_MS = 5 * MILLISECONDS_PER_MINUTE; export const CODEX_RECOVERY_BASE_DELAY_MS = 2 * MILLISECONDS_PER_SECOND; export const CODEX_RECOVERY_MAX_DELAY_MS = CODEX_RETRY_AFTER_MAX_MS; export const CODEX_RECOVERY_MAX_ATTEMPTS = 3; export const CODEX_RECOVERY_ATTEMPT_WINDOW_MS = 10 * MILLISECONDS_PER_MINUTE; export const CODEX_RECOVERY_JITTER_RATIO = 0.2; export const GOOGLE_VERTEX_BUDGET_DISPLAY_NAME_MAX_CHARACTERS = 160; /** Bounded per-poll pull size; a budget subscription realistically holds at most a few pending notifications. */ export const GOOGLE_VERTEX_BUDGET_MAX_MESSAGES_PER_PULL = 20; /** * Lower than Codex's header-derived 0.8: this is Google's own documented "estimated ... subject to * change until your invoice is finalized" data, delivered at-least-once and possibly out of order, * multiple times per day rather than on every response. */ export const GOOGLE_VERTEX_BUDGET_CONFIDENCE = 0.6; export const GOOGLE_ADC_TOKEN_REFRESH_SKEW_MS = 60_000; /** * Context Hub: the shared, versioned, multi-producer channel any extension can target to * contribute one segment of the context-window breakdown (successor to the single-producer * papyrus.context-injection.v1 shape) -- Papyrus's rules/tasks segment is the first producer. */ export const CONTEXT_HUB_CONTRIBUTION_CHANNEL = "jittor.context-contribution.v1"; export const CONTEXT_HUB_CONTRIBUTION_SCHEMA = "jittor.context-contribution/v1"; export const CONTEXT_HUB_PRODUCER_NAME_MAX_CHARACTERS = 80; export const CONTEXT_HUB_SEGMENT_LABEL_MAX_CHARACTERS = 160; export const CONTEXT_HUB_SEGMENT_KEY_MAX_CHARACTERS = 80; export const CONTEXT_HUB_ITEM_LABEL_MAX_CHARACTERS = 200; export const CONTEXT_HUB_MAX_ITEMS_PER_SEGMENT = 500; export const CONTEXT_HUB_MAX_ITEM_DEPTH = 6; export const CONTEXT_HUB_CONTRIBUTION_MAX_AGE_MS = 5 * MILLISECONDS_PER_MINUTE; export const CONTEXT_HUB_CONTRIBUTION_DEDUP_LIMIT = 1_000; /** Matches Papyrus's own CONTEXT_ESTIMATE_CHARACTERS_PER_TOKEN; kept independent since Jittor does not depend on the Papyrus package. */ export const CONTEXT_ESTIMATE_CHARACTERS_PER_TOKEN = 4; /** Matches Papyrus's own CONTEXT_TREE_MAX_NODES: a bound on the message-history tree walk, independent of any other producer's own item-count bound (CONTEXT_HUB_MAX_ITEMS_PER_SEGMENT). */ export const CONTEXT_TREE_MAX_NODES = 50_000; /** Pi's own documented compaction-reserve default (docs/compaction.md): headroom kept free for the model's response, subtracted from the model's contextWindow to get the real usable budget. */ export const CONTEXT_DEFAULT_RESERVE_TOKENS = 16_384; export const CONTEXT_HUB_CONFIDENCE_TIERS = ["exact-tool", "exact-structural", "exact-cooperative", "correlated", "audited"] as const;