WIP: Claude Code progress on #31
Automated salvage commit — agent session ended (exit 124). Work in progress, may need continuation.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { Router, type Request, type Response } from "express";
|
||||
import { randomUUID, createHash } from "crypto";
|
||||
import { db, jobs, invoices, jobDebates, type Job } from "@workspace/db";
|
||||
import { eq, and } from "drizzle-orm";
|
||||
import { eq, and, desc } from "drizzle-orm";
|
||||
import { CreateJobBody, GetJobParams } from "@workspace/api-zod";
|
||||
import { lnbitsService } from "../lib/lnbits.js";
|
||||
import { agentService } from "../lib/agent.js";
|
||||
@@ -494,6 +494,67 @@ async function advanceJob(job: Job): Promise<Job | null> {
|
||||
return job;
|
||||
}
|
||||
|
||||
// ── GET /jobs ─────────────────────────────────────────────────────────────────
|
||||
// Returns the caller's completed/rejected job history (requires Nostr token).
|
||||
|
||||
router.get("/jobs", async (req: Request, res: Response) => {
|
||||
const header = req.headers["x-nostr-token"];
|
||||
const raw = typeof header === "string" ? header.trim() : null;
|
||||
if (!raw) {
|
||||
res.status(401).json({ error: "X-Nostr-Token header required" });
|
||||
return;
|
||||
}
|
||||
const parsed = trustService.verifyToken(raw);
|
||||
if (!parsed) {
|
||||
res.status(401).json({ error: "Invalid or expired token" });
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const rows = await db
|
||||
.select({
|
||||
id: jobs.id,
|
||||
request: jobs.request,
|
||||
state: jobs.state,
|
||||
workAmountSats: jobs.workAmountSats,
|
||||
actualAmountSats: jobs.actualAmountSats,
|
||||
result: jobs.result,
|
||||
rejectionReason: jobs.rejectionReason,
|
||||
freeTier: jobs.freeTier,
|
||||
absorbedSats: jobs.absorbedSats,
|
||||
createdAt: jobs.createdAt,
|
||||
updatedAt: jobs.updatedAt,
|
||||
})
|
||||
.from(jobs)
|
||||
.where(
|
||||
and(
|
||||
eq(jobs.nostrPubkey, parsed.pubkey),
|
||||
// Only terminal states are useful for history
|
||||
)
|
||||
)
|
||||
.orderBy(desc(jobs.createdAt))
|
||||
.limit(50);
|
||||
|
||||
res.json({ jobs: rows.map(j => ({
|
||||
id: j.id,
|
||||
request: j.request,
|
||||
state: j.state,
|
||||
costSats: j.actualAmountSats ?? j.workAmountSats ?? null,
|
||||
freeTier: j.freeTier,
|
||||
absorbedSats: j.absorbedSats ?? null,
|
||||
result: j.state === "complete" ? j.result : null,
|
||||
rejectionReason: j.state === "rejected" ? j.rejectionReason : null,
|
||||
createdAt: j.createdAt.toISOString(),
|
||||
completedAt: (j.state === "complete" || j.state === "rejected")
|
||||
? j.updatedAt.toISOString()
|
||||
: null,
|
||||
})) });
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : "Failed to fetch jobs";
|
||||
res.status(500).json({ error: message });
|
||||
}
|
||||
});
|
||||
|
||||
// ── POST /jobs ────────────────────────────────────────────────────────────────
|
||||
|
||||
// ── Resolve Nostr pubkey from token header or body ────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user