fix: typing cleanup and viewer tsconfig split for PR feedback

- Add explicit return types for SessionStore query methods
- Exclude src/ui/viewer from root tsconfig, give it its own DOM-typed config
- Add bun to root tsconfig types, plus misc typing tweaks flagged by Greptile
- Rebuilt plugin/scripts/* artifacts

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alex Newman
2026-04-24 13:57:04 -07:00
parent 96c55078d2
commit 34a7f2021f
24 changed files with 467 additions and 283 deletions

View File

@@ -89,6 +89,9 @@
"cursor:uninstall": "bun plugin/scripts/worker-service.cjs cursor uninstall",
"cursor:status": "bun plugin/scripts/worker-service.cjs cursor status",
"cursor:setup": "bun plugin/scripts/worker-service.cjs cursor setup",
"typecheck": "tsc --noEmit && tsc --noEmit -p src/ui/viewer/tsconfig.json",
"typecheck:root": "tsc --noEmit",
"typecheck:viewer": "tsc --noEmit -p src/ui/viewer/tsconfig.json",
"test": "bun test",
"test:sqlite": "bun test tests/sqlite/",
"test:agents": "bun test tests/worker/agents/",
@@ -131,6 +134,7 @@
"@tree-sitter-grammars/tree-sitter-toml": "^0.7.0",
"@tree-sitter-grammars/tree-sitter-yaml": "^0.7.1",
"@tree-sitter-grammars/tree-sitter-zig": "^1.1.2",
"@types/bun": "^1.3.13",
"@types/cors": "^2.8.19",
"@types/dompurify": "^3.0.5",
"@types/express": "^4.17.21",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -351,7 +351,8 @@ function runNpmInstallInMarketplace(): void {
execSync('npm install --production', {
cwd: marketplaceDir,
stdio: 'pipe',
...(IS_WINDOWS ? { shell: true as const } : {}),
encoding: 'utf8',
...(IS_WINDOWS ? { shell: process.env.ComSpec ?? 'cmd.exe' } : {}),
});
}
@@ -370,7 +371,8 @@ function runSmartInstall(): boolean {
try {
execSync(`node "${smartInstallPath}"`, {
stdio: 'inherit',
...(IS_WINDOWS ? { shell: true as const } : {}),
encoding: 'utf8',
...(IS_WINDOWS ? { shell: process.env.ComSpec ?? 'cmd.exe' } : {}),
});
return true;
} catch (error: unknown) {

View File

@@ -480,15 +480,6 @@ const QUERIES: Record<string, string> = {
(class_definition name: (identifier) @name) @cls
(import_statement) @imp
(import_declaration) @imp
`,
php: `
(function_definition name: (name) @name) @func
(method_declaration name: (name) @name) @method
(class_declaration name: (name) @name) @cls
(interface_declaration name: (name) @name) @iface
(trait_declaration name: (name) @name) @trait_def
(namespace_use_declaration) @imp
`,
};

View File

@@ -1,4 +1,4 @@
import { Database } from 'bun:sqlite';
import { Database, type SQLQueryBindings } from 'bun:sqlite';
import { DATA_DIR, DB_PATH, ensureDir, OBSERVER_SESSIONS_PROJECT } from '../../shared/paths.js';
import { logger } from '../../utils/logger.js';
import {
@@ -13,6 +13,7 @@ import {
LatestPromptResult
} from '../../types/database.js';
import type { PendingMessageStore } from './PendingMessageStore.js';
import type { ObservationSearchResult, SessionSummarySearchResult } from './types.js';
import { computeObservationContentHash } from './observations/store.js';
import { parseFileList } from './observations/files.js';
import { DEFAULT_PLATFORM_SOURCE, normalizePlatformSource, sortPlatformSources } from '../../shared/platform-source.js';
@@ -1111,7 +1112,18 @@ export class SessionStore {
LIMIT ?
`);
return stmt.all(project, limit);
return stmt.all(project, limit) as Array<{
request: string | null;
investigated: string | null;
learned: string | null;
completed: string | null;
next_steps: string | null;
files_read: string | null;
files_edited: string | null;
notes: string | null;
prompt_number: number | null;
created_at: string;
}>;
}
/**
@@ -1136,7 +1148,15 @@ export class SessionStore {
LIMIT ?
`);
return stmt.all(project, limit);
return stmt.all(project, limit) as Array<{
memory_session_id: string;
request: string | null;
learned: string | null;
completed: string | null;
next_steps: string | null;
prompt_number: number | null;
created_at: string;
}>;
}
/**
@@ -1156,7 +1176,12 @@ export class SessionStore {
LIMIT ?
`);
return stmt.all(project, limit);
return stmt.all(project, limit) as Array<{
type: string;
text: string;
prompt_number: number | null;
created_at: string;
}>;
}
/**
@@ -1192,7 +1217,18 @@ export class SessionStore {
LIMIT ?
`);
return stmt.all(limit);
return stmt.all(limit) as Array<{
id: number;
type: string;
title: string | null;
subtitle: string | null;
text: string;
project: string;
platform_source: string;
prompt_number: number | null;
created_at: string;
created_at_epoch: number;
}>;
}
/**
@@ -1236,7 +1272,22 @@ export class SessionStore {
LIMIT ?
`);
return stmt.all(limit);
return stmt.all(limit) as Array<{
id: number;
request: string | null;
investigated: string | null;
learned: string | null;
completed: string | null;
next_steps: string | null;
files_read: string | null;
files_edited: string | null;
notes: string | null;
project: string;
platform_source: string;
prompt_number: number | null;
created_at: string;
created_at_epoch: number;
}>;
}
/**
@@ -1268,7 +1319,16 @@ export class SessionStore {
LIMIT ?
`);
return stmt.all(limit);
return stmt.all(limit) as Array<{
id: number;
content_session_id: string;
project: string;
platform_source: string;
prompt_number: number;
prompt_text: string;
created_at: string;
created_at_epoch: number;
}>;
}
/**
@@ -1282,7 +1342,7 @@ export class SessionStore {
WHERE project IS NOT NULL AND project != ''
AND project != ?
`;
const params: unknown[] = [OBSERVER_SESSIONS_PROJECT];
const params: SQLQueryBindings[] = [OBSERVER_SESSIONS_PROJECT];
if (normalizedPlatformSource) {
query += ' AND COALESCE(platform_source, ?) = ?';
@@ -1403,7 +1463,13 @@ export class SessionStore {
ORDER BY started_at_epoch ASC
`);
return stmt.all(project, limit);
return stmt.all(project, limit) as Array<{
memory_session_id: string | null;
status: string;
started_at: string;
user_prompt: string | null;
has_summary: boolean;
}>;
}
/**
@@ -1422,7 +1488,12 @@ export class SessionStore {
ORDER BY created_at_epoch ASC
`);
return stmt.all(memorySessionId);
return stmt.all(memorySessionId) as Array<{
title: string;
subtitle: string;
type: string;
prompt_number: number | null;
}>;
}
/**
@@ -1444,7 +1515,7 @@ export class SessionStore {
getObservationsByIds(
ids: number[],
options: { orderBy?: 'date_desc' | 'date_asc'; limit?: number; project?: string; type?: string | string[]; concepts?: string | string[]; files?: string | string[] } = {}
): ObservationRecord[] {
): ObservationSearchResult[] {
if (ids.length === 0) return [];
const { orderBy = 'date_desc', limit, project, type, concepts, files } = options;
@@ -1508,7 +1579,7 @@ export class SessionStore {
${limitClause}
`);
return stmt.all(...params) as ObservationRecord[];
return stmt.all(...params) as ObservationSearchResult[];
}
/**
@@ -1538,7 +1609,19 @@ export class SessionStore {
LIMIT 1
`);
return stmt.get(memorySessionId) || null;
return (stmt.get(memorySessionId) as {
request: string | null;
investigated: string | null;
learned: string | null;
completed: string | null;
next_steps: string | null;
files_read: string | null;
files_edited: string | null;
notes: string | null;
prompt_number: number | null;
created_at: string;
created_at_epoch: number;
} | null) || null;
}
/**
@@ -1598,7 +1681,16 @@ export class SessionStore {
LIMIT 1
`);
return stmt.get(id) || null;
return (stmt.get(id) as {
id: number;
content_session_id: string;
memory_session_id: string | null;
project: string;
platform_source: string;
user_prompt: string;
custom_title: string | null;
status: string;
} | null) || null;
}
/**
@@ -2216,7 +2308,7 @@ export class SessionStore {
getSessionSummariesByIds(
ids: number[],
options: { orderBy?: 'date_desc' | 'date_asc'; limit?: number; project?: string } = {}
): SessionSummaryRecord[] {
): SessionSummarySearchResult[] {
if (ids.length === 0) return [];
const { orderBy = 'date_desc', limit, project } = options;
@@ -2238,7 +2330,7 @@ export class SessionStore {
${limitClause}
`);
return stmt.all(...params) as SessionSummaryRecord[];
return stmt.all(...params) as SessionSummarySearchResult[];
}
/**
@@ -2470,7 +2562,15 @@ export class SessionStore {
LIMIT 1
`);
return stmt.get(id) || null;
return (stmt.get(id) as {
id: number;
content_session_id: string;
prompt_number: number;
prompt_text: string;
project: string;
created_at: string;
created_at_epoch: number;
} | null) || null;
}
/**
@@ -2546,7 +2646,18 @@ export class SessionStore {
LIMIT 1
`);
return stmt.get(id) || null;
return (stmt.get(id) as {
id: number;
memory_session_id: string | null;
content_session_id: string;
project: string;
user_prompt: string;
request_summary: string | null;
learned_summary: string | null;
status: string;
created_at: string;
created_at_epoch: number;
} | null) || null;
}
/**

View File

@@ -124,7 +124,7 @@ export class TranscriptEventProcessor {
const project = this.resolveProject(entry, watch, schema, event, session);
if (project) session.project = project;
const fields = resolveFields(event.fields, entry, { watch, schema, session });
const fields = resolveFields(event.fields, entry, { watch, schema, session: session as unknown as Record<string, unknown> });
switch (event.action) {
case 'session_context':

View File

@@ -79,6 +79,7 @@ import { DatabaseManager } from './worker/DatabaseManager.js';
import { SessionManager } from './worker/SessionManager.js';
import { SSEBroadcaster } from './worker/SSEBroadcaster.js';
import { SDKAgent } from './worker/SDKAgent.js';
import type { WorkerRef } from './worker/agents/types.js';
import { GeminiAgent, isGeminiSelected, isGeminiAvailable } from './worker/GeminiAgent.js';
import { OpenRouterAgent, isOpenRouterSelected, isOpenRouterAvailable } from './worker/OpenRouterAgent.js';
import { PaginationHelper } from './worker/PaginationHelper.js';
@@ -136,7 +137,7 @@ export function buildStatusOutput(status: 'ready' | 'error', message?: string):
};
}
export class WorkerService {
export class WorkerService implements WorkerRef {
private server: Server;
private startTime: number = Date.now();
private mcpClient: Client;
@@ -149,7 +150,7 @@ export class WorkerService {
// Service layer
private dbManager: DatabaseManager;
private sessionManager: SessionManager;
private sseBroadcaster: SSEBroadcaster;
public sseBroadcaster: SSEBroadcaster;
private sdkAgent: SDKAgent;
private geminiAgent: GeminiAgent;
private openRouterAgent: OpenRouterAgent;
@@ -496,7 +497,10 @@ export class WorkerService {
const transport = new StdioClientTransport({
command: process.execPath, // Use resolved path, not bare 'node' which fails on non-interactive PATH (#1876)
args: [mcpServerPath],
env: sanitizeEnv(process.env)
env: Object.fromEntries(
Object.entries(sanitizeEnv(process.env)).filter(([, value]) => value !== undefined)
) as Record<string, string>
});
const MCP_INIT_TIMEOUT_MS = 300000;

View File

@@ -7,6 +7,7 @@
* - Efficient LIMIT+1 trick to avoid COUNT(*) query
*/
import type { SQLQueryBindings } from 'bun:sqlite';
import { DatabaseManager } from './DatabaseManager.js';
import { logger } from '../../utils/logger.js';
import { OBSERVER_SESSIONS_PROJECT } from '../../shared/paths.js';
@@ -102,7 +103,7 @@ export class PaginationHelper {
FROM observations o
LEFT JOIN sdk_sessions s ON o.memory_session_id = s.memory_session_id
`;
const params: unknown[] = [];
const params: SQLQueryBindings[] = [];
const conditions: string[] = [];
if (project) {

View File

@@ -110,7 +110,7 @@ export class SDKAgent {
logger.info('SDK', 'Starting SDK query', {
sessionDbId: session.sessionDbId,
contentSessionId: session.contentSessionId,
memorySessionId: session.memorySessionId,
memorySessionId: session.memorySessionId ?? undefined,
hasRealMemorySessionId,
shouldResume,
resume_parameter: shouldResume ? session.memorySessionId : '(none - fresh start)',
@@ -144,7 +144,7 @@ export class SDKAgent {
// instead of polluting user's actual project resume lists
cwd: OBSERVER_SESSIONS_DIR,
// Only resume if shouldResume is true (memorySessionId exists, not first prompt, not forceInit)
...(shouldResume && { resume: session.memorySessionId }),
...(shouldResume && session.memorySessionId ? { resume: session.memorySessionId } : {}),
disallowedTools,
abortController: session.abortController,
pathToClaudeCodeExecutable: claudePath,

View File

@@ -37,7 +37,9 @@ export class SettingsManager {
for (const row of rows) {
const key = row.key as keyof ViewerSettings;
if (key in settings) {
settings[key] = JSON.parse(row.value) as ViewerSettings[typeof key];
// Object.assign narrows correctly across the discriminated union
// where `settings[key] = value` would collapse to `never`.
Object.assign(settings, { [key]: JSON.parse(row.value) });
}
}

View File

@@ -329,7 +329,7 @@ async function syncAndBroadcastObservations(
// Only runs if CLAUDE_MEM_FOLDER_CLAUDEMD_ENABLED is true (default: false)
const settings = SettingsDefaultsManager.loadFromFile(USER_SETTINGS_PATH);
// Handle both string 'true' and boolean true from JSON settings
const settingValue = settings.CLAUDE_MEM_FOLDER_CLAUDEMD_ENABLED;
const settingValue: unknown = settings.CLAUDE_MEM_FOLDER_CLAUDEMD_ENABLED;
const folderClaudeMdEnabled = settingValue === 'true' || settingValue === true;
if (folderClaudeMdEnabled) {

View File

@@ -73,6 +73,17 @@ export class MemoryRoutes extends BaseRouteHandler {
});
// 4. Sync to ChromaDB (async, fire-and-forget)
if (!chromaSync) {
logger.debug('CHROMA', 'ChromaDB sync skipped (chromaSync not available)', { id: result.id });
res.json({
success: true,
id: result.id,
title: observation.title,
project: targetProject,
message: `Memory saved as observation #${result.id}`
});
return;
}
chromaSync.syncObservation(
result.id,
memorySessionId,

View File

@@ -14,7 +14,7 @@ import { getPackageRoot } from '../../../../shared/paths.js';
import { logger } from '../../../../utils/logger.js';
import { SettingsManager } from '../../SettingsManager.js';
import { getBranchInfo, switchBranch, pullUpdates } from '../../BranchManager.js';
import { ModeManager } from '../../domain/ModeManager.js';
import { ModeManager } from '../../../domain/ModeManager.js';
import { BaseRouteHandler } from '../BaseRouteHandler.js';
import { validateBody } from '../middleware/validateBody.js';
import { SettingsDefaultsManager } from '../../../../shared/SettingsDefaultsManager.js';

View File

@@ -6,7 +6,7 @@
*/
import { logger } from '../../../utils/logger.js';
import type { ObservationRecord } from '../../../types/database.js';
import type { ObservationSearchResult } from '../../sqlite/types.js';
import type { SessionStore } from '../../sqlite/SessionStore.js';
import type { SearchOrchestrator } from '../search/SearchOrchestrator.js';
import { CorpusRenderer } from './CorpusRenderer.js';
@@ -121,19 +121,19 @@ export class CorpusBuilder {
}
/**
* Map a raw ObservationRecord (with JSON string fields) to a CorpusObservation
* Map a raw ObservationSearchResult (with JSON string fields) to a CorpusObservation
*/
private mapObservationToCorpus(row: ObservationRecord): CorpusObservation {
private mapObservationToCorpus(row: ObservationSearchResult): CorpusObservation {
return {
id: row.id,
type: row.type,
title: (row as any).title || '',
subtitle: (row as any).subtitle || null,
narrative: (row as any).narrative || null,
facts: safeParseJsonArray((row as any).facts),
concepts: safeParseJsonArray((row as any).concepts),
files_read: safeParseJsonArray((row as any).files_read),
files_modified: safeParseJsonArray((row as any).files_modified),
title: row.title || '',
subtitle: row.subtitle || null,
narrative: row.narrative || null,
facts: safeParseJsonArray(row.facts),
concepts: safeParseJsonArray(row.concepts),
files_read: safeParseJsonArray(row.files_read),
files_modified: safeParseJsonArray(row.files_modified),
project: row.project,
created_at: row.created_at,
created_at_epoch: row.created_at_epoch,

View File

@@ -107,20 +107,25 @@ export class ChromaSearchStrategy extends BaseSearchStrategy implements SearchSt
let sessions: SessionSummarySearchResult[] = [];
let prompts: UserPromptSearchResult[] = [];
// Chroma already ranks by vector similarity; 'relevance' has no SQL
// equivalent, so drop it before hydrating rows from SessionStore.
const sqlOrderBy: 'date_desc' | 'date_asc' | undefined =
options.orderBy === 'relevance' ? undefined : options.orderBy;
if (categorized.obsIds.length > 0) {
const obsOptions = { type: options.obsType, concepts: options.concepts, files: options.files, orderBy: options.orderBy, limit: options.limit, project: options.project };
const obsOptions = { type: options.obsType, concepts: options.concepts, files: options.files, orderBy: sqlOrderBy, limit: options.limit, project: options.project };
observations = this.sessionStore.getObservationsByIds(categorized.obsIds, obsOptions);
}
if (categorized.sessionIds.length > 0) {
sessions = this.sessionStore.getSessionSummariesByIds(categorized.sessionIds, {
orderBy: options.orderBy, limit: options.limit, project: options.project
orderBy: sqlOrderBy, limit: options.limit, project: options.project
});
}
if (categorized.promptIds.length > 0) {
prompts = this.sessionStore.getUserPromptsByIds(categorized.promptIds, {
orderBy: options.orderBy, limit: options.limit, project: options.project
orderBy: sqlOrderBy, limit: options.limit, project: options.project
});
}

View File

@@ -195,7 +195,7 @@ export class SettingsDefaultsManager {
* Handles both string 'true' and boolean true from JSON
*/
static getBool(key: keyof SettingsDefaults): boolean {
const value = this.get(key);
const value: unknown = this.get(key);
return value === 'true' || value === true;
}

View File

@@ -164,7 +164,7 @@ export function validateWorkerPidFile(options: ValidateWorkerPidOptions = {}): V
let pidInfo: PidInfo | null = null;
try {
pidInfo = JSON.parse(readFileSync(pidFilePath, 'utf-8')) as PidInfo;
pidInfo = JSON.parse(readFileSync(pidFilePath, 'utf-8')) as PidInfo | null;
} catch (error: unknown) {
if (error instanceof Error) {
logger.warn('SYSTEM', 'Failed to parse worker PID file, removing it', { path: pidFilePath }, error);
@@ -178,7 +178,8 @@ export function validateWorkerPidFile(options: ValidateWorkerPidOptions = {}): V
return 'invalid';
}
if (verifyPidFileOwnership(pidInfo)) {
const isAlive = verifyPidFileOwnership(pidInfo);
if (isAlive && pidInfo) {
if (options.logAlive ?? true) {
logger.info('SYSTEM', 'Worker already running (PID alive)', {
existingPid: pidInfo.pid,
@@ -190,9 +191,9 @@ export function validateWorkerPidFile(options: ValidateWorkerPidOptions = {}): V
}
logger.info('SYSTEM', 'Removing stale PID file (worker process is dead or PID has been reused)', {
pid: pidInfo.pid,
port: pidInfo.port,
startedAt: pidInfo.startedAt
pid: pidInfo?.pid,
port: pidInfo?.port,
startedAt: pidInfo?.startedAt
});
rmSync(pidFilePath, { force: true });
return 'stale';

View File

@@ -597,9 +597,9 @@ export async function waitForSlot(maxConcurrent: number, timeoutMs: number = 60_
// ---------------------------------------------------------------------------
export interface SpawnedSdkProcess {
stdin: ChildProcess['stdin'];
stdout: ChildProcess['stdout'];
stderr: ChildProcess['stderr'];
stdin: NonNullable<ChildProcess['stdin']>;
stdout: NonNullable<ChildProcess['stdout']>;
stderr: NonNullable<ChildProcess['stderr']>;
readonly killed: boolean;
readonly exitCode: number | null;
kill: ChildProcess['kill'];
@@ -720,6 +720,18 @@ export function spawnSdkProcess(
notifySlotAvailable();
});
if (!child.stdin || !child.stdout || !child.stderr) {
logger.error('PROCESS', 'Spawned SDK child missing required stdio streams', {
sessionDbId,
pid,
hasStdin: Boolean(child.stdin),
hasStdout: Boolean(child.stdout),
hasStderr: Boolean(child.stderr),
});
try { child.kill('SIGKILL'); } catch { /* already dead */ }
return null;
}
const spawned: SpawnedSdkProcess = {
stdin: child.stdin,
stdout: child.stdout,

View File

@@ -15,7 +15,7 @@ type DataItem = Observation | Summary | UserPrompt;
/**
* Generic pagination hook for observations, summaries, and prompts
*/
function usePaginationFor(endpoint: string, dataType: DataType, currentFilter: string, currentSource: string) {
function usePaginationFor<TItem extends DataItem>(endpoint: string, dataType: DataType, currentFilter: string, currentSource: string) {
const [state, setState] = useState<PaginationState>({
isLoading: false,
hasMore: true
@@ -30,7 +30,7 @@ function usePaginationFor(endpoint: string, dataType: DataType, currentFilter: s
* Load more items from the API
* Automatically resets offset to 0 if filter has changed
*/
const loadMore = useCallback(async (): Promise<DataItem[]> => {
const loadMore = useCallback(async (): Promise<TItem[]> => {
// Check if filter changed - if so, reset pagination synchronously
const selectionKey = `${currentSource}::${currentFilter}`;
const filterChanged = lastSelectionRef.current !== selectionKey;
@@ -75,7 +75,7 @@ function usePaginationFor(endpoint: string, dataType: DataType, currentFilter: s
throw new Error(`Failed to load ${dataType}: ${response.statusText}`);
}
const data = await response.json() as { items: DataItem[], hasMore: boolean };
const data = await response.json() as { items: TItem[], hasMore: boolean };
const nextState = {
...stateRef.current,
@@ -106,9 +106,9 @@ function usePaginationFor(endpoint: string, dataType: DataType, currentFilter: s
* Hook for paginating observations
*/
export function usePagination(currentFilter: string, currentSource: string) {
const observations = usePaginationFor(API_ENDPOINTS.OBSERVATIONS, 'observations', currentFilter, currentSource);
const summaries = usePaginationFor(API_ENDPOINTS.SUMMARIES, 'summaries', currentFilter, currentSource);
const prompts = usePaginationFor(API_ENDPOINTS.PROMPTS, 'prompts', currentFilter, currentSource);
const observations = usePaginationFor<Observation>(API_ENDPOINTS.OBSERVATIONS, 'observations', currentFilter, currentSource);
const summaries = usePaginationFor<Summary>(API_ENDPOINTS.SUMMARIES, 'summaries', currentFilter, currentSource);
const prompts = usePaginationFor<UserPrompt>(API_ENDPOINTS.PROMPTS, 'prompts', currentFilter, currentSource);
return {
observations,

View File

@@ -0,0 +1,9 @@
{
"extends": "../../../tsconfig.json",
"compilerOptions": {
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"rootDir": "."
},
"include": ["./**/*"],
"exclude": []
}

View File

@@ -15,12 +15,47 @@ export enum LogLevel {
SILENT = 4
}
export type Component = 'HOOK' | 'WORKER' | 'SDK' | 'PARSER' | 'DB' | 'SYSTEM' | 'HTTP' | 'SESSION' | 'CHROMA' | 'CHROMA_MCP' | 'CHROMA_SYNC' | 'FOLDER_INDEX' | 'CLAUDE_MD' | 'QUEUE' | 'TELEGRAM';
export type Component =
| 'AGENTS_MD'
| 'BRANCH'
| 'CHROMA'
| 'CHROMA_MCP'
| 'CHROMA_SYNC'
| 'CLAUDE_MD'
| 'CONFIG'
| 'CONSOLE'
| 'CURSOR'
| 'DB'
| 'DEDUP'
| 'ENV'
| 'FOLDER_INDEX'
| 'HOOK'
| 'HTTP'
| 'IMPORT'
| 'INGEST'
| 'OPENCLAW'
| 'OPENCODE'
| 'PARSER'
| 'PROCESS'
| 'PROJECT_NAME'
| 'QUEUE'
| 'SDK'
| 'SDK_SPAWN'
| 'SEARCH'
| 'SECURITY'
| 'SESSION'
| 'SETTINGS'
| 'SHUTDOWN'
| 'SYSTEM'
| 'TELEGRAM'
| 'TRANSCRIPT'
| 'WINDSURF'
| 'WORKER';
interface LogContext {
sessionId?: number;
sessionId?: string | number;
memorySessionId?: string;
correlationId?: string;
correlationId?: string | number;
[key: string]: any;
}

View File

@@ -15,7 +15,7 @@
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"types": ["node"],
"types": ["node", "bun"],
"allowSyntheticDefaultImports": true
},
"include": [
@@ -24,6 +24,7 @@
"exclude": [
"node_modules",
"dist",
"tests"
"tests",
"src/ui/viewer"
]
}