Stop shipping megabytes of skill prompts in every snapshot refresh
The whole app turned to molasses because snapshot.load() shipped the entire skill_runtime_snapshots table - unbounded, compiled_prompt included - over IPC on every refresh. A real profile carried 142 rows totaling 144MB (1.1MB each from the pre-cap CEO compile-all era), so every coalesced refresh serialized ~144MB of JSON. The forced-humanizer rework made it worse by adding a row per run for every agent. - Drop skillRuntimeSnapshots, skillRevisions, skillTests, and skillBindings from the renderer snapshot: no renderer surface reads them; skill internals are main-process state. Only the lightweight skillDefinitions catalogue still ships. - Project provider_requests without raw_response_json (4.1MB across the newest 100 rows; RunsPage only reads responseText) - Migration 051 purges the bug-era compiled prompts from existing DBs - resolveRuntimeSnapshot is now idempotent per run: a run re-queued by startup recovery reuses its frozen snapshot instead of dying on the uniqueness guard and burning real retry budget - Regression test pins the contract: a 2MB database row must not add bytes to the snapshot (payload asserted under 400KB)
This commit is contained in:
1 parent
4ab20e679c
commit
1f89ea7089
10 files changed
+117
-34
No files matched your search
@@ -178,9 +178,12 @@ export class SkillService {
|
||||
* compiled prompt instead of silently overflowing the model's context.
|
||||
*/
|
||||
resolveRuntimeSnapshot(input: ResolveAgentSkillsInput): string {
|
||||
// Idempotent per run: a run interrupted after resolving (crash, quit) is
|
||||
// re-queued by startup recovery and must reuse its frozen skill set, not
|
||||
// die on a uniqueness error that burns real retry budget.
|
||||
const existingSnapshot = this.db.prepare("select id from skill_runtime_snapshots where agent_id = ? and run_id = ?")
|
||||
.get(input.agentId, input.runId) as { id: string } | undefined;
|
||||
if (existingSnapshot) throw new Error("Skill runtime snapshot already exists for this run.");
|
||||
if (existingSnapshot) return existingSnapshot.id;
|
||||
const forcedRows = this.db.prepare(`
|
||||
select
|
||||
sd.id as skill_id,
|
||||
|
||||
@@ -62,8 +62,6 @@ export class SnapshotService {
|
||||
);
|
||||
const providerUsageWindows = list<ProviderUsageWindowRow>(this.db, "provider_usage_windows", "window_start desc");
|
||||
const providerRateLimits = buildProviderRateLimits(providers, providerUsageWindows);
|
||||
const skillBindings = list<AppSnapshot["skillBindings"][number]>(this.db, "skill_bindings", "priority asc")
|
||||
.map((binding) => ({ ...binding, enabled: toBool(binding.enabled) }));
|
||||
const files = list<AppSnapshot["files"][number]>(this.db, "file_objects", "created_at desc")
|
||||
.map((file) => ({ ...file, pinned: toBool(file.pinned) }));
|
||||
const legalHolds = list<AppSnapshot["legalHolds"][number]>(this.db, "legal_holds", "created_at desc")
|
||||
@@ -115,14 +113,18 @@ export class SnapshotService {
|
||||
providerAuthProfiles,
|
||||
providerAuthSessions,
|
||||
providerCatalog: PROVIDER_CATALOG,
|
||||
providerRequests: recentList(this.db, "provider_requests", "created_at desc", 100),
|
||||
// Explicit projection: raw_response_json alone weighs megabytes across
|
||||
// 100 rows and no renderer surface reads it.
|
||||
providerRequests: all<Row>(this.db.prepare(`
|
||||
select id, org_id, provider_id, provider_key, workspace_id, model, prompt_sha256,
|
||||
response_text, state, error_message, input_char_count, output_char_count,
|
||||
execution_mode, policy_decision, external_response_id, stream_event_count,
|
||||
cancelled_at, created_at, completed_at
|
||||
from provider_requests order by created_at desc limit 100
|
||||
`)).map((row) => camel(row) as unknown as AppSnapshot["providerRequests"][number]),
|
||||
providerRateLimits,
|
||||
providerRateLimitObservations,
|
||||
skillDefinitions: list(this.db, "skill_definitions", "created_at asc"),
|
||||
skillRevisions: list(this.db, "skill_revisions", "published_at desc"),
|
||||
skillBindings,
|
||||
skillRuntimeSnapshots: list(this.db, "skill_runtime_snapshots", "created_at desc"),
|
||||
skillTests: list(this.db, "skill_tests", "last_run_at desc, id asc"),
|
||||
socialAccounts: list(this.db, "social_accounts", "created_at asc"),
|
||||
socialAccountGrants: list(this.db, "social_account_grants", "created_at asc"),
|
||||
browserSessionContainers: list<AppSnapshot["browserSessionContainers"][number]>(this.db, "browser_session_containers", "created_at asc")
|
||||
|
||||
Reference in new issue
Block a user