oh-my-llmwikimode 1.0.0
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/LICENSE +21 -0
- package/README.md +494 -0
- package/bin/llmwiki.js +1493 -0
- package/docs/INSTALLATION.md +228 -0
- package/docs/SCOPE_LOCK.md +79 -0
- package/docs/STAGE1_GUIDE.md +265 -0
- package/docs/STAGE2_AGENT_TEAM_GUIDE.md +141 -0
- package/docs/STAGE3_CONVERSATIONAL_GROWTH_GUIDE.md +50 -0
- package/docs/TEST_WORKSHEET.md +120 -0
- package/docs/github-private-bootstrap.md +53 -0
- package/docs/release.md +79 -0
- package/docs/stage4-slice1-manual-test.md +259 -0
- package/docs/stage4-slice1-user-guide.md +269 -0
- package/docs/user-guide-ko.md +452 -0
- package/package.json +76 -0
- package/scripts/install-llmwiki.ps1 +229 -0
- package/src/config.js +74 -0
- package/src/curator/browser-data.js +134 -0
- package/src/curator/queue.js +324 -0
- package/src/curator/schema.js +237 -0
- package/src/curator/scoring.js +83 -0
- package/src/hooks.js +199 -0
- package/src/librarian/schema.js +218 -0
- package/src/librarian/weekly-digest.js +478 -0
- package/src/security.js +127 -0
- package/src/server.js +860 -0
- package/src/stage4/graph-reasoning/analyzer.js +255 -0
- package/src/stage4/graph-reasoning/browser-data.js +130 -0
- package/src/stage4/graph-reasoning/index.js +35 -0
- package/src/stage4/graph-reasoning/loader.js +122 -0
- package/src/stage4/graph-reasoning/queue.js +154 -0
- package/src/stage4/graph-reasoning/schema.js +190 -0
- package/src/team/browser-data.js +142 -0
- package/src/team/capabilities.js +79 -0
- package/src/team/dispatch.js +108 -0
- package/src/team/queue.js +290 -0
- package/src/team/schema.js +225 -0
- package/src/team/shared-memory.js +183 -0
- package/src/todo/browser-data.js +71 -0
- package/src/todo/queue.js +159 -0
- package/src/todo/schema.js +90 -0
- package/src/utils/embedding-model.js +111 -0
- package/src/wiki/alias-suggestions.js +180 -0
- package/src/wiki/browser-data.js +284 -0
- package/src/wiki/doctor.js +218 -0
- package/src/wiki/entry-normalizer.js +139 -0
- package/src/wiki/ingest.js +443 -0
- package/src/wiki/lesson-proposal-analyzer.js +463 -0
- package/src/wiki/lesson-proposal-manager.js +331 -0
- package/src/wiki/lesson-template.js +182 -0
- package/src/wiki/lint.js +294 -0
- package/src/wiki/notebooklm-adapter.js +264 -0
- package/src/wiki/query.js +304 -0
- package/src/wiki/raw-manager.js +400 -0
- package/src/wiki/search-feedback.js +211 -0
- package/src/wiki/semantic-index.js +333 -0
- package/src/wiki/semantic-search.js +170 -0
- package/src/wiki/source-ledger.js +370 -0
- package/src/wiki/store.js +1329 -0
- package/src/wiki/usage-events.js +144 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import crypto from "node:crypto";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* B1 Agent School — Usage Event Contract
|
|
7
|
+
*
|
|
8
|
+
* Append-only usage events under .system/usage/{YYYY-MM-DD}.jsonl
|
|
9
|
+
* Schema: {version, ts, event, entry_path, source, query_hash, actor, review_required}
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export const USAGE_EVENT_VERSION = 1;
|
|
13
|
+
export const USAGE_EVENT_DIR = ".system/usage";
|
|
14
|
+
|
|
15
|
+
export const USAGE_EVENTS = {
|
|
16
|
+
LESSON_VIEWED: "lesson_viewed",
|
|
17
|
+
LESSON_REFERENCED: "lesson_referenced",
|
|
18
|
+
SEARCH_RESULT_USED: "search_result_used",
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
function formatDateKey(date) {
|
|
22
|
+
const d = new Date(date);
|
|
23
|
+
const year = d.getUTCFullYear();
|
|
24
|
+
const month = String(d.getUTCMonth() + 1).padStart(2, "0");
|
|
25
|
+
const day = String(d.getUTCDate()).padStart(2, "0");
|
|
26
|
+
return `${year}-${month}-${day}`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function getUsageFilePath(wikiRoot, date) {
|
|
30
|
+
const dateKey = formatDateKey(date);
|
|
31
|
+
return path.join(wikiRoot, USAGE_EVENT_DIR, `${dateKey}.jsonl`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function ensureUsageDir(wikiRoot) {
|
|
35
|
+
const dir = path.join(wikiRoot, USAGE_EVENT_DIR);
|
|
36
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
37
|
+
return dir;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function hashQuery(query) {
|
|
41
|
+
if (!query) return "";
|
|
42
|
+
return crypto.createHash("sha256").update(String(query)).digest("hex");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Append a usage event.
|
|
47
|
+
*
|
|
48
|
+
* @param {string} wikiRoot
|
|
49
|
+
* @param {Object} event
|
|
50
|
+
* @param {string} event.event - One of USAGE_EVENTS values
|
|
51
|
+
* @param {string} event.entry_path - Path to the entry (e.g., editorial/lessons/...)
|
|
52
|
+
* @param {string} [event.source="manual"] - Source: wiki_search, wiki_query, cli, manual
|
|
53
|
+
* @param {string} [event.query] - Original query text (will be hashed, never stored raw)
|
|
54
|
+
* @param {string} [event.actor="local"] - Actor identifier
|
|
55
|
+
* @param {Object} [options]
|
|
56
|
+
* @param {Date} [options.now] - Injected timestamp for determinism in tests
|
|
57
|
+
* @returns {{success: boolean, path?: string, error?: string}}
|
|
58
|
+
*/
|
|
59
|
+
export function appendUsageEvent(wikiRoot, event, options = {}) {
|
|
60
|
+
try {
|
|
61
|
+
ensureUsageDir(wikiRoot);
|
|
62
|
+
|
|
63
|
+
const eventType = String(event.event || "").trim();
|
|
64
|
+
if (!Object.values(USAGE_EVENTS).includes(eventType)) {
|
|
65
|
+
return { success: false, error: `Invalid event type: ${eventType}` };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const entryPath = String(event.entry_path || "").trim();
|
|
69
|
+
if (!entryPath) {
|
|
70
|
+
return { success: false, error: "entry_path is required" };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const now = options.now ? new Date(options.now) : new Date();
|
|
74
|
+
const record = {
|
|
75
|
+
version: USAGE_EVENT_VERSION,
|
|
76
|
+
ts: now.toISOString(),
|
|
77
|
+
event: eventType,
|
|
78
|
+
entry_path: entryPath,
|
|
79
|
+
source: String(event.source || "manual").trim(),
|
|
80
|
+
query_hash: hashQuery(event.query),
|
|
81
|
+
actor: String(event.actor || "local").trim(),
|
|
82
|
+
review_required: true,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const filePath = getUsageFilePath(wikiRoot, now);
|
|
86
|
+
const line = JSON.stringify(record);
|
|
87
|
+
fs.appendFileSync(filePath, `${line}\n`, { encoding: "utf-8" });
|
|
88
|
+
|
|
89
|
+
return { success: true, path: filePath, record };
|
|
90
|
+
} catch (error) {
|
|
91
|
+
return { success: false, error: error.message };
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Read usage events for a specific date.
|
|
97
|
+
*
|
|
98
|
+
* @param {string} wikiRoot
|
|
99
|
+
* @param {string|Date} [date] - Defaults to today
|
|
100
|
+
* @returns {{success: boolean, events?: Array, error?: string}}
|
|
101
|
+
*/
|
|
102
|
+
export function readUsageEvents(wikiRoot, date) {
|
|
103
|
+
try {
|
|
104
|
+
const targetDate = date ? new Date(date) : new Date();
|
|
105
|
+
const filePath = getUsageFilePath(wikiRoot, targetDate);
|
|
106
|
+
|
|
107
|
+
if (!fs.existsSync(filePath)) {
|
|
108
|
+
return { success: true, events: [] };
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const lines = fs
|
|
112
|
+
.readFileSync(filePath, "utf-8")
|
|
113
|
+
.split(/\r?\n/)
|
|
114
|
+
.filter(Boolean);
|
|
115
|
+
|
|
116
|
+
const events = [];
|
|
117
|
+
for (const line of lines) {
|
|
118
|
+
try {
|
|
119
|
+
events.push(JSON.parse(line));
|
|
120
|
+
} catch {
|
|
121
|
+
// Skip malformed lines
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return { success: true, events };
|
|
126
|
+
} catch (error) {
|
|
127
|
+
return { success: false, error: error.message };
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Get all usage event file paths.
|
|
133
|
+
*
|
|
134
|
+
* @param {string} wikiRoot
|
|
135
|
+
* @returns {string[]}
|
|
136
|
+
*/
|
|
137
|
+
export function listUsageEventFiles(wikiRoot) {
|
|
138
|
+
const dir = path.join(wikiRoot, USAGE_EVENT_DIR);
|
|
139
|
+
if (!fs.existsSync(dir)) return [];
|
|
140
|
+
return fs
|
|
141
|
+
.readdirSync(dir)
|
|
142
|
+
.filter((f) => f.endsWith(".jsonl"))
|
|
143
|
+
.sort();
|
|
144
|
+
}
|