Fix issues and add linting

This commit is contained in:
khalid@traclabs.com
2026-04-22 22:44:03 -05:00
parent 498d873c47
commit bcd047bc54
21 changed files with 10634 additions and 134 deletions

View File

@@ -13,12 +13,30 @@ import { logger } from '../logger.js';
const REPO_ROOT = process.env.REPO_ROOT || '.';
/**
* In-memory map from job ID → proposal ID.
* Used by the HTTP API to let the editor poll for a proposal created by a queued job.
* Entries are pruned after 15 minutes to avoid unbounded growth.
*/
export const jobProposalMap = new Map<string, { proposalId: string; createdAt: number }>();
const JOB_MAP_TTL_MS = 15 * 60 * 1000;
function pruneJobMap() {
const cutoff = Date.now() - JOB_MAP_TTL_MS;
for (const [key, entry] of jobProposalMap) {
if (entry.createdAt < cutoff) jobProposalMap.delete(key);
}
}
export async function processEditJob(job: EditJobPayload): Promise<void> {
if (job.kind === 'propose') {
await handlePropose(job);
} else if (job.kind === 'apply') {
await handleApply(job);
}
// Opportunistic cleanup
if (jobProposalMap.size > 100) pruneJobMap();
}
async function handlePropose(job: Extract<EditJobPayload, { kind: 'propose' }>) {
@@ -120,6 +138,9 @@ async function handlePropose(job: Extract<EditJobPayload, { kind: 'propose' }>)
phoneHash: job.smsReplyMeta?.from ? crypto.createHash('sha256').update(job.smsReplyMeta.from).digest('hex').slice(0, 16) : undefined,
});
// Record the job → proposal mapping so the HTTP API can find it
jobProposalMap.set(job.id, { proposalId, createdAt: Date.now() });
log.info({ event: 'proposal.created', proposalId, path: repoRelativePath }, 'Proposal created');
// Step 6: Notify user
@@ -127,18 +148,11 @@ async function handlePropose(job: Extract<EditJobPayload, { kind: 'propose' }>)
await sendSms(job.smsReplyMeta.from, job.smsReplyMeta.to, SMS_TEMPLATES.PROPOSAL_SUMMARY(summary, proposalId));
}
// For HTTP callers, the proposal_id is returned via the response (handled in route)
// Store on the job for the route handler to read
(job as Record<string, unknown>)._proposalId = proposalId;
(job as Record<string, unknown>)._summary = summary;
} catch (err) {
const msg = (err as Error).message;
log.error({ event: 'propose.failed', error: msg }, 'Propose failed');
log.error({ event: 'propose.failed', error: (err as Error).message }, 'Propose failed');
if (job.smsReplyMeta) {
const template = msg === 'LLM_UNAVAILABLE' ? SMS_TEMPLATES.LLM_UNAVAILABLE() : SMS_TEMPLATES.LLM_UNAVAILABLE();
await sendSms(job.smsReplyMeta.from, job.smsReplyMeta.to, template);
await sendSms(job.smsReplyMeta.from, job.smsReplyMeta.to, SMS_TEMPLATES.LLM_UNAVAILABLE());
}
}
}