Merge branch 'pr-1472' into integration/validation-batch

# Conflicts:
#	plugin/scripts/context-generator.cjs
#	plugin/scripts/mcp-server.cjs
#	plugin/scripts/worker-service.cjs
#	plugin/ui/viewer-bundle.js
#	src/cli/handlers/context.ts
#	src/services/sqlite/SessionStore.ts
#	src/services/sqlite/migrations/runner.ts
#	src/services/worker-service.ts
#	src/shared/SettingsDefaultsManager.ts
This commit is contained in:
Alex Newman
2026-04-06 14:23:18 -07:00
50 changed files with 3852 additions and 683 deletions
+10 -6
View File
@@ -9,9 +9,11 @@ import { writeAgentsMd } from '../../utils/agents-md-utils.js';
import { resolveFieldSpec, resolveFields, matchesRule } from './field-utils.js';
import { expandHomePath } from './config.js';
import type { TranscriptSchema, WatchTarget, SchemaEvent } from './types.js';
import { normalizePlatformSource } from '../../shared/platform-source.js';
interface SessionState {
sessionId: string;
platformSource: string;
cwd?: string;
project?: string;
lastUserMessage?: string;
@@ -51,6 +53,7 @@ export class TranscriptEventProcessor {
if (!session) {
session = {
sessionId,
platformSource: normalizePlatformSource(watch.name),
pendingTools: new Map()
};
this.sessions.set(key, session);
@@ -181,7 +184,7 @@ export class TranscriptEventProcessor {
sessionId: session.sessionId,
cwd,
prompt,
platform: 'transcript'
platform: session.platformSource
});
}
@@ -250,7 +253,7 @@ export class TranscriptEventProcessor {
toolName,
toolInput: this.maybeParseJson(fields.toolInput),
toolResponse: this.maybeParseJson(fields.toolResponse),
platform: 'transcript'
platform: session.platformSource
});
}
@@ -263,7 +266,7 @@ export class TranscriptEventProcessor {
cwd: session.cwd ?? process.cwd(),
filePath,
edits: Array.isArray(fields.edits) ? fields.edits : undefined,
platform: 'transcript'
platform: session.platformSource
});
}
@@ -305,7 +308,7 @@ export class TranscriptEventProcessor {
await sessionCompleteHandler.execute({
sessionId: session.sessionId,
cwd: session.cwd ?? process.cwd(),
platform: 'transcript'
platform: session.platformSource
});
await this.updateContext(session, watch);
session.pendingTools.clear();
@@ -325,7 +328,8 @@ export class TranscriptEventProcessor {
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
contentSessionId: session.sessionId,
last_assistant_message: lastAssistantMessage
last_assistant_message: lastAssistantMessage,
platformSource: session.platformSource
})
});
} catch (error) {
@@ -350,7 +354,7 @@ export class TranscriptEventProcessor {
try {
const response = await workerHttpRequest(
`/api/context/inject?projects=${encodeURIComponent(projectsParam)}`
`/api/context/inject?projects=${encodeURIComponent(projectsParam)}&platformSource=${encodeURIComponent(session.platformSource)}`
);
if (!response.ok) return;
+12 -5
View File
@@ -117,15 +117,15 @@ export class TranscriptWatcher {
const files = this.resolveWatchFiles(resolvedPath);
for (const filePath of files) {
await this.addTailer(filePath, watch, schema);
await this.addTailer(filePath, watch, schema, true);
}
const rescanIntervalMs = watch.rescanIntervalMs ?? 5000;
const timer = setInterval(async () => {
const timer = setInterval(async () => {
const newFiles = this.resolveWatchFiles(resolvedPath);
for (const filePath of newFiles) {
if (!this.tailers.has(filePath)) {
await this.addTailer(filePath, watch, schema);
await this.addTailer(filePath, watch, schema, false);
}
}
}, rescanIntervalMs);
@@ -164,13 +164,20 @@ export class TranscriptWatcher {
return /[*?[\]{}()]/.test(inputPath);
}
private async addTailer(filePath: string, watch: WatchTarget, schema: TranscriptSchema): Promise<void> {
private async addTailer(
filePath: string,
watch: WatchTarget,
schema: TranscriptSchema,
initialDiscovery: boolean
): Promise<void> {
if (this.tailers.has(filePath)) return;
const sessionIdOverride = this.extractSessionIdFromPath(filePath);
let offset = this.state.offsets[filePath] ?? 0;
if (offset === 0 && watch.startAtEnd) {
// `startAtEnd` is useful on worker startup to avoid replaying the full backlog,
// but new transcript files must be read from byte 0 or we lose session_meta/user_message.
if (offset === 0 && watch.startAtEnd && initialDiscovery) {
try {
offset = statSync(filePath).size;
} catch {