@goondocks/myco 0.3.0 → 0.3.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/dist/chunk-3JCXYLHD.js +33 -0
- package/dist/chunk-3JCXYLHD.js.map +1 -0
- package/dist/{chunk-QQWUV3TC.js → chunk-72OAG4SF.js} +2 -1
- package/dist/chunk-JIQISBPI.js +362 -0
- package/dist/chunk-JIQISBPI.js.map +1 -0
- package/dist/{cli-ZHUR53CS.js → cli-ERAS5H43.js} +5 -2
- package/dist/cli-ERAS5H43.js.map +1 -0
- package/dist/{main-JY6O6ZVH.js → main-D4X6XWRT.js} +215 -531
- package/dist/main-D4X6XWRT.js.map +1 -0
- package/dist/{rebuild-YAN3TPFB.js → rebuild-3367GP5R.js} +21 -14
- package/dist/rebuild-3367GP5R.js.map +1 -0
- package/dist/reprocess-EM5RIRH4.js +199 -0
- package/dist/reprocess-EM5RIRH4.js.map +1 -0
- package/dist/{server-DLBATUNG.js → server-I7MRMIOP.js} +14 -7
- package/dist/{server-DLBATUNG.js.map → server-I7MRMIOP.js.map} +1 -1
- package/dist/src/cli.js +1 -1
- package/dist/src/daemon/main.js +1 -1
- package/dist/src/mcp/server.js +1 -1
- package/package.json +1 -1
- package/skills/myco/SKILL.md +33 -0
- package/dist/cli-ZHUR53CS.js.map +0 -1
- package/dist/main-JY6O6ZVH.js.map +0 -1
- package/dist/rebuild-YAN3TPFB.js.map +0 -1
- /package/dist/{chunk-QQWUV3TC.js.map → chunk-72OAG4SF.js.map} +0 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
|
|
2
|
+
|
|
3
|
+
// src/intelligence/batch.ts
|
|
4
|
+
var LLM_BATCH_CONCURRENCY = 3;
|
|
5
|
+
var EMBEDDING_BATCH_CONCURRENCY = 4;
|
|
6
|
+
async function batchExecute(items, fn, options) {
|
|
7
|
+
const { concurrency, onProgress } = options;
|
|
8
|
+
let succeeded = 0;
|
|
9
|
+
let failed = 0;
|
|
10
|
+
const results = [];
|
|
11
|
+
for (let i = 0; i < items.length; i += concurrency) {
|
|
12
|
+
const batch = items.slice(i, i + concurrency);
|
|
13
|
+
const settled = await Promise.allSettled(batch.map(fn));
|
|
14
|
+
for (const result of settled) {
|
|
15
|
+
if (result.status === "fulfilled") {
|
|
16
|
+
succeeded++;
|
|
17
|
+
results.push({ status: "fulfilled", value: result.value });
|
|
18
|
+
} else {
|
|
19
|
+
failed++;
|
|
20
|
+
results.push({ status: "rejected", reason: result.reason?.message ?? String(result.reason) });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
onProgress?.(succeeded + failed, items.length);
|
|
24
|
+
}
|
|
25
|
+
return { succeeded, failed, results };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export {
|
|
29
|
+
LLM_BATCH_CONCURRENCY,
|
|
30
|
+
EMBEDDING_BATCH_CONCURRENCY,
|
|
31
|
+
batchExecute
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=chunk-3JCXYLHD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/intelligence/batch.ts"],"sourcesContent":["/**\n * Batch execution utilities for LLM and embedding operations.\n *\n * Provides concurrency-limited parallel execution for bulk operations\n * like reprocessing, rebuilding, and any future batch pipeline.\n */\n\n/** Default concurrency for LLM calls (heavier, single-threaded backends). */\nexport const LLM_BATCH_CONCURRENCY = 3;\n/** Default concurrency for embedding calls (lighter, can run more in parallel). */\nexport const EMBEDDING_BATCH_CONCURRENCY = 4;\n\nexport interface BatchResult<T> {\n succeeded: number;\n failed: number;\n results: Array<{ status: 'fulfilled'; value: T } | { status: 'rejected'; reason: string }>;\n}\n\n/**\n * Execute async tasks with a concurrency limit.\n * Reports progress via an optional callback.\n */\nexport async function batchExecute<I, O>(\n items: I[],\n fn: (item: I) => Promise<O>,\n options: {\n concurrency: number;\n onProgress?: (completed: number, total: number) => void;\n },\n): Promise<BatchResult<O>> {\n const { concurrency, onProgress } = options;\n let succeeded = 0;\n let failed = 0;\n const results: BatchResult<O>['results'] = [];\n\n for (let i = 0; i < items.length; i += concurrency) {\n const batch = items.slice(i, i + concurrency);\n const settled = await Promise.allSettled(batch.map(fn));\n\n for (const result of settled) {\n if (result.status === 'fulfilled') {\n succeeded++;\n results.push({ status: 'fulfilled', value: result.value });\n } else {\n failed++;\n results.push({ status: 'rejected', reason: (result.reason as Error)?.message ?? String(result.reason) });\n }\n }\n\n onProgress?.(succeeded + failed, items.length);\n }\n\n return { succeeded, failed, results };\n}\n"],"mappings":";;;AAQO,IAAM,wBAAwB;AAE9B,IAAM,8BAA8B;AAY3C,eAAsB,aACpB,OACA,IACA,SAIyB;AACzB,QAAM,EAAE,aAAa,WAAW,IAAI;AACpC,MAAI,YAAY;AAChB,MAAI,SAAS;AACb,QAAM,UAAqC,CAAC;AAE5C,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,aAAa;AAClD,UAAM,QAAQ,MAAM,MAAM,GAAG,IAAI,WAAW;AAC5C,UAAM,UAAU,MAAM,QAAQ,WAAW,MAAM,IAAI,EAAE,CAAC;AAEtD,eAAW,UAAU,SAAS;AAC5B,UAAI,OAAO,WAAW,aAAa;AACjC;AACA,gBAAQ,KAAK,EAAE,QAAQ,aAAa,OAAO,OAAO,MAAM,CAAC;AAAA,MAC3D,OAAO;AACL;AACA,gBAAQ,KAAK,EAAE,QAAQ,YAAY,QAAS,OAAO,QAAkB,WAAW,OAAO,OAAO,MAAM,EAAE,CAAC;AAAA,MACzG;AAAA,IACF;AAEA,iBAAa,YAAY,QAAQ,MAAM,MAAM;AAAA,EAC/C;AAEA,SAAO,EAAE,WAAW,QAAQ,QAAQ;AACtC;","names":[]}
|
|
@@ -3665,6 +3665,7 @@ function extractTitle(content) {
|
|
|
3665
3665
|
}
|
|
3666
3666
|
|
|
3667
3667
|
export {
|
|
3668
|
+
require_gray_matter,
|
|
3668
3669
|
PlanFrontmatterSchema,
|
|
3669
3670
|
ARTIFACT_TYPES,
|
|
3670
3671
|
indexNote,
|
|
@@ -3688,4 +3689,4 @@ strip-bom-string/index.js:
|
|
|
3688
3689
|
* Released under the MIT License.
|
|
3689
3690
|
*)
|
|
3690
3691
|
*/
|
|
3691
|
-
//# sourceMappingURL=chunk-
|
|
3692
|
+
//# sourceMappingURL=chunk-72OAG4SF.js.map
|
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
formatMemoryBody,
|
|
4
|
+
sessionNoteId
|
|
5
|
+
} from "./chunk-P2Q77C5F.js";
|
|
6
|
+
import {
|
|
7
|
+
ARTIFACT_TYPES,
|
|
8
|
+
indexNote
|
|
9
|
+
} from "./chunk-72OAG4SF.js";
|
|
10
|
+
import {
|
|
11
|
+
external_exports
|
|
12
|
+
} from "./chunk-ISCT2SI6.js";
|
|
13
|
+
import {
|
|
14
|
+
AgentRegistry
|
|
15
|
+
} from "./chunk-2QEJKG7R.js";
|
|
16
|
+
import {
|
|
17
|
+
AI_RESPONSE_PREVIEW_CHARS,
|
|
18
|
+
CANDIDATE_CONTENT_PREVIEW,
|
|
19
|
+
CHARS_PER_TOKEN,
|
|
20
|
+
CLASSIFICATION_MAX_TOKENS,
|
|
21
|
+
COMMAND_PREVIEW_CHARS,
|
|
22
|
+
EXTRACTION_MAX_TOKENS,
|
|
23
|
+
PROMPT_PREVIEW_CHARS,
|
|
24
|
+
SUMMARY_MAX_TOKENS,
|
|
25
|
+
TITLE_MAX_TOKENS
|
|
26
|
+
} from "./chunk-Q7BEFSOV.js";
|
|
27
|
+
|
|
28
|
+
// src/prompts/index.ts
|
|
29
|
+
import fs from "fs";
|
|
30
|
+
import path from "path";
|
|
31
|
+
import { fileURLToPath } from "url";
|
|
32
|
+
function resolvePromptsDir() {
|
|
33
|
+
let dir = path.dirname(fileURLToPath(import.meta.url));
|
|
34
|
+
for (let i = 0; i < 5; i++) {
|
|
35
|
+
if (fs.existsSync(path.join(dir, "package.json"))) {
|
|
36
|
+
return path.join(dir, "dist", "src", "prompts");
|
|
37
|
+
}
|
|
38
|
+
if (fs.existsSync(path.join(dir, "extraction.md"))) {
|
|
39
|
+
return dir;
|
|
40
|
+
}
|
|
41
|
+
dir = path.dirname(dir);
|
|
42
|
+
}
|
|
43
|
+
return path.dirname(fileURLToPath(import.meta.url));
|
|
44
|
+
}
|
|
45
|
+
var PROMPTS_DIR = resolvePromptsDir();
|
|
46
|
+
var promptCache = /* @__PURE__ */ new Map();
|
|
47
|
+
function loadPrompt(name) {
|
|
48
|
+
let cached = promptCache.get(name);
|
|
49
|
+
if (!cached) {
|
|
50
|
+
cached = fs.readFileSync(path.join(PROMPTS_DIR, `${name}.md`), "utf-8").trim();
|
|
51
|
+
promptCache.set(name, cached);
|
|
52
|
+
}
|
|
53
|
+
return cached;
|
|
54
|
+
}
|
|
55
|
+
function interpolate(template, vars) {
|
|
56
|
+
let result = template;
|
|
57
|
+
for (const [key, value] of Object.entries(vars)) {
|
|
58
|
+
result = result.replaceAll(`{{${key}}}`, value);
|
|
59
|
+
}
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
function buildExtractionPrompt(sessionId, eventCount, toolSummary) {
|
|
63
|
+
return interpolate(loadPrompt("extraction"), {
|
|
64
|
+
sessionId,
|
|
65
|
+
eventCount: String(eventCount),
|
|
66
|
+
toolSummary
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
function buildSummaryPrompt(sessionId, user, content) {
|
|
70
|
+
return interpolate(loadPrompt("summary"), {
|
|
71
|
+
sessionId,
|
|
72
|
+
user,
|
|
73
|
+
content
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
function buildTitlePrompt(summary, sessionId) {
|
|
77
|
+
return interpolate(loadPrompt("title"), {
|
|
78
|
+
summary,
|
|
79
|
+
sessionId
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
var ARTIFACT_TYPE_DESCRIPTIONS = [
|
|
83
|
+
'"spec" \u2014 Design specifications, architecture documents',
|
|
84
|
+
'"plan" \u2014 Implementation plans, roadmaps',
|
|
85
|
+
'"rfc" \u2014 Requests for comment, proposals',
|
|
86
|
+
'"doc" \u2014 Documentation, guides, READMEs',
|
|
87
|
+
'"other" \u2014 Other substantive documents'
|
|
88
|
+
];
|
|
89
|
+
function buildSimilarityPrompt(currentSummary, candidateSummary) {
|
|
90
|
+
return interpolate(loadPrompt("session-similarity"), {
|
|
91
|
+
currentSummary,
|
|
92
|
+
candidateSummary
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
function buildClassificationPrompt(sessionId, candidates) {
|
|
96
|
+
const fileList = candidates.map((c) => {
|
|
97
|
+
const truncated = c.content.slice(0, CANDIDATE_CONTENT_PREVIEW);
|
|
98
|
+
return `### ${c.path}
|
|
99
|
+
\`\`\`
|
|
100
|
+
${truncated}
|
|
101
|
+
\`\`\``;
|
|
102
|
+
}).join("\n\n");
|
|
103
|
+
return interpolate(loadPrompt("classification"), {
|
|
104
|
+
sessionId,
|
|
105
|
+
fileList,
|
|
106
|
+
artifactTypes: ARTIFACT_TYPE_DESCRIPTIONS.map((d) => `- ${d}`).join("\n"),
|
|
107
|
+
validTypes: ARTIFACT_TYPES.join("|")
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// src/intelligence/response.ts
|
|
112
|
+
var REASONING_PATTERNS = [
|
|
113
|
+
// <think>...</think>answer (DeepSeek, Qwen, GLM, many others)
|
|
114
|
+
/<think>[\s\S]*?<\/think>\s*/gi,
|
|
115
|
+
// Implicit opening: reasoning...</think>answer (GLM-4.7 observed)
|
|
116
|
+
/^[\s\S]*?<\/think>\s*/i,
|
|
117
|
+
// <reasoning>...</reasoning>answer
|
|
118
|
+
/<reasoning>[\s\S]*?<\/reasoning>\s*/gi,
|
|
119
|
+
// <|thinking|>...<|/thinking|>answer
|
|
120
|
+
/<\|thinking\|>[\s\S]*?<\|\/thinking\|>\s*/gi
|
|
121
|
+
];
|
|
122
|
+
function stripReasoningTokens(text) {
|
|
123
|
+
if (!text) return text;
|
|
124
|
+
for (const pattern of REASONING_PATTERNS) {
|
|
125
|
+
const stripped = text.replace(pattern, "").trim();
|
|
126
|
+
if (stripped && stripped !== text.trim()) {
|
|
127
|
+
return stripped;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return text;
|
|
131
|
+
}
|
|
132
|
+
function extractJson(text) {
|
|
133
|
+
const cleaned = stripReasoningTokens(text);
|
|
134
|
+
const fenceMatch = cleaned.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/);
|
|
135
|
+
if (fenceMatch) {
|
|
136
|
+
return JSON.parse(fenceMatch[1].trim());
|
|
137
|
+
}
|
|
138
|
+
const objectMatch = cleaned.match(/\{[\s\S]*\}/);
|
|
139
|
+
if (objectMatch) {
|
|
140
|
+
return JSON.parse(objectMatch[0]);
|
|
141
|
+
}
|
|
142
|
+
return JSON.parse(cleaned);
|
|
143
|
+
}
|
|
144
|
+
function extractNumber(text) {
|
|
145
|
+
const cleaned = stripReasoningTokens(text).trim();
|
|
146
|
+
const match = cleaned.match(/(\d+\.?\d*)/);
|
|
147
|
+
if (match) return parseFloat(match[1]);
|
|
148
|
+
return parseFloat(cleaned);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// src/daemon/processor.ts
|
|
152
|
+
var ClassificationResponseSchema = external_exports.object({
|
|
153
|
+
artifacts: external_exports.array(external_exports.object({
|
|
154
|
+
source_path: external_exports.string(),
|
|
155
|
+
artifact_type: external_exports.enum(ARTIFACT_TYPES),
|
|
156
|
+
title: external_exports.string(),
|
|
157
|
+
tags: external_exports.array(external_exports.string()).default([])
|
|
158
|
+
})).default([])
|
|
159
|
+
});
|
|
160
|
+
var BufferProcessor = class {
|
|
161
|
+
constructor(backend, contextWindow = 8192) {
|
|
162
|
+
this.backend = backend;
|
|
163
|
+
this.contextWindow = contextWindow;
|
|
164
|
+
}
|
|
165
|
+
truncateForContext(data, maxTokens) {
|
|
166
|
+
const available = this.contextWindow - maxTokens;
|
|
167
|
+
const dataTokens = Math.ceil(data.length / CHARS_PER_TOKEN);
|
|
168
|
+
if (dataTokens <= available) return data;
|
|
169
|
+
const charBudget = available * CHARS_PER_TOKEN;
|
|
170
|
+
return data.slice(0, charBudget);
|
|
171
|
+
}
|
|
172
|
+
async process(events, sessionId) {
|
|
173
|
+
const rawPrompt = this.buildPromptForExtraction(events, sessionId);
|
|
174
|
+
const prompt = this.truncateForContext(rawPrompt, EXTRACTION_MAX_TOKENS);
|
|
175
|
+
try {
|
|
176
|
+
const response = await this.backend.summarize(prompt, { maxTokens: EXTRACTION_MAX_TOKENS });
|
|
177
|
+
const parsed = extractJson(response.text);
|
|
178
|
+
return {
|
|
179
|
+
summary: parsed.summary,
|
|
180
|
+
observations: parsed.observations ?? [],
|
|
181
|
+
degraded: false
|
|
182
|
+
};
|
|
183
|
+
} catch (error) {
|
|
184
|
+
return {
|
|
185
|
+
summary: `LLM processing failed for session ${sessionId}. ${events.length} events captured. Error: ${error.message}`,
|
|
186
|
+
observations: [],
|
|
187
|
+
degraded: true
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
buildPromptForExtraction(events, sessionId) {
|
|
192
|
+
const toolSummary = this.summarizeEvents(events);
|
|
193
|
+
return buildExtractionPrompt(sessionId, events.length, toolSummary);
|
|
194
|
+
}
|
|
195
|
+
async summarizeSession(conversationMarkdown, sessionId, user) {
|
|
196
|
+
const truncatedContent = this.truncateForContext(conversationMarkdown, SUMMARY_MAX_TOKENS);
|
|
197
|
+
const summaryPrompt = buildSummaryPrompt(sessionId, user ?? "unknown", truncatedContent);
|
|
198
|
+
let summaryText;
|
|
199
|
+
try {
|
|
200
|
+
const response = await this.backend.summarize(summaryPrompt, { maxTokens: SUMMARY_MAX_TOKENS });
|
|
201
|
+
summaryText = stripReasoningTokens(response.text);
|
|
202
|
+
} catch (error) {
|
|
203
|
+
summaryText = `Session ${sessionId} \u2014 summarization failed: ${error.message}`;
|
|
204
|
+
}
|
|
205
|
+
const titlePrompt = buildTitlePrompt(summaryText, sessionId);
|
|
206
|
+
let title;
|
|
207
|
+
try {
|
|
208
|
+
const response = await this.backend.summarize(titlePrompt, { maxTokens: TITLE_MAX_TOKENS });
|
|
209
|
+
title = stripReasoningTokens(response.text).trim();
|
|
210
|
+
} catch {
|
|
211
|
+
title = `Session ${sessionId}`;
|
|
212
|
+
}
|
|
213
|
+
return { summary: summaryText, title };
|
|
214
|
+
}
|
|
215
|
+
async classifyArtifacts(candidates, sessionId) {
|
|
216
|
+
if (candidates.length === 0) return [];
|
|
217
|
+
const prompt = this.buildPromptForClassification(candidates, sessionId);
|
|
218
|
+
const response = await this.backend.summarize(prompt, { maxTokens: CLASSIFICATION_MAX_TOKENS });
|
|
219
|
+
const raw = extractJson(response.text);
|
|
220
|
+
const parsed = ClassificationResponseSchema.parse(raw);
|
|
221
|
+
return parsed.artifacts;
|
|
222
|
+
}
|
|
223
|
+
buildPromptForClassification(candidates, sessionId) {
|
|
224
|
+
return buildClassificationPrompt(sessionId, candidates);
|
|
225
|
+
}
|
|
226
|
+
summarizeEvents(events) {
|
|
227
|
+
const toolCounts = /* @__PURE__ */ new Map();
|
|
228
|
+
const filesAccessed = /* @__PURE__ */ new Set();
|
|
229
|
+
const prompts = [];
|
|
230
|
+
const aiResponses = [];
|
|
231
|
+
for (const event of events) {
|
|
232
|
+
if (event.type === "user_prompt") {
|
|
233
|
+
const prompt = String(event.prompt ?? "");
|
|
234
|
+
if (prompt) prompts.push(prompt.slice(0, PROMPT_PREVIEW_CHARS));
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
if (event.type === "ai_response") {
|
|
238
|
+
const content = String(event.content ?? "");
|
|
239
|
+
if (content) aiResponses.push(content.slice(0, AI_RESPONSE_PREVIEW_CHARS));
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
const tool = String(event.tool_name ?? event.tool ?? "unknown");
|
|
243
|
+
toolCounts.set(tool, (toolCounts.get(tool) ?? 0) + 1);
|
|
244
|
+
const input = event.tool_input ?? event.input;
|
|
245
|
+
if (input?.path) filesAccessed.add(String(input.path));
|
|
246
|
+
if (input?.file_path) filesAccessed.add(String(input.file_path));
|
|
247
|
+
if (input?.command) filesAccessed.add(`[cmd] ${String(input.command).slice(0, COMMAND_PREVIEW_CHARS)}`);
|
|
248
|
+
}
|
|
249
|
+
const lines = [];
|
|
250
|
+
if (prompts.length > 0) {
|
|
251
|
+
lines.push("### User Prompts");
|
|
252
|
+
for (const p of prompts) {
|
|
253
|
+
lines.push(`- "${p}"`);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
lines.push("\n### Tool Usage");
|
|
257
|
+
for (const [tool, count] of toolCounts) {
|
|
258
|
+
lines.push(`- ${tool}: ${count} calls`);
|
|
259
|
+
}
|
|
260
|
+
if (filesAccessed.size > 0) {
|
|
261
|
+
lines.push("\n### Files Accessed");
|
|
262
|
+
for (const file of filesAccessed) {
|
|
263
|
+
lines.push(`- ${file}`);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
if (aiResponses.length > 0) {
|
|
267
|
+
lines.push("\n### AI Responses");
|
|
268
|
+
for (const r of aiResponses) {
|
|
269
|
+
lines.push(`- "${r}"`);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return lines.join("\n");
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
// src/capture/transcript-miner.ts
|
|
277
|
+
var TranscriptMiner = class {
|
|
278
|
+
registry;
|
|
279
|
+
constructor(config) {
|
|
280
|
+
this.registry = new AgentRegistry(config?.additionalAdapters);
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Extract all conversation turns for a session.
|
|
284
|
+
* Convenience wrapper — delegates to getAllTurnsWithSource.
|
|
285
|
+
*/
|
|
286
|
+
getAllTurns(sessionId) {
|
|
287
|
+
return this.getAllTurnsWithSource(sessionId).turns;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Extract turns using the hook-provided transcript path first (fast, no scanning),
|
|
291
|
+
* then fall back to adapter registry scanning if the path isn't provided.
|
|
292
|
+
*/
|
|
293
|
+
getAllTurnsWithSource(sessionId, transcriptPath) {
|
|
294
|
+
if (transcriptPath) {
|
|
295
|
+
const result2 = this.registry.parseTurnsFromPath(transcriptPath);
|
|
296
|
+
if (result2) return result2;
|
|
297
|
+
}
|
|
298
|
+
const result = this.registry.getTranscriptTurns(sessionId);
|
|
299
|
+
if (result) return result;
|
|
300
|
+
return { turns: [], source: "none" };
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
function extractTurnsFromBuffer(events) {
|
|
304
|
+
const turns = [];
|
|
305
|
+
let current = null;
|
|
306
|
+
for (const event of events) {
|
|
307
|
+
const type = event.type;
|
|
308
|
+
if (type === "user_prompt") {
|
|
309
|
+
if (current) turns.push(current);
|
|
310
|
+
current = {
|
|
311
|
+
prompt: String(event.prompt ?? "").slice(0, PROMPT_PREVIEW_CHARS),
|
|
312
|
+
toolCount: 0,
|
|
313
|
+
timestamp: String(event.timestamp ?? (/* @__PURE__ */ new Date()).toISOString())
|
|
314
|
+
};
|
|
315
|
+
} else if (type === "tool_use") {
|
|
316
|
+
if (current) current.toolCount++;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
if (current) turns.push(current);
|
|
320
|
+
return turns;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// src/vault/observations.ts
|
|
324
|
+
function writeObservationNotes(observations, sessionId, writer, index, vaultDir) {
|
|
325
|
+
const results = [];
|
|
326
|
+
for (const obs of observations) {
|
|
327
|
+
const obsId = `${obs.type}-${sessionId.slice(-6)}-${Date.now()}`;
|
|
328
|
+
const body = formatMemoryBody({
|
|
329
|
+
title: obs.title,
|
|
330
|
+
observationType: obs.type,
|
|
331
|
+
content: obs.content,
|
|
332
|
+
sessionId,
|
|
333
|
+
root_cause: obs.root_cause,
|
|
334
|
+
fix: obs.fix,
|
|
335
|
+
rationale: obs.rationale,
|
|
336
|
+
alternatives_rejected: obs.alternatives_rejected,
|
|
337
|
+
gained: obs.gained,
|
|
338
|
+
sacrificed: obs.sacrificed,
|
|
339
|
+
tags: obs.tags
|
|
340
|
+
});
|
|
341
|
+
const relativePath = writer.writeMemory({
|
|
342
|
+
id: obsId,
|
|
343
|
+
observation_type: obs.type,
|
|
344
|
+
session: sessionNoteId(sessionId),
|
|
345
|
+
tags: obs.tags,
|
|
346
|
+
content: body
|
|
347
|
+
});
|
|
348
|
+
indexNote(index, vaultDir, relativePath);
|
|
349
|
+
results.push({ id: obsId, path: relativePath, observation: obs });
|
|
350
|
+
}
|
|
351
|
+
return results;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
export {
|
|
355
|
+
buildSimilarityPrompt,
|
|
356
|
+
extractNumber,
|
|
357
|
+
BufferProcessor,
|
|
358
|
+
TranscriptMiner,
|
|
359
|
+
extractTurnsFromBuffer,
|
|
360
|
+
writeObservationNotes
|
|
361
|
+
};
|
|
362
|
+
//# sourceMappingURL=chunk-JIQISBPI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/prompts/index.ts","../src/intelligence/response.ts","../src/daemon/processor.ts","../src/capture/transcript-miner.ts","../src/vault/observations.ts"],"sourcesContent":["/**\n * Prompt loader — reads .md templates from disk and interpolates variables.\n * Prompts are markdown files in this directory, not TypeScript strings.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { ARTIFACT_TYPES } from '../vault/types.js';\nimport { CANDIDATE_CONTENT_PREVIEW } from '../constants.js';\n\n/**\n * Resolve the prompts directory. With tsup code-splitting, import.meta.url\n * points to a chunk file (dist/chunk-XXXX.js), not dist/src/prompts/.\n * Walk up from the current file to find package.json, then use dist/src/prompts/.\n */\nfunction resolvePromptsDir(): string {\n let dir = path.dirname(fileURLToPath(import.meta.url));\n for (let i = 0; i < 5; i++) {\n if (fs.existsSync(path.join(dir, 'package.json'))) {\n return path.join(dir, 'dist', 'src', 'prompts');\n }\n // Also check if we're already in the right place (tsc output or dev mode)\n if (fs.existsSync(path.join(dir, 'extraction.md'))) {\n return dir;\n }\n dir = path.dirname(dir);\n }\n // Final fallback: adjacent to current file (works with tsc)\n return path.dirname(fileURLToPath(import.meta.url));\n}\n\nconst PROMPTS_DIR = resolvePromptsDir();\n\nconst promptCache = new Map<string, string>();\n\nfunction loadPrompt(name: string): string {\n let cached = promptCache.get(name);\n if (!cached) {\n cached = fs.readFileSync(path.join(PROMPTS_DIR, `${name}.md`), 'utf-8').trim();\n promptCache.set(name, cached);\n }\n return cached;\n}\n\nfunction interpolate(template: string, vars: Record<string, string>): string {\n let result = template;\n for (const [key, value] of Object.entries(vars)) {\n result = result.replaceAll(`{{${key}}}`, value);\n }\n return result;\n}\n\n// --- Prompt builders ---\n\nexport function buildExtractionPrompt(\n sessionId: string,\n eventCount: number,\n toolSummary: string,\n): string {\n return interpolate(loadPrompt('extraction'), {\n sessionId,\n eventCount: String(eventCount),\n toolSummary,\n });\n}\n\nexport function buildSummaryPrompt(\n sessionId: string,\n user: string,\n content: string,\n): string {\n return interpolate(loadPrompt('summary'), {\n sessionId,\n user,\n content,\n });\n}\n\nexport function buildTitlePrompt(\n summary: string,\n sessionId: string,\n): string {\n return interpolate(loadPrompt('title'), {\n summary,\n sessionId,\n });\n}\n\nconst ARTIFACT_TYPE_DESCRIPTIONS = [\n '\"spec\" — Design specifications, architecture documents',\n '\"plan\" — Implementation plans, roadmaps',\n '\"rfc\" — Requests for comment, proposals',\n '\"doc\" — Documentation, guides, READMEs',\n '\"other\" — Other substantive documents',\n];\n\nexport function buildSimilarityPrompt(\n currentSummary: string,\n candidateSummary: string,\n): string {\n return interpolate(loadPrompt('session-similarity'), {\n currentSummary,\n candidateSummary,\n });\n}\n\nexport function buildClassificationPrompt(\n sessionId: string,\n candidates: Array<{ path: string; content: string }>,\n): string {\n const fileList = candidates\n .map((c) => {\n const truncated = c.content.slice(0, CANDIDATE_CONTENT_PREVIEW);\n return `### ${c.path}\\n\\`\\`\\`\\n${truncated}\\n\\`\\`\\``;\n })\n .join('\\n\\n');\n\n return interpolate(loadPrompt('classification'), {\n sessionId,\n fileList,\n artifactTypes: ARTIFACT_TYPE_DESCRIPTIONS.map((d) => `- ${d}`).join('\\n'),\n validTypes: ARTIFACT_TYPES.join('|'),\n });\n}\n","/**\n * Clean LLM response text before parsing.\n *\n * Reasoning models (DeepSeek, Qwen, GLM, etc.) embed chain-of-thought\n * in the response using special tags. These must be stripped before\n * JSON parsing or value extraction.\n */\n\n// Patterns for reasoning model chain-of-thought tokens.\n// Order matters: most specific patterns first.\nconst REASONING_PATTERNS = [\n // <think>...</think>answer (DeepSeek, Qwen, GLM, many others)\n /<think>[\\s\\S]*?<\\/think>\\s*/gi,\n // Implicit opening: reasoning...</think>answer (GLM-4.7 observed)\n /^[\\s\\S]*?<\\/think>\\s*/i,\n // <reasoning>...</reasoning>answer\n /<reasoning>[\\s\\S]*?<\\/reasoning>\\s*/gi,\n // <|thinking|>...<|/thinking|>answer\n /<\\|thinking\\|>[\\s\\S]*?<\\|\\/thinking\\|>\\s*/gi,\n];\n\n/**\n * Strip reasoning/chain-of-thought tokens from LLM response text.\n * Returns the final answer without the thinking process.\n */\nexport function stripReasoningTokens(text: string): string {\n if (!text) return text;\n\n for (const pattern of REASONING_PATTERNS) {\n const stripped = text.replace(pattern, '').trim();\n if (stripped && stripped !== text.trim()) {\n return stripped;\n }\n }\n\n return text;\n}\n\n/**\n * Extract JSON from an LLM response that may contain markdown fences,\n * reasoning tokens, or other wrapper text.\n *\n * Tries in order:\n * 1. Strip reasoning tokens\n * 2. Extract from ```json ... ``` code fences\n * 3. Find bare {...} JSON object\n * 4. Parse the cleaned text directly\n */\nexport function extractJson(text: string): unknown {\n const cleaned = stripReasoningTokens(text);\n\n // Try code fence extraction\n const fenceMatch = cleaned.match(/```(?:json)?\\s*\\n?([\\s\\S]*?)\\n?```/);\n if (fenceMatch) {\n return JSON.parse(fenceMatch[1].trim());\n }\n\n // Try bare JSON object\n const objectMatch = cleaned.match(/\\{[\\s\\S]*\\}/);\n if (objectMatch) {\n return JSON.parse(objectMatch[0]);\n }\n\n // Try direct parse\n return JSON.parse(cleaned);\n}\n\n/**\n * Extract a numeric value from an LLM response that may contain\n * reasoning tokens or extra text around the number.\n */\nexport function extractNumber(text: string): number {\n const cleaned = stripReasoningTokens(text).trim();\n const match = cleaned.match(/(\\d+\\.?\\d*)/);\n if (match) return parseFloat(match[1]);\n return parseFloat(cleaned);\n}\n","import { z } from 'zod';\nimport type { LlmProvider } from '../intelligence/llm.js';\nimport { ARTIFACT_TYPES } from '../vault/types.js';\nimport { CHARS_PER_TOKEN, EXTRACTION_MAX_TOKENS, SUMMARY_MAX_TOKENS, TITLE_MAX_TOKENS, CLASSIFICATION_MAX_TOKENS, PROMPT_PREVIEW_CHARS, AI_RESPONSE_PREVIEW_CHARS, COMMAND_PREVIEW_CHARS } from '../constants.js';\nimport type { ObservationType, ArtifactType } from '../vault/types.js';\nimport { buildExtractionPrompt, buildSummaryPrompt, buildTitlePrompt, buildClassificationPrompt } from '../prompts/index.js';\nimport { extractJson, stripReasoningTokens } from '../intelligence/response.js';\n\nexport interface Observation {\n type: ObservationType;\n title: string;\n content: string;\n tags: string[];\n root_cause?: string;\n fix?: string;\n rationale?: string;\n alternatives_rejected?: string;\n gained?: string;\n sacrificed?: string;\n}\n\nexport interface ProcessorResult {\n summary: string;\n observations: Observation[];\n degraded: boolean;\n}\n\nexport interface ClassifiedArtifact {\n source_path: string;\n artifact_type: ArtifactType;\n title: string;\n tags: string[];\n}\n\nconst ClassificationResponseSchema = z.object({\n artifacts: z.array(z.object({\n source_path: z.string(),\n artifact_type: z.enum(ARTIFACT_TYPES),\n title: z.string(),\n tags: z.array(z.string()).default([]),\n })).default([]),\n});\n\nexport class BufferProcessor {\n constructor(private backend: LlmProvider, private contextWindow: number = 8192) {}\n\n private truncateForContext(data: string, maxTokens: number): string {\n const available = this.contextWindow - maxTokens;\n const dataTokens = Math.ceil(data.length / CHARS_PER_TOKEN);\n if (dataTokens <= available) return data;\n const charBudget = available * CHARS_PER_TOKEN;\n return data.slice(0, charBudget);\n }\n\n async process(\n events: Array<Record<string, unknown>>,\n sessionId: string,\n ): Promise<ProcessorResult> {\n const rawPrompt = this.buildPromptForExtraction(events, sessionId);\n const prompt = this.truncateForContext(rawPrompt, EXTRACTION_MAX_TOKENS);\n\n try {\n const response = await this.backend.summarize(prompt, { maxTokens: EXTRACTION_MAX_TOKENS });\n const parsed = extractJson(response.text) as {\n summary: string;\n observations: Observation[];\n };\n\n return {\n summary: parsed.summary,\n observations: parsed.observations ?? [],\n degraded: false,\n };\n } catch (error) {\n return {\n summary: `LLM processing failed for session ${sessionId}. ${events.length} events captured. Error: ${(error as Error).message}`,\n observations: [],\n degraded: true,\n };\n }\n }\n\n private buildPromptForExtraction(\n events: Array<Record<string, unknown>>,\n sessionId: string,\n ): string {\n const toolSummary = this.summarizeEvents(events);\n return buildExtractionPrompt(sessionId, events.length, toolSummary);\n }\n\n async summarizeSession(\n conversationMarkdown: string,\n sessionId: string,\n user?: string,\n ): Promise<{ summary: string; title: string }> {\n const truncatedContent = this.truncateForContext(conversationMarkdown, SUMMARY_MAX_TOKENS);\n const summaryPrompt = buildSummaryPrompt(sessionId, user ?? 'unknown', truncatedContent);\n\n let summaryText: string;\n try {\n const response = await this.backend.summarize(summaryPrompt, { maxTokens: SUMMARY_MAX_TOKENS });\n summaryText = stripReasoningTokens(response.text);\n } catch (error) {\n summaryText = `Session ${sessionId} — summarization failed: ${(error as Error).message}`;\n }\n\n const titlePrompt = buildTitlePrompt(summaryText, sessionId);\n let title: string;\n try {\n const response = await this.backend.summarize(titlePrompt, { maxTokens: TITLE_MAX_TOKENS });\n title = stripReasoningTokens(response.text).trim();\n } catch {\n title = `Session ${sessionId}`;\n }\n\n return { summary: summaryText, title };\n }\n\n async classifyArtifacts(\n candidates: Array<{ path: string; content: string }>,\n sessionId: string,\n ): Promise<ClassifiedArtifact[]> {\n if (candidates.length === 0) return [];\n\n const prompt = this.buildPromptForClassification(candidates, sessionId);\n const response = await this.backend.summarize(prompt, { maxTokens: CLASSIFICATION_MAX_TOKENS });\n const raw = extractJson(response.text);\n const parsed = ClassificationResponseSchema.parse(raw);\n return parsed.artifacts;\n }\n\n private buildPromptForClassification(\n candidates: Array<{ path: string; content: string }>,\n sessionId: string,\n ): string {\n return buildClassificationPrompt(sessionId, candidates);\n }\n\n private summarizeEvents(events: Array<Record<string, unknown>>): string {\n const toolCounts = new Map<string, number>();\n const filesAccessed = new Set<string>();\n const prompts: string[] = [];\n const aiResponses: string[] = [];\n\n for (const event of events) {\n if (event.type === 'user_prompt') {\n const prompt = String(event.prompt ?? '');\n if (prompt) prompts.push(prompt.slice(0, PROMPT_PREVIEW_CHARS));\n continue;\n }\n\n if (event.type === 'ai_response') {\n const content = String(event.content ?? '');\n if (content) aiResponses.push(content.slice(0, AI_RESPONSE_PREVIEW_CHARS));\n continue;\n }\n\n // Hooks send tool_name/tool_input; also support legacy tool/input\n const tool = String(event.tool_name ?? event.tool ?? 'unknown');\n toolCounts.set(tool, (toolCounts.get(tool) ?? 0) + 1);\n\n const input = (event.tool_input ?? event.input) as Record<string, unknown> | undefined;\n if (input?.path) filesAccessed.add(String(input.path));\n if (input?.file_path) filesAccessed.add(String(input.file_path));\n if (input?.command) filesAccessed.add(`[cmd] ${String(input.command).slice(0, COMMAND_PREVIEW_CHARS)}`);\n }\n\n const lines: string[] = [];\n\n if (prompts.length > 0) {\n lines.push('### User Prompts');\n for (const p of prompts) {\n lines.push(`- \"${p}\"`);\n }\n }\n\n lines.push('\\n### Tool Usage');\n for (const [tool, count] of toolCounts) {\n lines.push(`- ${tool}: ${count} calls`);\n }\n\n if (filesAccessed.size > 0) {\n lines.push('\\n### Files Accessed');\n for (const file of filesAccessed) {\n lines.push(`- ${file}`);\n }\n }\n\n if (aiResponses.length > 0) {\n lines.push('\\n### AI Responses');\n for (const r of aiResponses) {\n lines.push(`- \"${r}\"`);\n }\n }\n\n return lines.join('\\n');\n }\n}\n","import { AgentRegistry } from '../agents/registry.js';\nimport type { AgentAdapter } from '../agents/adapter.js';\nimport { PROMPT_PREVIEW_CHARS } from '../constants.js';\nimport fs from 'node:fs';\n\n// Re-export TranscriptTurn from its canonical home in agents/adapter.ts\nexport type { TranscriptTurn } from '../agents/adapter.js';\nimport type { TranscriptTurn } from '../agents/adapter.js';\n\ninterface TranscriptConfig {\n /** Additional agent adapters to register (useful for testing or custom agents) */\n additionalAdapters?: AgentAdapter[];\n}\n\nexport class TranscriptMiner {\n private registry: AgentRegistry;\n\n constructor(config?: TranscriptConfig) {\n this.registry = new AgentRegistry(config?.additionalAdapters);\n }\n\n /**\n * Extract all conversation turns for a session.\n * Convenience wrapper — delegates to getAllTurnsWithSource.\n */\n getAllTurns(sessionId: string): TranscriptTurn[] {\n return this.getAllTurnsWithSource(sessionId).turns;\n }\n\n /**\n * Extract turns using the hook-provided transcript path first (fast, no scanning),\n * then fall back to adapter registry scanning if the path isn't provided.\n */\n getAllTurnsWithSource(sessionId: string, transcriptPath?: string): { turns: TranscriptTurn[]; source: string } {\n // Primary: use the path provided by the hook (no directory scanning needed)\n if (transcriptPath) {\n const result = this.registry.parseTurnsFromPath(transcriptPath);\n if (result) return result;\n }\n\n // Fallback: scan known agent directories\n const result = this.registry.getTranscriptTurns(sessionId);\n if (result) return result;\n return { turns: [], source: 'none' };\n }\n}\n\n/**\n * Build turns from buffer events — the fallback when no agent transcript is available.\n * Buffer events come from hooks (user_prompt, tool_use) and lack AI responses.\n * Turns will have prompts and tool counts but no aiResponse.\n */\nexport function extractTurnsFromBuffer(events: Array<Record<string, unknown>>): TranscriptTurn[] {\n const turns: TranscriptTurn[] = [];\n let current: TranscriptTurn | null = null;\n\n for (const event of events) {\n const type = event.type as string;\n if (type === 'user_prompt') {\n if (current) turns.push(current);\n current = {\n prompt: String(event.prompt ?? '').slice(0, PROMPT_PREVIEW_CHARS),\n toolCount: 0,\n timestamp: String(event.timestamp ?? new Date().toISOString()),\n };\n } else if (type === 'tool_use') {\n if (current) current.toolCount++;\n }\n }\n if (current) turns.push(current);\n return turns;\n}\n","import { formatMemoryBody } from '../obsidian/formatter.js';\nimport { sessionNoteId } from './session-id.js';\nimport { indexNote } from '../index/rebuild.js';\nimport type { Observation } from '../daemon/processor.js';\nimport type { VaultWriter } from './writer.js';\nimport type { MycoIndex } from '../index/sqlite.js';\n\nexport interface WrittenNote {\n id: string;\n path: string;\n observation: Observation;\n}\n\nexport function writeObservationNotes(\n observations: Observation[],\n sessionId: string,\n writer: VaultWriter,\n index: MycoIndex,\n vaultDir: string,\n): WrittenNote[] {\n const results: WrittenNote[] = [];\n\n for (const obs of observations) {\n const obsId = `${obs.type}-${sessionId.slice(-6)}-${Date.now()}`;\n const body = formatMemoryBody({\n title: obs.title,\n observationType: obs.type,\n content: obs.content,\n sessionId,\n root_cause: obs.root_cause,\n fix: obs.fix,\n rationale: obs.rationale,\n alternatives_rejected: obs.alternatives_rejected,\n gained: obs.gained,\n sacrificed: obs.sacrificed,\n tags: obs.tags,\n });\n const relativePath = writer.writeMemory({\n id: obsId,\n observation_type: obs.type,\n session: sessionNoteId(sessionId),\n tags: obs.tags,\n content: body,\n });\n indexNote(index, vaultDir, relativePath);\n results.push({ id: obsId, path: relativePath, observation: obs });\n }\n\n return results;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAS9B,SAAS,oBAA4B;AACnC,MAAI,MAAM,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC;AACrD,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,QAAI,GAAG,WAAW,KAAK,KAAK,KAAK,cAAc,CAAC,GAAG;AACjD,aAAO,KAAK,KAAK,KAAK,QAAQ,OAAO,SAAS;AAAA,IAChD;AAEA,QAAI,GAAG,WAAW,KAAK,KAAK,KAAK,eAAe,CAAC,GAAG;AAClD,aAAO;AAAA,IACT;AACA,UAAM,KAAK,QAAQ,GAAG;AAAA,EACxB;AAEA,SAAO,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC;AACpD;AAEA,IAAM,cAAc,kBAAkB;AAEtC,IAAM,cAAc,oBAAI,IAAoB;AAE5C,SAAS,WAAW,MAAsB;AACxC,MAAI,SAAS,YAAY,IAAI,IAAI;AACjC,MAAI,CAAC,QAAQ;AACX,aAAS,GAAG,aAAa,KAAK,KAAK,aAAa,GAAG,IAAI,KAAK,GAAG,OAAO,EAAE,KAAK;AAC7E,gBAAY,IAAI,MAAM,MAAM;AAAA,EAC9B;AACA,SAAO;AACT;AAEA,SAAS,YAAY,UAAkB,MAAsC;AAC3E,MAAI,SAAS;AACb,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,GAAG;AAC/C,aAAS,OAAO,WAAW,KAAK,GAAG,MAAM,KAAK;AAAA,EAChD;AACA,SAAO;AACT;AAIO,SAAS,sBACd,WACA,YACA,aACQ;AACR,SAAO,YAAY,WAAW,YAAY,GAAG;AAAA,IAC3C;AAAA,IACA,YAAY,OAAO,UAAU;AAAA,IAC7B;AAAA,EACF,CAAC;AACH;AAEO,SAAS,mBACd,WACA,MACA,SACQ;AACR,SAAO,YAAY,WAAW,SAAS,GAAG;AAAA,IACxC;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAEO,SAAS,iBACd,SACA,WACQ;AACR,SAAO,YAAY,WAAW,OAAO,GAAG;AAAA,IACtC;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAEA,IAAM,6BAA6B;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,SAAS,sBACd,gBACA,kBACQ;AACR,SAAO,YAAY,WAAW,oBAAoB,GAAG;AAAA,IACnD;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAEO,SAAS,0BACd,WACA,YACQ;AACR,QAAM,WAAW,WACd,IAAI,CAAC,MAAM;AACV,UAAM,YAAY,EAAE,QAAQ,MAAM,GAAG,yBAAyB;AAC9D,WAAO,OAAO,EAAE,IAAI;AAAA;AAAA,EAAa,SAAS;AAAA;AAAA,EAC5C,CAAC,EACA,KAAK,MAAM;AAEd,SAAO,YAAY,WAAW,gBAAgB,GAAG;AAAA,IAC/C;AAAA,IACA;AAAA,IACA,eAAe,2BAA2B,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI;AAAA,IACxE,YAAY,eAAe,KAAK,GAAG;AAAA,EACrC,CAAC;AACH;;;AClHA,IAAM,qBAAqB;AAAA;AAAA,EAEzB;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AACF;AAMO,SAAS,qBAAqB,MAAsB;AACzD,MAAI,CAAC,KAAM,QAAO;AAElB,aAAW,WAAW,oBAAoB;AACxC,UAAM,WAAW,KAAK,QAAQ,SAAS,EAAE,EAAE,KAAK;AAChD,QAAI,YAAY,aAAa,KAAK,KAAK,GAAG;AACxC,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAYO,SAAS,YAAY,MAAuB;AACjD,QAAM,UAAU,qBAAqB,IAAI;AAGzC,QAAM,aAAa,QAAQ,MAAM,oCAAoC;AACrE,MAAI,YAAY;AACd,WAAO,KAAK,MAAM,WAAW,CAAC,EAAE,KAAK,CAAC;AAAA,EACxC;AAGA,QAAM,cAAc,QAAQ,MAAM,aAAa;AAC/C,MAAI,aAAa;AACf,WAAO,KAAK,MAAM,YAAY,CAAC,CAAC;AAAA,EAClC;AAGA,SAAO,KAAK,MAAM,OAAO;AAC3B;AAMO,SAAS,cAAc,MAAsB;AAClD,QAAM,UAAU,qBAAqB,IAAI,EAAE,KAAK;AAChD,QAAM,QAAQ,QAAQ,MAAM,aAAa;AACzC,MAAI,MAAO,QAAO,WAAW,MAAM,CAAC,CAAC;AACrC,SAAO,WAAW,OAAO;AAC3B;;;AC1CA,IAAM,+BAA+B,iBAAE,OAAO;AAAA,EAC5C,WAAW,iBAAE,MAAM,iBAAE,OAAO;AAAA,IAC1B,aAAa,iBAAE,OAAO;AAAA,IACtB,eAAe,iBAAE,KAAK,cAAc;AAAA,IACpC,OAAO,iBAAE,OAAO;AAAA,IAChB,MAAM,iBAAE,MAAM,iBAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAA,EACtC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;AAChB,CAAC;AAEM,IAAM,kBAAN,MAAsB;AAAA,EAC3B,YAAoB,SAA8B,gBAAwB,MAAM;AAA5D;AAA8B;AAAA,EAA+B;AAAA,EAEzE,mBAAmB,MAAc,WAA2B;AAClE,UAAM,YAAY,KAAK,gBAAgB;AACvC,UAAM,aAAa,KAAK,KAAK,KAAK,SAAS,eAAe;AAC1D,QAAI,cAAc,UAAW,QAAO;AACpC,UAAM,aAAa,YAAY;AAC/B,WAAO,KAAK,MAAM,GAAG,UAAU;AAAA,EACjC;AAAA,EAEA,MAAM,QACJ,QACA,WAC0B;AAC1B,UAAM,YAAY,KAAK,yBAAyB,QAAQ,SAAS;AACjE,UAAM,SAAS,KAAK,mBAAmB,WAAW,qBAAqB;AAEvE,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,QAAQ,UAAU,QAAQ,EAAE,WAAW,sBAAsB,CAAC;AAC1F,YAAM,SAAS,YAAY,SAAS,IAAI;AAKxC,aAAO;AAAA,QACL,SAAS,OAAO;AAAA,QAChB,cAAc,OAAO,gBAAgB,CAAC;AAAA,QACtC,UAAU;AAAA,MACZ;AAAA,IACF,SAAS,OAAO;AACd,aAAO;AAAA,QACL,SAAS,qCAAqC,SAAS,KAAK,OAAO,MAAM,4BAA6B,MAAgB,OAAO;AAAA,QAC7H,cAAc,CAAC;AAAA,QACf,UAAU;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,yBACN,QACA,WACQ;AACR,UAAM,cAAc,KAAK,gBAAgB,MAAM;AAC/C,WAAO,sBAAsB,WAAW,OAAO,QAAQ,WAAW;AAAA,EACpE;AAAA,EAEA,MAAM,iBACJ,sBACA,WACA,MAC6C;AAC7C,UAAM,mBAAmB,KAAK,mBAAmB,sBAAsB,kBAAkB;AACzF,UAAM,gBAAgB,mBAAmB,WAAW,QAAQ,WAAW,gBAAgB;AAEvF,QAAI;AACJ,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,QAAQ,UAAU,eAAe,EAAE,WAAW,mBAAmB,CAAC;AAC9F,oBAAc,qBAAqB,SAAS,IAAI;AAAA,IAClD,SAAS,OAAO;AACd,oBAAc,WAAW,SAAS,iCAA6B,MAAgB,OAAO;AAAA,IACxF;AAEA,UAAM,cAAc,iBAAiB,aAAa,SAAS;AAC3D,QAAI;AACJ,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,QAAQ,UAAU,aAAa,EAAE,WAAW,iBAAiB,CAAC;AAC1F,cAAQ,qBAAqB,SAAS,IAAI,EAAE,KAAK;AAAA,IACnD,QAAQ;AACN,cAAQ,WAAW,SAAS;AAAA,IAC9B;AAEA,WAAO,EAAE,SAAS,aAAa,MAAM;AAAA,EACvC;AAAA,EAEA,MAAM,kBACJ,YACA,WAC+B;AAC/B,QAAI,WAAW,WAAW,EAAG,QAAO,CAAC;AAErC,UAAM,SAAS,KAAK,6BAA6B,YAAY,SAAS;AACtE,UAAM,WAAW,MAAM,KAAK,QAAQ,UAAU,QAAQ,EAAE,WAAW,0BAA0B,CAAC;AAC9F,UAAM,MAAM,YAAY,SAAS,IAAI;AACrC,UAAM,SAAS,6BAA6B,MAAM,GAAG;AACrD,WAAO,OAAO;AAAA,EAChB;AAAA,EAEQ,6BACN,YACA,WACQ;AACR,WAAO,0BAA0B,WAAW,UAAU;AAAA,EACxD;AAAA,EAEQ,gBAAgB,QAAgD;AACtE,UAAM,aAAa,oBAAI,IAAoB;AAC3C,UAAM,gBAAgB,oBAAI,IAAY;AACtC,UAAM,UAAoB,CAAC;AAC3B,UAAM,cAAwB,CAAC;AAE/B,eAAW,SAAS,QAAQ;AAC1B,UAAI,MAAM,SAAS,eAAe;AAChC,cAAM,SAAS,OAAO,MAAM,UAAU,EAAE;AACxC,YAAI,OAAQ,SAAQ,KAAK,OAAO,MAAM,GAAG,oBAAoB,CAAC;AAC9D;AAAA,MACF;AAEA,UAAI,MAAM,SAAS,eAAe;AAChC,cAAM,UAAU,OAAO,MAAM,WAAW,EAAE;AAC1C,YAAI,QAAS,aAAY,KAAK,QAAQ,MAAM,GAAG,yBAAyB,CAAC;AACzE;AAAA,MACF;AAGA,YAAM,OAAO,OAAO,MAAM,aAAa,MAAM,QAAQ,SAAS;AAC9D,iBAAW,IAAI,OAAO,WAAW,IAAI,IAAI,KAAK,KAAK,CAAC;AAEpD,YAAM,QAAS,MAAM,cAAc,MAAM;AACzC,UAAI,OAAO,KAAM,eAAc,IAAI,OAAO,MAAM,IAAI,CAAC;AACrD,UAAI,OAAO,UAAW,eAAc,IAAI,OAAO,MAAM,SAAS,CAAC;AAC/D,UAAI,OAAO,QAAS,eAAc,IAAI,SAAS,OAAO,MAAM,OAAO,EAAE,MAAM,GAAG,qBAAqB,CAAC,EAAE;AAAA,IACxG;AAEA,UAAM,QAAkB,CAAC;AAEzB,QAAI,QAAQ,SAAS,GAAG;AACtB,YAAM,KAAK,kBAAkB;AAC7B,iBAAW,KAAK,SAAS;AACvB,cAAM,KAAK,MAAM,CAAC,GAAG;AAAA,MACvB;AAAA,IACF;AAEA,UAAM,KAAK,kBAAkB;AAC7B,eAAW,CAAC,MAAM,KAAK,KAAK,YAAY;AACtC,YAAM,KAAK,KAAK,IAAI,KAAK,KAAK,QAAQ;AAAA,IACxC;AAEA,QAAI,cAAc,OAAO,GAAG;AAC1B,YAAM,KAAK,sBAAsB;AACjC,iBAAW,QAAQ,eAAe;AAChC,cAAM,KAAK,KAAK,IAAI,EAAE;AAAA,MACxB;AAAA,IACF;AAEA,QAAI,YAAY,SAAS,GAAG;AAC1B,YAAM,KAAK,oBAAoB;AAC/B,iBAAW,KAAK,aAAa;AAC3B,cAAM,KAAK,MAAM,CAAC,GAAG;AAAA,MACvB;AAAA,IACF;AAEA,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AACF;;;ACvLO,IAAM,kBAAN,MAAsB;AAAA,EACnB;AAAA,EAER,YAAY,QAA2B;AACrC,SAAK,WAAW,IAAI,cAAc,QAAQ,kBAAkB;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,WAAqC;AAC/C,WAAO,KAAK,sBAAsB,SAAS,EAAE;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,sBAAsB,WAAmB,gBAAsE;AAE7G,QAAI,gBAAgB;AAClB,YAAMA,UAAS,KAAK,SAAS,mBAAmB,cAAc;AAC9D,UAAIA,QAAQ,QAAOA;AAAA,IACrB;AAGA,UAAM,SAAS,KAAK,SAAS,mBAAmB,SAAS;AACzD,QAAI,OAAQ,QAAO;AACnB,WAAO,EAAE,OAAO,CAAC,GAAG,QAAQ,OAAO;AAAA,EACrC;AACF;AAOO,SAAS,uBAAuB,QAA0D;AAC/F,QAAM,QAA0B,CAAC;AACjC,MAAI,UAAiC;AAErC,aAAW,SAAS,QAAQ;AAC1B,UAAM,OAAO,MAAM;AACnB,QAAI,SAAS,eAAe;AAC1B,UAAI,QAAS,OAAM,KAAK,OAAO;AAC/B,gBAAU;AAAA,QACR,QAAQ,OAAO,MAAM,UAAU,EAAE,EAAE,MAAM,GAAG,oBAAoB;AAAA,QAChE,WAAW;AAAA,QACX,WAAW,OAAO,MAAM,cAAa,oBAAI,KAAK,GAAE,YAAY,CAAC;AAAA,MAC/D;AAAA,IACF,WAAW,SAAS,YAAY;AAC9B,UAAI,QAAS,SAAQ;AAAA,IACvB;AAAA,EACF;AACA,MAAI,QAAS,OAAM,KAAK,OAAO;AAC/B,SAAO;AACT;;;AC1DO,SAAS,sBACd,cACA,WACA,QACA,OACA,UACe;AACf,QAAM,UAAyB,CAAC;AAEhC,aAAW,OAAO,cAAc;AAC9B,UAAM,QAAQ,GAAG,IAAI,IAAI,IAAI,UAAU,MAAM,EAAE,CAAC,IAAI,KAAK,IAAI,CAAC;AAC9D,UAAM,OAAO,iBAAiB;AAAA,MAC5B,OAAO,IAAI;AAAA,MACX,iBAAiB,IAAI;AAAA,MACrB,SAAS,IAAI;AAAA,MACb;AAAA,MACA,YAAY,IAAI;AAAA,MAChB,KAAK,IAAI;AAAA,MACT,WAAW,IAAI;AAAA,MACf,uBAAuB,IAAI;AAAA,MAC3B,QAAQ,IAAI;AAAA,MACZ,YAAY,IAAI;AAAA,MAChB,MAAM,IAAI;AAAA,IACZ,CAAC;AACD,UAAM,eAAe,OAAO,YAAY;AAAA,MACtC,IAAI;AAAA,MACJ,kBAAkB,IAAI;AAAA,MACtB,SAAS,cAAc,SAAS;AAAA,MAChC,MAAM,IAAI;AAAA,MACV,SAAS;AAAA,IACX,CAAC;AACD,cAAU,OAAO,UAAU,YAAY;AACvC,YAAQ,KAAK,EAAE,IAAI,OAAO,MAAM,cAAc,aAAa,IAAI,CAAC;AAAA,EAClE;AAEA,SAAO;AACT;","names":["result"]}
|
|
@@ -30,6 +30,7 @@ Commands:
|
|
|
30
30
|
logs [options] View daemon logs
|
|
31
31
|
restart Restart the daemon
|
|
32
32
|
rebuild Reindex the entire vault
|
|
33
|
+
reprocess [options] Re-extract observations and re-index sessions
|
|
33
34
|
`;
|
|
34
35
|
async function main() {
|
|
35
36
|
const [cmd, ...args] = process.argv.slice(2);
|
|
@@ -60,7 +61,9 @@ async function main() {
|
|
|
60
61
|
case "restart":
|
|
61
62
|
return (await import("./restart-NH5MX45I.js")).run(args, vaultDir);
|
|
62
63
|
case "rebuild":
|
|
63
|
-
return (await import("./rebuild-
|
|
64
|
+
return (await import("./rebuild-3367GP5R.js")).run(args, vaultDir);
|
|
65
|
+
case "reprocess":
|
|
66
|
+
return (await import("./reprocess-EM5RIRH4.js")).run(args, vaultDir);
|
|
64
67
|
case "logs":
|
|
65
68
|
return (await import("./logs-BSTBZHDR.js")).run(args, vaultDir);
|
|
66
69
|
default:
|
|
@@ -73,4 +76,4 @@ main().catch((err) => {
|
|
|
73
76
|
console.error(`myco: ${err.message}`);
|
|
74
77
|
process.exit(1);
|
|
75
78
|
});
|
|
76
|
-
//# sourceMappingURL=cli-
|
|
79
|
+
//# sourceMappingURL=cli-ERAS5H43.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { loadEnv } from './cli/shared.js';\nimport { resolveVaultDir } from './vault/resolve.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nloadEnv();\n\nconst USAGE = `Usage: myco <command> [args]\n\nCommands:\n init [options] Initialize a new vault\n config <get|set> [args] Get or set vault config values\n detect-providers Detect available LLM/embedding providers (JSON)\n verify Test LLM and embedding connectivity\n stats Vault health, index counts, vector count\n search <query> Combined FTS + vector search with scores\n vectors <query> Raw vector search with similarity scores\n session [id|latest] Show a session note\n logs [options] View daemon logs\n restart Restart the daemon\n rebuild Reindex the entire vault\n reprocess [options] Re-extract observations and re-index sessions\n`;\n\nasync function main(): Promise<void> {\n const [cmd, ...args] = process.argv.slice(2);\n if (!cmd || cmd === '--help' || cmd === '-h') {\n process.stdout.write(USAGE);\n return;\n }\n\n if (cmd === 'init') return (await import('./cli/init.js')).run(args);\n if (cmd === 'detect-providers') return (await import('./cli/detect-providers.js')).run(args);\n\n const vaultDir = resolveVaultDir();\n if (!fs.existsSync(path.join(vaultDir, 'myco.yaml'))) {\n console.error(`No myco.yaml found in ${vaultDir}. Run 'myco init' first.`);\n process.exit(1);\n }\n\n switch (cmd) {\n case 'config': return (await import('./cli/config.js')).run(args, vaultDir);\n case 'verify': return (await import('./cli/verify.js')).run(args, vaultDir);\n case 'stats': return (await import('./cli/stats.js')).run(args, vaultDir);\n case 'search': return (await import('./cli/search.js')).run(args, vaultDir);\n case 'vectors': return (await import('./cli/search.js')).runVectors(args, vaultDir);\n case 'session': return (await import('./cli/session.js')).run(args, vaultDir);\n case 'restart': return (await import('./cli/restart.js')).run(args, vaultDir);\n case 'rebuild': return (await import('./cli/rebuild.js')).run(args, vaultDir);\n case 'reprocess': return (await import('./cli/reprocess.js')).run(args, vaultDir);\n case 'logs': return (await import('./cli/logs.js')).run(args, vaultDir);\n default:\n console.error(`Unknown command: ${cmd}`);\n process.stdout.write(USAGE);\n process.exit(1);\n }\n}\n\nmain().catch((err) => {\n console.error(`myco: ${(err as Error).message}`);\n process.exit(1);\n});\n"],"mappings":";;;;;;;;;;;;;;;AAGA,OAAO,QAAQ;AACf,OAAO,UAAU;AAEjB,QAAQ;AAER,IAAM,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBd,eAAe,OAAsB;AACnC,QAAM,CAAC,KAAK,GAAG,IAAI,IAAI,QAAQ,KAAK,MAAM,CAAC;AAC3C,MAAI,CAAC,OAAO,QAAQ,YAAY,QAAQ,MAAM;AAC5C,YAAQ,OAAO,MAAM,KAAK;AAC1B;AAAA,EACF;AAEA,MAAI,QAAQ,OAAQ,SAAQ,MAAM,OAAO,oBAAe,GAAG,IAAI,IAAI;AACnE,MAAI,QAAQ,mBAAoB,SAAQ,MAAM,OAAO,gCAA2B,GAAG,IAAI,IAAI;AAE3F,QAAM,WAAW,gBAAgB;AACjC,MAAI,CAAC,GAAG,WAAW,KAAK,KAAK,UAAU,WAAW,CAAC,GAAG;AACpD,YAAQ,MAAM,yBAAyB,QAAQ,0BAA0B;AACzE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ,KAAK;AAAA,IACX,KAAK;AAAU,cAAQ,MAAM,OAAO,sBAAiB,GAAG,IAAI,MAAM,QAAQ;AAAA,IAC1E,KAAK;AAAU,cAAQ,MAAM,OAAO,sBAAiB,GAAG,IAAI,MAAM,QAAQ;AAAA,IAC1E,KAAK;AAAS,cAAQ,MAAM,OAAO,qBAAgB,GAAG,IAAI,MAAM,QAAQ;AAAA,IACxE,KAAK;AAAU,cAAQ,MAAM,OAAO,sBAAiB,GAAG,IAAI,MAAM,QAAQ;AAAA,IAC1E,KAAK;AAAW,cAAQ,MAAM,OAAO,sBAAiB,GAAG,WAAW,MAAM,QAAQ;AAAA,IAClF,KAAK;AAAW,cAAQ,MAAM,OAAO,uBAAkB,GAAG,IAAI,MAAM,QAAQ;AAAA,IAC5E,KAAK;AAAW,cAAQ,MAAM,OAAO,uBAAkB,GAAG,IAAI,MAAM,QAAQ;AAAA,IAC5E,KAAK;AAAW,cAAQ,MAAM,OAAO,uBAAkB,GAAG,IAAI,MAAM,QAAQ;AAAA,IAC5E,KAAK;AAAa,cAAQ,MAAM,OAAO,yBAAoB,GAAG,IAAI,MAAM,QAAQ;AAAA,IAChF,KAAK;AAAQ,cAAQ,MAAM,OAAO,oBAAe,GAAG,IAAI,MAAM,QAAQ;AAAA,IACtE;AACE,cAAQ,MAAM,oBAAoB,GAAG,EAAE;AACvC,cAAQ,OAAO,MAAM,KAAK;AAC1B,cAAQ,KAAK,CAAC;AAAA,EAClB;AACF;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AACpB,UAAQ,MAAM,SAAU,IAAc,OAAO,EAAE;AAC/C,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":[]}
|