fix: wire generated_by_model into observation write path
The generated_by_model column was added to the observations table in the Phase 0 governance schema migration but never wired into the INSERT statements. All 3,878+ observations in production have this field NULL. This fix threads the model ID from each agent (SDKAgent, GeminiAgent, OpenRouterAgent) through processAgentResponse() into storeObservation(), storeObservations(), and storeObservationsAndMarkComplete(). Unblocks Thompson Sampling RFC (#1571) which needs {obs_type}:{model} as the bandit arm key. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1517,7 +1517,8 @@ export class SessionStore {
|
||||
},
|
||||
promptNumber?: number,
|
||||
discoveryTokens: number = 0,
|
||||
overrideTimestampEpoch?: number
|
||||
overrideTimestampEpoch?: number,
|
||||
generatedByModel?: string
|
||||
): { id: number; createdAtEpoch: number } {
|
||||
// Use override timestamp if provided (for processing backlog messages with original timestamps)
|
||||
const timestampEpoch = overrideTimestampEpoch ?? Date.now();
|
||||
@@ -1533,8 +1534,9 @@ export class SessionStore {
|
||||
const stmt = this.db.prepare(`
|
||||
INSERT INTO observations
|
||||
(memory_session_id, project, type, title, subtitle, facts, narrative, concepts,
|
||||
files_read, files_modified, prompt_number, discovery_tokens, content_hash, created_at, created_at_epoch)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
files_read, files_modified, prompt_number, discovery_tokens, content_hash, created_at, created_at_epoch,
|
||||
generated_by_model)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`);
|
||||
|
||||
const result = stmt.run(
|
||||
@@ -1552,7 +1554,8 @@ export class SessionStore {
|
||||
discoveryTokens,
|
||||
contentHash,
|
||||
timestampIso,
|
||||
timestampEpoch
|
||||
timestampEpoch,
|
||||
generatedByModel || null
|
||||
);
|
||||
|
||||
return {
|
||||
@@ -1651,7 +1654,8 @@ export class SessionStore {
|
||||
} | null,
|
||||
promptNumber?: number,
|
||||
discoveryTokens: number = 0,
|
||||
overrideTimestampEpoch?: number
|
||||
overrideTimestampEpoch?: number,
|
||||
generatedByModel?: string
|
||||
): { observationIds: number[]; summaryId: number | null; createdAtEpoch: number } {
|
||||
// Use override timestamp if provided
|
||||
const timestampEpoch = overrideTimestampEpoch ?? Date.now();
|
||||
@@ -1665,8 +1669,9 @@ export class SessionStore {
|
||||
const obsStmt = this.db.prepare(`
|
||||
INSERT INTO observations
|
||||
(memory_session_id, project, type, title, subtitle, facts, narrative, concepts,
|
||||
files_read, files_modified, prompt_number, discovery_tokens, content_hash, created_at, created_at_epoch)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
files_read, files_modified, prompt_number, discovery_tokens, content_hash, created_at, created_at_epoch,
|
||||
generated_by_model)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`);
|
||||
|
||||
for (const observation of observations) {
|
||||
@@ -1693,7 +1698,8 @@ export class SessionStore {
|
||||
discoveryTokens,
|
||||
contentHash,
|
||||
timestampIso,
|
||||
timestampEpoch
|
||||
timestampEpoch,
|
||||
generatedByModel || null
|
||||
);
|
||||
observationIds.push(Number(result.lastInsertRowid));
|
||||
}
|
||||
@@ -1780,7 +1786,8 @@ export class SessionStore {
|
||||
_pendingStore: PendingMessageStore,
|
||||
promptNumber?: number,
|
||||
discoveryTokens: number = 0,
|
||||
overrideTimestampEpoch?: number
|
||||
overrideTimestampEpoch?: number,
|
||||
generatedByModel?: string
|
||||
): { observationIds: number[]; summaryId?: number; createdAtEpoch: number } {
|
||||
// Use override timestamp if provided
|
||||
const timestampEpoch = overrideTimestampEpoch ?? Date.now();
|
||||
@@ -1794,8 +1801,9 @@ export class SessionStore {
|
||||
const obsStmt = this.db.prepare(`
|
||||
INSERT INTO observations
|
||||
(memory_session_id, project, type, title, subtitle, facts, narrative, concepts,
|
||||
files_read, files_modified, prompt_number, discovery_tokens, content_hash, created_at, created_at_epoch)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
files_read, files_modified, prompt_number, discovery_tokens, content_hash, created_at, created_at_epoch,
|
||||
generated_by_model)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`);
|
||||
|
||||
for (const observation of observations) {
|
||||
@@ -1822,7 +1830,8 @@ export class SessionStore {
|
||||
discoveryTokens,
|
||||
contentHash,
|
||||
timestampIso,
|
||||
timestampEpoch
|
||||
timestampEpoch,
|
||||
generatedByModel || null
|
||||
);
|
||||
observationIds.push(Number(result.lastInsertRowid));
|
||||
}
|
||||
|
||||
@@ -175,7 +175,9 @@ export class GeminiAgent {
|
||||
worker,
|
||||
tokensUsed,
|
||||
null,
|
||||
'Gemini'
|
||||
'Gemini',
|
||||
undefined,
|
||||
model
|
||||
);
|
||||
} else {
|
||||
logger.error('SDK', 'Empty Gemini init response - session may lack context', {
|
||||
@@ -248,7 +250,8 @@ export class GeminiAgent {
|
||||
tokensUsed,
|
||||
originalTimestamp,
|
||||
'Gemini',
|
||||
lastCwd
|
||||
lastCwd,
|
||||
model
|
||||
);
|
||||
} else {
|
||||
logger.warn('SDK', 'Empty Gemini observation response, skipping processing to preserve message', {
|
||||
@@ -298,7 +301,8 @@ export class GeminiAgent {
|
||||
tokensUsed,
|
||||
originalTimestamp,
|
||||
'Gemini',
|
||||
lastCwd
|
||||
lastCwd,
|
||||
model
|
||||
);
|
||||
} else {
|
||||
logger.warn('SDK', 'Empty Gemini summary response, skipping processing to preserve message', {
|
||||
|
||||
@@ -131,7 +131,8 @@ export class OpenRouterAgent {
|
||||
tokensUsed,
|
||||
null,
|
||||
'OpenRouter',
|
||||
undefined // No lastCwd yet - before message processing
|
||||
undefined, // No lastCwd yet - before message processing
|
||||
model
|
||||
);
|
||||
} else {
|
||||
logger.error('SDK', 'Empty OpenRouter init response - session may lack context', {
|
||||
@@ -202,7 +203,8 @@ export class OpenRouterAgent {
|
||||
tokensUsed,
|
||||
originalTimestamp,
|
||||
'OpenRouter',
|
||||
lastCwd
|
||||
lastCwd,
|
||||
model
|
||||
);
|
||||
|
||||
} else if (message.type === 'summarize') {
|
||||
@@ -244,7 +246,8 @@ export class OpenRouterAgent {
|
||||
tokensUsed,
|
||||
originalTimestamp,
|
||||
'OpenRouter',
|
||||
lastCwd
|
||||
lastCwd,
|
||||
model
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,7 +270,8 @@ export class SDKAgent {
|
||||
discoveryTokens,
|
||||
originalTimestamp,
|
||||
'SDK',
|
||||
cwdTracker.lastCwd
|
||||
cwdTracker.lastCwd,
|
||||
modelId
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,8 @@ export async function processAgentResponse(
|
||||
discoveryTokens: number,
|
||||
originalTimestamp: number | null,
|
||||
agentName: string,
|
||||
projectRoot?: string
|
||||
projectRoot?: string,
|
||||
modelId?: string
|
||||
): Promise<void> {
|
||||
// Track generator activity for stale detection (Issue #1099)
|
||||
session.lastGeneratorActivity = Date.now();
|
||||
@@ -102,7 +103,8 @@ export async function processAgentResponse(
|
||||
summaryForStore,
|
||||
session.lastPromptNumber,
|
||||
discoveryTokens,
|
||||
originalTimestamp ?? undefined
|
||||
originalTimestamp ?? undefined,
|
||||
modelId
|
||||
);
|
||||
|
||||
// Log storage result with IDs for end-to-end traceability
|
||||
|
||||
Reference in New Issue
Block a user