Add `source` column to sessions and messages ('claude' | 'codex').
Discover and parse Codex JSONL files from ~/.codex/sessions/, mapping
Codex thread/item structures to the same schema (messages, tool_calls,
tool_results, subagents). Move DB to ~/.obelisk/ with legacy migration.
Add rebuild-to-temp-then-swap for safe full rebuilds. On the app side:
source filter toggle, collapsible untitled session fold, configurable
codexDir in Settings, and a dev script. Update SKILL.md and query
helpers to expose source fields and accept source filter opt.
61 lines
1.6 KiB
JavaScript
61 lines
1.6 KiB
JavaScript
const path = require('path');
|
|
const { Worker } = require('worker_threads');
|
|
|
|
function createWorkerBuildIndex({
|
|
workerPath = path.join(__dirname, 'indexer-worker.js'),
|
|
WorkerImpl = Worker,
|
|
} = {}) {
|
|
let worker = null;
|
|
let nextId = 1;
|
|
const pending = new Map();
|
|
|
|
const rejectPending = (error) => {
|
|
for (const { reject } of pending.values()) reject(error);
|
|
pending.clear();
|
|
};
|
|
|
|
const ensureWorker = () => {
|
|
if (worker) return worker;
|
|
worker = new WorkerImpl(workerPath);
|
|
worker.on('message', (message) => {
|
|
const current = pending.get(message.id);
|
|
if (!current) return;
|
|
pending.delete(message.id);
|
|
if (message.error) {
|
|
const error = new Error(message.error.message);
|
|
error.stack = message.error.stack;
|
|
current.reject(error);
|
|
} else {
|
|
current.resolve(message.result);
|
|
}
|
|
});
|
|
worker.on('error', (error) => {
|
|
rejectPending(error);
|
|
worker = null;
|
|
});
|
|
worker.on('exit', (code) => {
|
|
if (pending.size) rejectPending(new Error(`Indexer worker exited with code ${code}`));
|
|
worker = null;
|
|
});
|
|
return worker;
|
|
};
|
|
|
|
const buildIndex = (args = {}) => new Promise((resolve, reject) => {
|
|
const id = nextId++;
|
|
pending.set(id, { resolve, reject });
|
|
ensureWorker().postMessage({ id, args });
|
|
});
|
|
|
|
const stop = () => {
|
|
const current = worker;
|
|
worker = null;
|
|
const termination = current?.terminate ? Promise.resolve(current.terminate()) : Promise.resolve();
|
|
rejectPending(new Error('Indexer worker stopped'));
|
|
return termination;
|
|
};
|
|
|
|
return { buildIndex, stop };
|
|
}
|
|
|
|
module.exports = { createWorkerBuildIndex };
|