chapterhouse 0.9.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/korg.js +0 -17
- package/dist/api/route-coverage.test.js +1 -2
- package/dist/api/server.js +11 -13
- package/dist/shared/api-schemas.js +0 -3
- package/dist/store/db.js +1 -0
- package/dist/wiki/index-manager.js +1 -1
- package/package.json +1 -1
- package/web/dist/assets/{index-tBfBbEk5.js → index-iQrv3lQN.js} +74 -76
- package/web/dist/assets/{index-tBfBbEk5.js.map → index-iQrv3lQN.js.map} +1 -1
- package/web/dist/index.html +1 -1
- package/dist/api/korg.test.js +0 -42
package/dist/api/korg.js
CHANGED
|
@@ -1,20 +1,3 @@
|
|
|
1
|
-
import { sendToAgentSession } from "../copilot/orchestrator.js";
|
|
2
|
-
export async function routeKorgMessage(input) {
|
|
3
|
-
const message = input.message.trim();
|
|
4
|
-
const sessionId = input.sessionKey?.trim() || `korg-${Date.now()}`;
|
|
5
|
-
const sessionName = input.sessionKey?.trim() || message.slice(0, 80).trim() || sessionId;
|
|
6
|
-
const prompt = [
|
|
7
|
-
"Handle this request as Korg via the API.",
|
|
8
|
-
`Research session id: ${sessionId}`,
|
|
9
|
-
`Research session name: ${sessionName}`,
|
|
10
|
-
`When you ingest sources for this session, pass session_id: \"${sessionId}\" and session_name: \"${sessionName}\" to wiki_ingest_source.`,
|
|
11
|
-
"Reply directly to the user with the next best research action or synthesis.",
|
|
12
|
-
"",
|
|
13
|
-
message,
|
|
14
|
-
].join("\n");
|
|
15
|
-
const reply = await sendToAgentSession("korg", prompt);
|
|
16
|
-
return { ok: true, sessionKey: sessionId, reply };
|
|
17
|
-
}
|
|
18
1
|
export function listKorgResearchSessions(db) {
|
|
19
2
|
return db.prepare(`
|
|
20
3
|
SELECT
|
|
@@ -13,8 +13,7 @@
|
|
|
13
13
|
// POST /api/wiki/update — static auth guard tested below
|
|
14
14
|
// POST /api/wiki/page/pin — auth + traversal guard tested
|
|
15
15
|
// POST /api/wiki/ingest — NOT tested (add in Phase 3c)
|
|
16
|
-
// GET /api/wiki/korg/sessions —
|
|
17
|
-
// POST /api/wiki/korg — NOT tested (add in Phase 3c)
|
|
16
|
+
// GET /api/wiki/korg/sessions — tested (server.test.ts: grouped active sessions)
|
|
18
17
|
// ──────────────────────────────────────────────────────────────────────────────
|
|
19
18
|
import { describe, test } from "node:test";
|
|
20
19
|
import assert from "node:assert/strict";
|
package/dist/api/server.js
CHANGED
|
@@ -42,7 +42,7 @@ import { recordDecision } from "../memory/decisions.js";
|
|
|
42
42
|
import { upsertEntity } from "../memory/entities.js";
|
|
43
43
|
import { getInboxItem, listPendingInboxItems, resolveInboxItem } from "../memory/inbox.js";
|
|
44
44
|
import { ingestSource } from "../wiki/ingest.js";
|
|
45
|
-
import { listKorgResearchSessions
|
|
45
|
+
import { listKorgResearchSessions } from "./korg.js";
|
|
46
46
|
const log = childLogger("server");
|
|
47
47
|
const modeContext = new ModeContext(config);
|
|
48
48
|
void searchIndex; // re-exported by index-manager; reference here documents the dep
|
|
@@ -146,10 +146,6 @@ const prMergeHookSchema = z.object({
|
|
|
146
146
|
body: z.string().optional(),
|
|
147
147
|
files_changed: z.array(z.string()).optional(),
|
|
148
148
|
});
|
|
149
|
-
const korgRequestSchema = z.object({
|
|
150
|
-
message: requiredString("Missing 'message' in request body"),
|
|
151
|
-
sessionKey: z.string().trim().min(1).optional(),
|
|
152
|
-
}).strict();
|
|
153
149
|
const projectHardRulesSchema = z.object({
|
|
154
150
|
hardRules: z.object({
|
|
155
151
|
auto_pr: z.boolean({ error: "hardRules.auto_pr must be a boolean" }),
|
|
@@ -209,6 +205,13 @@ function coerceWikiPageUpdated(path, updated) {
|
|
|
209
205
|
function wikiPathToBrowserSlug(path) {
|
|
210
206
|
return path.replace(/^pages\//, "").replace(/\.md$/, "");
|
|
211
207
|
}
|
|
208
|
+
function entityTypeFromPath(path) {
|
|
209
|
+
const rest = path.startsWith("pages/") ? path.slice("pages/".length) : path;
|
|
210
|
+
const segs = rest.split("/").filter(Boolean);
|
|
211
|
+
if (segs.length <= 1)
|
|
212
|
+
return (segs[0] || "pages").replace(/\.md$/i, "");
|
|
213
|
+
return segs[0];
|
|
214
|
+
}
|
|
212
215
|
function normalizeOptionalQueryParam(value) {
|
|
213
216
|
if (typeof value !== "string") {
|
|
214
217
|
return undefined;
|
|
@@ -255,8 +258,8 @@ function listDbWikiBrowserPages(filters) {
|
|
|
255
258
|
const clauses = [];
|
|
256
259
|
const params = [];
|
|
257
260
|
if (filters.type) {
|
|
258
|
-
clauses.push("entity_type = ?");
|
|
259
|
-
params.push(filters.type);
|
|
261
|
+
clauses.push("(entity_type = ? OR (entity_type IS NULL AND path LIKE ?))");
|
|
262
|
+
params.push(filters.type, `pages/${filters.type}/%`);
|
|
260
263
|
}
|
|
261
264
|
if (filters.q) {
|
|
262
265
|
clauses.push("(title LIKE ? COLLATE NOCASE OR COALESCE(summary, '') LIKE ? COLLATE NOCASE)");
|
|
@@ -272,7 +275,7 @@ function listDbWikiBrowserPages(filters) {
|
|
|
272
275
|
slug: wikiPathToBrowserSlug(row.path),
|
|
273
276
|
title: row.title,
|
|
274
277
|
summary: row.summary ?? "",
|
|
275
|
-
type: row.entity_type ??
|
|
278
|
+
type: row.entity_type ?? entityTypeFromPath(row.path),
|
|
276
279
|
last_updated: coerceWikiPageUpdated(row.path, row.last_updated ?? undefined),
|
|
277
280
|
...(row.pinned ? { pinned: true } : {}),
|
|
278
281
|
}));
|
|
@@ -1742,11 +1745,6 @@ app.delete("/api/wiki/page", async (req, res) => {
|
|
|
1742
1745
|
const removed = await withWikiWrite(() => deletePage(path));
|
|
1743
1746
|
res.json({ ok: removed, path });
|
|
1744
1747
|
});
|
|
1745
|
-
app.post("/api/wiki/korg", authMiddleware, async (req, res) => {
|
|
1746
|
-
const body = parseRequest(korgRequestSchema, req.body ?? {});
|
|
1747
|
-
const result = await routeKorgMessage(body);
|
|
1748
|
-
res.json(result);
|
|
1749
|
-
});
|
|
1750
1748
|
app.get("/api/wiki/korg/sessions", authMiddleware, (_req, res) => {
|
|
1751
1749
|
res.json({ sessions: listKorgResearchSessions(getDb()) });
|
|
1752
1750
|
});
|
|
@@ -314,9 +314,6 @@ export const WikiPageUpdateResponseSchema = z.object({
|
|
|
314
314
|
page: WikiPageDetailSchema.shape.page.optional(),
|
|
315
315
|
pinned: z.boolean().optional(),
|
|
316
316
|
}).passthrough();
|
|
317
|
-
export const WikiKorgResponseSchema = z.object({
|
|
318
|
-
reply: z.string(),
|
|
319
|
-
}).passthrough();
|
|
320
317
|
export const WikiReingestResponseSchema = z.object({
|
|
321
318
|
ok: z.boolean(),
|
|
322
319
|
}).passthrough();
|
package/dist/store/db.js
CHANGED
|
@@ -551,6 +551,7 @@ export function getDb() {
|
|
|
551
551
|
ensureChapterhouseHome();
|
|
552
552
|
db = new Database(getDbPath());
|
|
553
553
|
db.pragma("journal_mode = WAL");
|
|
554
|
+
db.pragma("busy_timeout = 5000");
|
|
554
555
|
db.pragma("foreign_keys = ON");
|
|
555
556
|
db.exec(`
|
|
556
557
|
CREATE TABLE IF NOT EXISTS worker_sessions (
|
|
@@ -77,7 +77,7 @@ export function upsertWikiPage(path, frontmatter, summary) {
|
|
|
77
77
|
const db = getDb();
|
|
78
78
|
const normalizedPath = normalizeWikiPath(path);
|
|
79
79
|
const title = frontmatter.title ?? basenameTitle(normalizedPath);
|
|
80
|
-
const entityType = frontmatter.metadata?.["entity_type"] ??
|
|
80
|
+
const entityType = frontmatter.metadata?.["entity_type"] ?? categoryOfPath(normalizedPath);
|
|
81
81
|
const tags = JSON.stringify(frontmatter.tags ?? []);
|
|
82
82
|
const lastUpdated = frontmatter.updated ?? new Date().toISOString();
|
|
83
83
|
db.prepare(`
|
package/package.json
CHANGED