@goondocks/myco 0.3.0 → 0.3.2
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-2UEJVXXE.js +33 -0
- package/dist/chunk-2UEJVXXE.js.map +1 -0
- package/dist/chunk-3JCXYLHD.js +33 -0
- package/dist/chunk-3JCXYLHD.js.map +1 -0
- package/dist/{chunk-NTYYYC32.js → chunk-5BGQJOJN.js} +47 -4
- package/dist/chunk-5BGQJOJN.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-4RR3QBYK.js} +15 -6
- package/dist/cli-4RR3QBYK.js.map +1 -0
- package/dist/{client-HORA3CC4.js → client-43ML4EHJ.js} +3 -2
- package/dist/{init-LLLHUNSY.js → init-HTKEL3YT.js} +4 -4
- package/dist/{main-JY6O6ZVH.js → main-DTWU4OAH.js} +227 -537
- package/dist/main-DTWU4OAH.js.map +1 -0
- package/dist/{rebuild-YAN3TPFB.js → rebuild-TXMFYBOU.js} +27 -20
- package/dist/rebuild-TXMFYBOU.js.map +1 -0
- package/dist/reprocess-ARKHGDWF.js +199 -0
- package/dist/reprocess-ARKHGDWF.js.map +1 -0
- package/dist/{restart-NH5MX45I.js → restart-C5BCVG3A.js} +2 -2
- package/dist/{search-W3ECVSTH.js → search-YCKNX2WS.js} +7 -7
- package/dist/{server-DLBATUNG.js → server-EBKMQISL.js} +18 -23
- package/dist/{server-DLBATUNG.js.map → server-EBKMQISL.js.map} +1 -1
- package/dist/{session-start-DECLNJDI.js → session-start-ADZLL2YI.js} +3 -2
- package/dist/{session-start-DECLNJDI.js.map → session-start-ADZLL2YI.js.map} +1 -1
- package/dist/src/cli.js +1 -1
- package/dist/src/daemon/main.js +1 -1
- package/dist/src/hooks/post-tool-use.js +2 -1
- package/dist/src/hooks/post-tool-use.js.map +1 -1
- package/dist/src/hooks/session-end.js +2 -1
- package/dist/src/hooks/session-end.js.map +1 -1
- package/dist/src/hooks/session-start.js +1 -1
- package/dist/src/hooks/stop.js +2 -1
- package/dist/src/hooks/stop.js.map +1 -1
- package/dist/src/hooks/user-prompt-submit.js +2 -1
- package/dist/src/hooks/user-prompt-submit.js.map +1 -1
- package/dist/src/mcp/server.js +1 -1
- package/dist/version-N55WTRG5.js +11 -0
- package/dist/version-N55WTRG5.js.map +1 -0
- package/package.json +1 -1
- package/skills/myco/SKILL.md +34 -0
- package/dist/chunk-NTYYYC32.js.map +0 -1
- 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
- /package/dist/{client-HORA3CC4.js.map → client-43ML4EHJ.js.map} +0 -0
- /package/dist/{init-LLLHUNSY.js.map → init-HTKEL3YT.js.map} +0 -0
- /package/dist/{restart-NH5MX45I.js.map → restart-C5BCVG3A.js.map} +0 -0
- /package/dist/{search-W3ECVSTH.js.map → search-YCKNX2WS.js.map} +0 -0
|
@@ -1,37 +1,43 @@
|
|
|
1
1
|
import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
BufferProcessor,
|
|
4
|
+
TranscriptMiner,
|
|
5
|
+
buildSimilarityPrompt,
|
|
6
|
+
extractNumber,
|
|
7
|
+
extractTurnsFromBuffer,
|
|
8
|
+
writeObservationNotes
|
|
9
|
+
} from "./chunk-JIQISBPI.js";
|
|
2
10
|
import {
|
|
3
11
|
VaultWriter,
|
|
4
12
|
bareSessionId,
|
|
5
|
-
formatMemoryBody,
|
|
6
13
|
formatSessionBody,
|
|
7
14
|
sessionNoteId,
|
|
8
15
|
sessionRelativePath,
|
|
9
16
|
sessionWikilink
|
|
10
17
|
} from "./chunk-P2Q77C5F.js";
|
|
11
18
|
import {
|
|
12
|
-
ARTIFACT_TYPES,
|
|
13
19
|
indexNote,
|
|
14
20
|
rebuildIndex
|
|
15
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-72OAG4SF.js";
|
|
16
22
|
import {
|
|
17
23
|
generateEmbedding
|
|
18
24
|
} from "./chunk-RGVBGTD6.js";
|
|
25
|
+
import {
|
|
26
|
+
VectorIndex
|
|
27
|
+
} from "./chunk-XQXXF6MU.js";
|
|
19
28
|
import {
|
|
20
29
|
DaemonLogger
|
|
21
30
|
} from "./chunk-5EZ7QF6J.js";
|
|
22
31
|
import {
|
|
23
32
|
initFts
|
|
24
33
|
} from "./chunk-6FQISQNA.js";
|
|
34
|
+
import {
|
|
35
|
+
MycoIndex
|
|
36
|
+
} from "./chunk-PA3VMINE.js";
|
|
25
37
|
import {
|
|
26
38
|
createEmbeddingProvider,
|
|
27
39
|
createLlmProvider
|
|
28
40
|
} from "./chunk-N6IAW33G.js";
|
|
29
|
-
import {
|
|
30
|
-
VectorIndex
|
|
31
|
-
} from "./chunk-XQXXF6MU.js";
|
|
32
|
-
import {
|
|
33
|
-
MycoIndex
|
|
34
|
-
} from "./chunk-PA3VMINE.js";
|
|
35
41
|
import "./chunk-XW3OL55U.js";
|
|
36
42
|
import {
|
|
37
43
|
external_exports,
|
|
@@ -44,33 +50,27 @@ import {
|
|
|
44
50
|
EventBuffer
|
|
45
51
|
} from "./chunk-I7PMGO6S.js";
|
|
46
52
|
import {
|
|
47
|
-
|
|
53
|
+
getPluginVersion
|
|
54
|
+
} from "./chunk-2UEJVXXE.js";
|
|
55
|
+
import {
|
|
48
56
|
claudeCodeAdapter,
|
|
49
57
|
createPerProjectAdapter,
|
|
50
58
|
extensionForMimeType
|
|
51
59
|
} from "./chunk-2QEJKG7R.js";
|
|
52
60
|
import {
|
|
53
|
-
AI_RESPONSE_PREVIEW_CHARS,
|
|
54
61
|
CANDIDATE_CONTENT_PREVIEW,
|
|
55
|
-
CHARS_PER_TOKEN,
|
|
56
|
-
CLASSIFICATION_MAX_TOKENS,
|
|
57
|
-
COMMAND_PREVIEW_CHARS,
|
|
58
62
|
CONTENT_SNIPPET_CHARS,
|
|
59
63
|
CONTEXT_SESSION_PREVIEW_CHARS,
|
|
60
64
|
EMBEDDING_INPUT_LIMIT,
|
|
61
|
-
EXTRACTION_MAX_TOKENS,
|
|
62
65
|
FILE_WATCH_STABILITY_MS,
|
|
63
66
|
LINEAGE_RECENT_SESSIONS_LIMIT,
|
|
64
67
|
MAX_SLUG_LENGTH,
|
|
65
68
|
PROMPT_CONTEXT_MAX_MEMORIES,
|
|
66
69
|
PROMPT_CONTEXT_MIN_LENGTH,
|
|
67
70
|
PROMPT_CONTEXT_MIN_SIMILARITY,
|
|
68
|
-
PROMPT_PREVIEW_CHARS,
|
|
69
71
|
RELATED_MEMORIES_LIMIT,
|
|
70
72
|
SESSION_CONTEXT_MAX_PLANS,
|
|
71
|
-
STALE_BUFFER_MAX_AGE_MS
|
|
72
|
-
SUMMARY_MAX_TOKENS,
|
|
73
|
-
TITLE_MAX_TOKENS
|
|
73
|
+
STALE_BUFFER_MAX_AGE_MS
|
|
74
74
|
} from "./chunk-Q7BEFSOV.js";
|
|
75
75
|
import {
|
|
76
76
|
__toESM
|
|
@@ -82,6 +82,7 @@ import fs from "fs";
|
|
|
82
82
|
import path from "path";
|
|
83
83
|
var DaemonServer = class {
|
|
84
84
|
port = 0;
|
|
85
|
+
version;
|
|
85
86
|
server = null;
|
|
86
87
|
vaultDir;
|
|
87
88
|
logger;
|
|
@@ -89,6 +90,7 @@ var DaemonServer = class {
|
|
|
89
90
|
constructor(config) {
|
|
90
91
|
this.vaultDir = config.vaultDir;
|
|
91
92
|
this.logger = config.logger;
|
|
93
|
+
this.version = getPluginVersion();
|
|
92
94
|
this.registerDefaultRoutes();
|
|
93
95
|
}
|
|
94
96
|
registerRoute(method, routePath, handler) {
|
|
@@ -123,6 +125,7 @@ var DaemonServer = class {
|
|
|
123
125
|
registerDefaultRoutes() {
|
|
124
126
|
this.registerRoute("GET", "/health", async () => ({
|
|
125
127
|
myco: true,
|
|
128
|
+
version: this.version,
|
|
126
129
|
pid: process.pid,
|
|
127
130
|
uptime: process.uptime()
|
|
128
131
|
}));
|
|
@@ -280,244 +283,9 @@ var BatchManager = class {
|
|
|
280
283
|
}
|
|
281
284
|
};
|
|
282
285
|
|
|
283
|
-
// src/
|
|
286
|
+
// src/daemon/lineage.ts
|
|
284
287
|
import fs2 from "fs";
|
|
285
288
|
import path2 from "path";
|
|
286
|
-
import { fileURLToPath } from "url";
|
|
287
|
-
var __dirname = path2.dirname(fileURLToPath(import.meta.url));
|
|
288
|
-
var promptCache = /* @__PURE__ */ new Map();
|
|
289
|
-
function loadPrompt(name) {
|
|
290
|
-
let cached = promptCache.get(name);
|
|
291
|
-
if (!cached) {
|
|
292
|
-
cached = fs2.readFileSync(path2.join(__dirname, `${name}.md`), "utf-8").trim();
|
|
293
|
-
promptCache.set(name, cached);
|
|
294
|
-
}
|
|
295
|
-
return cached;
|
|
296
|
-
}
|
|
297
|
-
function interpolate(template, vars) {
|
|
298
|
-
let result = template;
|
|
299
|
-
for (const [key, value] of Object.entries(vars)) {
|
|
300
|
-
result = result.replaceAll(`{{${key}}}`, value);
|
|
301
|
-
}
|
|
302
|
-
return result;
|
|
303
|
-
}
|
|
304
|
-
function buildExtractionPrompt(sessionId, eventCount, toolSummary) {
|
|
305
|
-
return interpolate(loadPrompt("extraction"), {
|
|
306
|
-
sessionId,
|
|
307
|
-
eventCount: String(eventCount),
|
|
308
|
-
toolSummary
|
|
309
|
-
});
|
|
310
|
-
}
|
|
311
|
-
function buildSummaryPrompt(sessionId, user, content) {
|
|
312
|
-
return interpolate(loadPrompt("summary"), {
|
|
313
|
-
sessionId,
|
|
314
|
-
user,
|
|
315
|
-
content
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
|
-
function buildTitlePrompt(summary, sessionId) {
|
|
319
|
-
return interpolate(loadPrompt("title"), {
|
|
320
|
-
summary,
|
|
321
|
-
sessionId
|
|
322
|
-
});
|
|
323
|
-
}
|
|
324
|
-
var ARTIFACT_TYPE_DESCRIPTIONS = [
|
|
325
|
-
'"spec" \u2014 Design specifications, architecture documents',
|
|
326
|
-
'"plan" \u2014 Implementation plans, roadmaps',
|
|
327
|
-
'"rfc" \u2014 Requests for comment, proposals',
|
|
328
|
-
'"doc" \u2014 Documentation, guides, READMEs',
|
|
329
|
-
'"other" \u2014 Other substantive documents'
|
|
330
|
-
];
|
|
331
|
-
function buildSimilarityPrompt(currentSummary, candidateSummary) {
|
|
332
|
-
return interpolate(loadPrompt("session-similarity"), {
|
|
333
|
-
currentSummary,
|
|
334
|
-
candidateSummary
|
|
335
|
-
});
|
|
336
|
-
}
|
|
337
|
-
function buildClassificationPrompt(sessionId, candidates) {
|
|
338
|
-
const fileList = candidates.map((c) => {
|
|
339
|
-
const truncated = c.content.slice(0, CANDIDATE_CONTENT_PREVIEW);
|
|
340
|
-
return `### ${c.path}
|
|
341
|
-
\`\`\`
|
|
342
|
-
${truncated}
|
|
343
|
-
\`\`\``;
|
|
344
|
-
}).join("\n\n");
|
|
345
|
-
return interpolate(loadPrompt("classification"), {
|
|
346
|
-
sessionId,
|
|
347
|
-
fileList,
|
|
348
|
-
artifactTypes: ARTIFACT_TYPE_DESCRIPTIONS.map((d) => `- ${d}`).join("\n"),
|
|
349
|
-
validTypes: ARTIFACT_TYPES.join("|")
|
|
350
|
-
});
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
// src/intelligence/response.ts
|
|
354
|
-
var REASONING_PATTERNS = [
|
|
355
|
-
// <think>...</think>answer (DeepSeek, Qwen, GLM, many others)
|
|
356
|
-
/<think>[\s\S]*?<\/think>\s*/gi,
|
|
357
|
-
// Implicit opening: reasoning...</think>answer (GLM-4.7 observed)
|
|
358
|
-
/^[\s\S]*?<\/think>\s*/i,
|
|
359
|
-
// <reasoning>...</reasoning>answer
|
|
360
|
-
/<reasoning>[\s\S]*?<\/reasoning>\s*/gi,
|
|
361
|
-
// <|thinking|>...<|/thinking|>answer
|
|
362
|
-
/<\|thinking\|>[\s\S]*?<\|\/thinking\|>\s*/gi
|
|
363
|
-
];
|
|
364
|
-
function stripReasoningTokens(text) {
|
|
365
|
-
if (!text) return text;
|
|
366
|
-
for (const pattern of REASONING_PATTERNS) {
|
|
367
|
-
const stripped = text.replace(pattern, "").trim();
|
|
368
|
-
if (stripped && stripped !== text.trim()) {
|
|
369
|
-
return stripped;
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
return text;
|
|
373
|
-
}
|
|
374
|
-
function extractJson(text) {
|
|
375
|
-
const cleaned = stripReasoningTokens(text);
|
|
376
|
-
const fenceMatch = cleaned.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/);
|
|
377
|
-
if (fenceMatch) {
|
|
378
|
-
return JSON.parse(fenceMatch[1].trim());
|
|
379
|
-
}
|
|
380
|
-
const objectMatch = cleaned.match(/\{[\s\S]*\}/);
|
|
381
|
-
if (objectMatch) {
|
|
382
|
-
return JSON.parse(objectMatch[0]);
|
|
383
|
-
}
|
|
384
|
-
return JSON.parse(cleaned);
|
|
385
|
-
}
|
|
386
|
-
function extractNumber(text) {
|
|
387
|
-
const cleaned = stripReasoningTokens(text).trim();
|
|
388
|
-
const match = cleaned.match(/(\d+\.?\d*)/);
|
|
389
|
-
if (match) return parseFloat(match[1]);
|
|
390
|
-
return parseFloat(cleaned);
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
// src/daemon/processor.ts
|
|
394
|
-
var ClassificationResponseSchema = external_exports.object({
|
|
395
|
-
artifacts: external_exports.array(external_exports.object({
|
|
396
|
-
source_path: external_exports.string(),
|
|
397
|
-
artifact_type: external_exports.enum(ARTIFACT_TYPES),
|
|
398
|
-
title: external_exports.string(),
|
|
399
|
-
tags: external_exports.array(external_exports.string()).default([])
|
|
400
|
-
})).default([])
|
|
401
|
-
});
|
|
402
|
-
var BufferProcessor = class {
|
|
403
|
-
constructor(backend, contextWindow = 8192) {
|
|
404
|
-
this.backend = backend;
|
|
405
|
-
this.contextWindow = contextWindow;
|
|
406
|
-
}
|
|
407
|
-
truncateForContext(data, maxTokens) {
|
|
408
|
-
const available = this.contextWindow - maxTokens;
|
|
409
|
-
const dataTokens = Math.ceil(data.length / CHARS_PER_TOKEN);
|
|
410
|
-
if (dataTokens <= available) return data;
|
|
411
|
-
const charBudget = available * CHARS_PER_TOKEN;
|
|
412
|
-
return data.slice(0, charBudget);
|
|
413
|
-
}
|
|
414
|
-
async process(events, sessionId) {
|
|
415
|
-
const rawPrompt = this.buildPromptForExtraction(events, sessionId);
|
|
416
|
-
const prompt = this.truncateForContext(rawPrompt, EXTRACTION_MAX_TOKENS);
|
|
417
|
-
try {
|
|
418
|
-
const response = await this.backend.summarize(prompt, { maxTokens: EXTRACTION_MAX_TOKENS });
|
|
419
|
-
const parsed = extractJson(response.text);
|
|
420
|
-
return {
|
|
421
|
-
summary: parsed.summary,
|
|
422
|
-
observations: parsed.observations ?? [],
|
|
423
|
-
degraded: false
|
|
424
|
-
};
|
|
425
|
-
} catch (error) {
|
|
426
|
-
return {
|
|
427
|
-
summary: `LLM processing failed for session ${sessionId}. ${events.length} events captured. Error: ${error.message}`,
|
|
428
|
-
observations: [],
|
|
429
|
-
degraded: true
|
|
430
|
-
};
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
buildPromptForExtraction(events, sessionId) {
|
|
434
|
-
const toolSummary = this.summarizeEvents(events);
|
|
435
|
-
return buildExtractionPrompt(sessionId, events.length, toolSummary);
|
|
436
|
-
}
|
|
437
|
-
async summarizeSession(conversationMarkdown, sessionId, user) {
|
|
438
|
-
const truncatedContent = this.truncateForContext(conversationMarkdown, SUMMARY_MAX_TOKENS);
|
|
439
|
-
const summaryPrompt = buildSummaryPrompt(sessionId, user ?? "unknown", truncatedContent);
|
|
440
|
-
let summaryText;
|
|
441
|
-
try {
|
|
442
|
-
const response = await this.backend.summarize(summaryPrompt, { maxTokens: SUMMARY_MAX_TOKENS });
|
|
443
|
-
summaryText = stripReasoningTokens(response.text);
|
|
444
|
-
} catch (error) {
|
|
445
|
-
summaryText = `Session ${sessionId} \u2014 summarization failed: ${error.message}`;
|
|
446
|
-
}
|
|
447
|
-
const titlePrompt = buildTitlePrompt(summaryText, sessionId);
|
|
448
|
-
let title;
|
|
449
|
-
try {
|
|
450
|
-
const response = await this.backend.summarize(titlePrompt, { maxTokens: TITLE_MAX_TOKENS });
|
|
451
|
-
title = stripReasoningTokens(response.text).trim();
|
|
452
|
-
} catch {
|
|
453
|
-
title = `Session ${sessionId}`;
|
|
454
|
-
}
|
|
455
|
-
return { summary: summaryText, title };
|
|
456
|
-
}
|
|
457
|
-
async classifyArtifacts(candidates, sessionId) {
|
|
458
|
-
if (candidates.length === 0) return [];
|
|
459
|
-
const prompt = this.buildPromptForClassification(candidates, sessionId);
|
|
460
|
-
const response = await this.backend.summarize(prompt, { maxTokens: CLASSIFICATION_MAX_TOKENS });
|
|
461
|
-
const raw = extractJson(response.text);
|
|
462
|
-
const parsed = ClassificationResponseSchema.parse(raw);
|
|
463
|
-
return parsed.artifacts;
|
|
464
|
-
}
|
|
465
|
-
buildPromptForClassification(candidates, sessionId) {
|
|
466
|
-
return buildClassificationPrompt(sessionId, candidates);
|
|
467
|
-
}
|
|
468
|
-
summarizeEvents(events) {
|
|
469
|
-
const toolCounts = /* @__PURE__ */ new Map();
|
|
470
|
-
const filesAccessed = /* @__PURE__ */ new Set();
|
|
471
|
-
const prompts = [];
|
|
472
|
-
const aiResponses = [];
|
|
473
|
-
for (const event of events) {
|
|
474
|
-
if (event.type === "user_prompt") {
|
|
475
|
-
const prompt = String(event.prompt ?? "");
|
|
476
|
-
if (prompt) prompts.push(prompt.slice(0, PROMPT_PREVIEW_CHARS));
|
|
477
|
-
continue;
|
|
478
|
-
}
|
|
479
|
-
if (event.type === "ai_response") {
|
|
480
|
-
const content = String(event.content ?? "");
|
|
481
|
-
if (content) aiResponses.push(content.slice(0, AI_RESPONSE_PREVIEW_CHARS));
|
|
482
|
-
continue;
|
|
483
|
-
}
|
|
484
|
-
const tool = String(event.tool_name ?? event.tool ?? "unknown");
|
|
485
|
-
toolCounts.set(tool, (toolCounts.get(tool) ?? 0) + 1);
|
|
486
|
-
const input = event.tool_input ?? event.input;
|
|
487
|
-
if (input?.path) filesAccessed.add(String(input.path));
|
|
488
|
-
if (input?.file_path) filesAccessed.add(String(input.file_path));
|
|
489
|
-
if (input?.command) filesAccessed.add(`[cmd] ${String(input.command).slice(0, COMMAND_PREVIEW_CHARS)}`);
|
|
490
|
-
}
|
|
491
|
-
const lines = [];
|
|
492
|
-
if (prompts.length > 0) {
|
|
493
|
-
lines.push("### User Prompts");
|
|
494
|
-
for (const p of prompts) {
|
|
495
|
-
lines.push(`- "${p}"`);
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
lines.push("\n### Tool Usage");
|
|
499
|
-
for (const [tool, count] of toolCounts) {
|
|
500
|
-
lines.push(`- ${tool}: ${count} calls`);
|
|
501
|
-
}
|
|
502
|
-
if (filesAccessed.size > 0) {
|
|
503
|
-
lines.push("\n### Files Accessed");
|
|
504
|
-
for (const file of filesAccessed) {
|
|
505
|
-
lines.push(`- ${file}`);
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
if (aiResponses.length > 0) {
|
|
509
|
-
lines.push("\n### AI Responses");
|
|
510
|
-
for (const r of aiResponses) {
|
|
511
|
-
lines.push(`- "${r}"`);
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
return lines.join("\n");
|
|
515
|
-
}
|
|
516
|
-
};
|
|
517
|
-
|
|
518
|
-
// src/daemon/lineage.ts
|
|
519
|
-
import fs3 from "fs";
|
|
520
|
-
import path3 from "path";
|
|
521
289
|
var LINEAGE_IMMEDIATE_GAP_SECONDS = 5;
|
|
522
290
|
var LINEAGE_FALLBACK_MAX_HOURS = 24;
|
|
523
291
|
var LINEAGE_SIMILARITY_THRESHOLD = 0.7;
|
|
@@ -530,8 +298,8 @@ var LineageGraph = class {
|
|
|
530
298
|
state;
|
|
531
299
|
filePath;
|
|
532
300
|
constructor(vaultDir) {
|
|
533
|
-
this.filePath =
|
|
534
|
-
|
|
301
|
+
this.filePath = path2.join(vaultDir, "lineage.json");
|
|
302
|
+
fs2.mkdirSync(path2.dirname(this.filePath), { recursive: true });
|
|
535
303
|
this.state = this.load();
|
|
536
304
|
}
|
|
537
305
|
addLink(link) {
|
|
@@ -611,7 +379,7 @@ var LineageGraph = class {
|
|
|
611
379
|
}
|
|
612
380
|
load() {
|
|
613
381
|
try {
|
|
614
|
-
const raw = JSON.parse(
|
|
382
|
+
const raw = JSON.parse(fs2.readFileSync(this.filePath, "utf-8"));
|
|
615
383
|
const sessionArtifacts = raw.sessionArtifacts ?? raw.sessionPlans ?? {};
|
|
616
384
|
return { links: raw.links ?? [], sessionArtifacts };
|
|
617
385
|
} catch {
|
|
@@ -620,8 +388,8 @@ var LineageGraph = class {
|
|
|
620
388
|
}
|
|
621
389
|
persist() {
|
|
622
390
|
const tmp = this.filePath + ".tmp";
|
|
623
|
-
|
|
624
|
-
|
|
391
|
+
fs2.writeFileSync(tmp, JSON.stringify(this.state, null, 2));
|
|
392
|
+
fs2.renameSync(tmp, this.filePath);
|
|
625
393
|
}
|
|
626
394
|
};
|
|
627
395
|
|
|
@@ -715,7 +483,7 @@ var ReaddirpStream = class extends Readable {
|
|
|
715
483
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
716
484
|
const statMethod = opts.lstat ? lstat : stat;
|
|
717
485
|
if (wantBigintFsStats) {
|
|
718
|
-
this._stat = (
|
|
486
|
+
this._stat = (path7) => statMethod(path7, { bigint: true });
|
|
719
487
|
} else {
|
|
720
488
|
this._stat = statMethod;
|
|
721
489
|
}
|
|
@@ -740,8 +508,8 @@ var ReaddirpStream = class extends Readable {
|
|
|
740
508
|
const par = this.parent;
|
|
741
509
|
const fil = par && par.files;
|
|
742
510
|
if (fil && fil.length > 0) {
|
|
743
|
-
const { path:
|
|
744
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
511
|
+
const { path: path7, depth } = par;
|
|
512
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path7));
|
|
745
513
|
const awaited = await Promise.all(slice);
|
|
746
514
|
for (const entry of awaited) {
|
|
747
515
|
if (!entry)
|
|
@@ -781,20 +549,20 @@ var ReaddirpStream = class extends Readable {
|
|
|
781
549
|
this.reading = false;
|
|
782
550
|
}
|
|
783
551
|
}
|
|
784
|
-
async _exploreDir(
|
|
552
|
+
async _exploreDir(path7, depth) {
|
|
785
553
|
let files;
|
|
786
554
|
try {
|
|
787
|
-
files = await readdir(
|
|
555
|
+
files = await readdir(path7, this._rdOptions);
|
|
788
556
|
} catch (error) {
|
|
789
557
|
this._onError(error);
|
|
790
558
|
}
|
|
791
|
-
return { files, depth, path:
|
|
559
|
+
return { files, depth, path: path7 };
|
|
792
560
|
}
|
|
793
|
-
async _formatEntry(dirent,
|
|
561
|
+
async _formatEntry(dirent, path7) {
|
|
794
562
|
let entry;
|
|
795
563
|
const basename3 = this._isDirent ? dirent.name : dirent;
|
|
796
564
|
try {
|
|
797
|
-
const fullPath = presolve(pjoin(
|
|
565
|
+
const fullPath = presolve(pjoin(path7, basename3));
|
|
798
566
|
entry = { path: prelative(this._root, fullPath), fullPath, basename: basename3 };
|
|
799
567
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
800
568
|
} catch (err) {
|
|
@@ -1194,16 +962,16 @@ var delFromSet = (main2, prop, item) => {
|
|
|
1194
962
|
};
|
|
1195
963
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
1196
964
|
var FsWatchInstances = /* @__PURE__ */ new Map();
|
|
1197
|
-
function createFsWatchInstance(
|
|
965
|
+
function createFsWatchInstance(path7, options, listener, errHandler, emitRaw) {
|
|
1198
966
|
const handleEvent = (rawEvent, evPath) => {
|
|
1199
|
-
listener(
|
|
1200
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
1201
|
-
if (evPath &&
|
|
1202
|
-
fsWatchBroadcast(sp.resolve(
|
|
967
|
+
listener(path7);
|
|
968
|
+
emitRaw(rawEvent, evPath, { watchedPath: path7 });
|
|
969
|
+
if (evPath && path7 !== evPath) {
|
|
970
|
+
fsWatchBroadcast(sp.resolve(path7, evPath), KEY_LISTENERS, sp.join(path7, evPath));
|
|
1203
971
|
}
|
|
1204
972
|
};
|
|
1205
973
|
try {
|
|
1206
|
-
return fs_watch(
|
|
974
|
+
return fs_watch(path7, {
|
|
1207
975
|
persistent: options.persistent
|
|
1208
976
|
}, handleEvent);
|
|
1209
977
|
} catch (error) {
|
|
@@ -1219,12 +987,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
1219
987
|
listener(val1, val2, val3);
|
|
1220
988
|
});
|
|
1221
989
|
};
|
|
1222
|
-
var setFsWatchListener = (
|
|
990
|
+
var setFsWatchListener = (path7, fullPath, options, handlers) => {
|
|
1223
991
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
1224
992
|
let cont = FsWatchInstances.get(fullPath);
|
|
1225
993
|
let watcher;
|
|
1226
994
|
if (!options.persistent) {
|
|
1227
|
-
watcher = createFsWatchInstance(
|
|
995
|
+
watcher = createFsWatchInstance(path7, options, listener, errHandler, rawEmitter);
|
|
1228
996
|
if (!watcher)
|
|
1229
997
|
return;
|
|
1230
998
|
return watcher.close.bind(watcher);
|
|
@@ -1235,7 +1003,7 @@ var setFsWatchListener = (path8, fullPath, options, handlers) => {
|
|
|
1235
1003
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
1236
1004
|
} else {
|
|
1237
1005
|
watcher = createFsWatchInstance(
|
|
1238
|
-
|
|
1006
|
+
path7,
|
|
1239
1007
|
options,
|
|
1240
1008
|
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
1241
1009
|
errHandler,
|
|
@@ -1250,7 +1018,7 @@ var setFsWatchListener = (path8, fullPath, options, handlers) => {
|
|
|
1250
1018
|
cont.watcherUnusable = true;
|
|
1251
1019
|
if (isWindows && error.code === "EPERM") {
|
|
1252
1020
|
try {
|
|
1253
|
-
const fd = await open(
|
|
1021
|
+
const fd = await open(path7, "r");
|
|
1254
1022
|
await fd.close();
|
|
1255
1023
|
broadcastErr(error);
|
|
1256
1024
|
} catch (err) {
|
|
@@ -1281,7 +1049,7 @@ var setFsWatchListener = (path8, fullPath, options, handlers) => {
|
|
|
1281
1049
|
};
|
|
1282
1050
|
};
|
|
1283
1051
|
var FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
1284
|
-
var setFsWatchFileListener = (
|
|
1052
|
+
var setFsWatchFileListener = (path7, fullPath, options, handlers) => {
|
|
1285
1053
|
const { listener, rawEmitter } = handlers;
|
|
1286
1054
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
1287
1055
|
const copts = cont && cont.options;
|
|
@@ -1303,7 +1071,7 @@ var setFsWatchFileListener = (path8, fullPath, options, handlers) => {
|
|
|
1303
1071
|
});
|
|
1304
1072
|
const currmtime = curr.mtimeMs;
|
|
1305
1073
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
1306
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
1074
|
+
foreach(cont.listeners, (listener2) => listener2(path7, curr));
|
|
1307
1075
|
}
|
|
1308
1076
|
})
|
|
1309
1077
|
};
|
|
@@ -1333,13 +1101,13 @@ var NodeFsHandler = class {
|
|
|
1333
1101
|
* @param listener on fs change
|
|
1334
1102
|
* @returns closer for the watcher instance
|
|
1335
1103
|
*/
|
|
1336
|
-
_watchWithNodeFs(
|
|
1104
|
+
_watchWithNodeFs(path7, listener) {
|
|
1337
1105
|
const opts = this.fsw.options;
|
|
1338
|
-
const directory = sp.dirname(
|
|
1339
|
-
const basename3 = sp.basename(
|
|
1106
|
+
const directory = sp.dirname(path7);
|
|
1107
|
+
const basename3 = sp.basename(path7);
|
|
1340
1108
|
const parent = this.fsw._getWatchedDir(directory);
|
|
1341
1109
|
parent.add(basename3);
|
|
1342
|
-
const absolutePath = sp.resolve(
|
|
1110
|
+
const absolutePath = sp.resolve(path7);
|
|
1343
1111
|
const options = {
|
|
1344
1112
|
persistent: opts.persistent
|
|
1345
1113
|
};
|
|
@@ -1349,12 +1117,12 @@ var NodeFsHandler = class {
|
|
|
1349
1117
|
if (opts.usePolling) {
|
|
1350
1118
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
1351
1119
|
options.interval = enableBin && isBinaryPath(basename3) ? opts.binaryInterval : opts.interval;
|
|
1352
|
-
closer = setFsWatchFileListener(
|
|
1120
|
+
closer = setFsWatchFileListener(path7, absolutePath, options, {
|
|
1353
1121
|
listener,
|
|
1354
1122
|
rawEmitter: this.fsw._emitRaw
|
|
1355
1123
|
});
|
|
1356
1124
|
} else {
|
|
1357
|
-
closer = setFsWatchListener(
|
|
1125
|
+
closer = setFsWatchListener(path7, absolutePath, options, {
|
|
1358
1126
|
listener,
|
|
1359
1127
|
errHandler: this._boundHandleError,
|
|
1360
1128
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -1376,7 +1144,7 @@ var NodeFsHandler = class {
|
|
|
1376
1144
|
let prevStats = stats;
|
|
1377
1145
|
if (parent.has(basename3))
|
|
1378
1146
|
return;
|
|
1379
|
-
const listener = async (
|
|
1147
|
+
const listener = async (path7, newStats) => {
|
|
1380
1148
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
1381
1149
|
return;
|
|
1382
1150
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -1390,11 +1158,11 @@ var NodeFsHandler = class {
|
|
|
1390
1158
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
1391
1159
|
}
|
|
1392
1160
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
1393
|
-
this.fsw._closeFile(
|
|
1161
|
+
this.fsw._closeFile(path7);
|
|
1394
1162
|
prevStats = newStats2;
|
|
1395
1163
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
1396
1164
|
if (closer2)
|
|
1397
|
-
this.fsw._addPathCloser(
|
|
1165
|
+
this.fsw._addPathCloser(path7, closer2);
|
|
1398
1166
|
} else {
|
|
1399
1167
|
prevStats = newStats2;
|
|
1400
1168
|
}
|
|
@@ -1426,7 +1194,7 @@ var NodeFsHandler = class {
|
|
|
1426
1194
|
* @param item basename of this item
|
|
1427
1195
|
* @returns true if no more processing is needed for this entry.
|
|
1428
1196
|
*/
|
|
1429
|
-
async _handleSymlink(entry, directory,
|
|
1197
|
+
async _handleSymlink(entry, directory, path7, item) {
|
|
1430
1198
|
if (this.fsw.closed) {
|
|
1431
1199
|
return;
|
|
1432
1200
|
}
|
|
@@ -1436,7 +1204,7 @@ var NodeFsHandler = class {
|
|
|
1436
1204
|
this.fsw._incrReadyCount();
|
|
1437
1205
|
let linkPath;
|
|
1438
1206
|
try {
|
|
1439
|
-
linkPath = await fsrealpath(
|
|
1207
|
+
linkPath = await fsrealpath(path7);
|
|
1440
1208
|
} catch (e) {
|
|
1441
1209
|
this.fsw._emitReady();
|
|
1442
1210
|
return true;
|
|
@@ -1446,12 +1214,12 @@ var NodeFsHandler = class {
|
|
|
1446
1214
|
if (dir.has(item)) {
|
|
1447
1215
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
1448
1216
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
1449
|
-
this.fsw._emit(EV.CHANGE,
|
|
1217
|
+
this.fsw._emit(EV.CHANGE, path7, entry.stats);
|
|
1450
1218
|
}
|
|
1451
1219
|
} else {
|
|
1452
1220
|
dir.add(item);
|
|
1453
1221
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
1454
|
-
this.fsw._emit(EV.ADD,
|
|
1222
|
+
this.fsw._emit(EV.ADD, path7, entry.stats);
|
|
1455
1223
|
}
|
|
1456
1224
|
this.fsw._emitReady();
|
|
1457
1225
|
return true;
|
|
@@ -1481,9 +1249,9 @@ var NodeFsHandler = class {
|
|
|
1481
1249
|
return;
|
|
1482
1250
|
}
|
|
1483
1251
|
const item = entry.path;
|
|
1484
|
-
let
|
|
1252
|
+
let path7 = sp.join(directory, item);
|
|
1485
1253
|
current.add(item);
|
|
1486
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
1254
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path7, item)) {
|
|
1487
1255
|
return;
|
|
1488
1256
|
}
|
|
1489
1257
|
if (this.fsw.closed) {
|
|
@@ -1492,8 +1260,8 @@ var NodeFsHandler = class {
|
|
|
1492
1260
|
}
|
|
1493
1261
|
if (item === target || !target && !previous.has(item)) {
|
|
1494
1262
|
this.fsw._incrReadyCount();
|
|
1495
|
-
|
|
1496
|
-
this._addToNodeFs(
|
|
1263
|
+
path7 = sp.join(dir, sp.relative(dir, path7));
|
|
1264
|
+
this._addToNodeFs(path7, initialAdd, wh, depth + 1);
|
|
1497
1265
|
}
|
|
1498
1266
|
}).on(EV.ERROR, this._boundHandleError);
|
|
1499
1267
|
return new Promise((resolve3, reject) => {
|
|
@@ -1562,13 +1330,13 @@ var NodeFsHandler = class {
|
|
|
1562
1330
|
* @param depth Child path actually targeted for watch
|
|
1563
1331
|
* @param target Child path actually targeted for watch
|
|
1564
1332
|
*/
|
|
1565
|
-
async _addToNodeFs(
|
|
1333
|
+
async _addToNodeFs(path7, initialAdd, priorWh, depth, target) {
|
|
1566
1334
|
const ready = this.fsw._emitReady;
|
|
1567
|
-
if (this.fsw._isIgnored(
|
|
1335
|
+
if (this.fsw._isIgnored(path7) || this.fsw.closed) {
|
|
1568
1336
|
ready();
|
|
1569
1337
|
return false;
|
|
1570
1338
|
}
|
|
1571
|
-
const wh = this.fsw._getWatchHelpers(
|
|
1339
|
+
const wh = this.fsw._getWatchHelpers(path7);
|
|
1572
1340
|
if (priorWh) {
|
|
1573
1341
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
1574
1342
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -1584,8 +1352,8 @@ var NodeFsHandler = class {
|
|
|
1584
1352
|
const follow = this.fsw.options.followSymlinks;
|
|
1585
1353
|
let closer;
|
|
1586
1354
|
if (stats.isDirectory()) {
|
|
1587
|
-
const absPath = sp.resolve(
|
|
1588
|
-
const targetPath = follow ? await fsrealpath(
|
|
1355
|
+
const absPath = sp.resolve(path7);
|
|
1356
|
+
const targetPath = follow ? await fsrealpath(path7) : path7;
|
|
1589
1357
|
if (this.fsw.closed)
|
|
1590
1358
|
return;
|
|
1591
1359
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -1595,29 +1363,29 @@ var NodeFsHandler = class {
|
|
|
1595
1363
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
1596
1364
|
}
|
|
1597
1365
|
} else if (stats.isSymbolicLink()) {
|
|
1598
|
-
const targetPath = follow ? await fsrealpath(
|
|
1366
|
+
const targetPath = follow ? await fsrealpath(path7) : path7;
|
|
1599
1367
|
if (this.fsw.closed)
|
|
1600
1368
|
return;
|
|
1601
1369
|
const parent = sp.dirname(wh.watchPath);
|
|
1602
1370
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
1603
1371
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
1604
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
1372
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path7, wh, targetPath);
|
|
1605
1373
|
if (this.fsw.closed)
|
|
1606
1374
|
return;
|
|
1607
1375
|
if (targetPath !== void 0) {
|
|
1608
|
-
this.fsw._symlinkPaths.set(sp.resolve(
|
|
1376
|
+
this.fsw._symlinkPaths.set(sp.resolve(path7), targetPath);
|
|
1609
1377
|
}
|
|
1610
1378
|
} else {
|
|
1611
1379
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
1612
1380
|
}
|
|
1613
1381
|
ready();
|
|
1614
1382
|
if (closer)
|
|
1615
|
-
this.fsw._addPathCloser(
|
|
1383
|
+
this.fsw._addPathCloser(path7, closer);
|
|
1616
1384
|
return false;
|
|
1617
1385
|
} catch (error) {
|
|
1618
1386
|
if (this.fsw._handleError(error)) {
|
|
1619
1387
|
ready();
|
|
1620
|
-
return
|
|
1388
|
+
return path7;
|
|
1621
1389
|
}
|
|
1622
1390
|
}
|
|
1623
1391
|
}
|
|
@@ -1660,24 +1428,24 @@ function createPattern(matcher) {
|
|
|
1660
1428
|
}
|
|
1661
1429
|
return () => false;
|
|
1662
1430
|
}
|
|
1663
|
-
function normalizePath(
|
|
1664
|
-
if (typeof
|
|
1431
|
+
function normalizePath(path7) {
|
|
1432
|
+
if (typeof path7 !== "string")
|
|
1665
1433
|
throw new Error("string expected");
|
|
1666
|
-
|
|
1667
|
-
|
|
1434
|
+
path7 = sp2.normalize(path7);
|
|
1435
|
+
path7 = path7.replace(/\\/g, "/");
|
|
1668
1436
|
let prepend = false;
|
|
1669
|
-
if (
|
|
1437
|
+
if (path7.startsWith("//"))
|
|
1670
1438
|
prepend = true;
|
|
1671
|
-
|
|
1439
|
+
path7 = path7.replace(DOUBLE_SLASH_RE, "/");
|
|
1672
1440
|
if (prepend)
|
|
1673
|
-
|
|
1674
|
-
return
|
|
1441
|
+
path7 = "/" + path7;
|
|
1442
|
+
return path7;
|
|
1675
1443
|
}
|
|
1676
1444
|
function matchPatterns(patterns, testString, stats) {
|
|
1677
|
-
const
|
|
1445
|
+
const path7 = normalizePath(testString);
|
|
1678
1446
|
for (let index = 0; index < patterns.length; index++) {
|
|
1679
1447
|
const pattern = patterns[index];
|
|
1680
|
-
if (pattern(
|
|
1448
|
+
if (pattern(path7, stats)) {
|
|
1681
1449
|
return true;
|
|
1682
1450
|
}
|
|
1683
1451
|
}
|
|
@@ -1715,19 +1483,19 @@ var toUnix = (string) => {
|
|
|
1715
1483
|
}
|
|
1716
1484
|
return str;
|
|
1717
1485
|
};
|
|
1718
|
-
var normalizePathToUnix = (
|
|
1719
|
-
var normalizeIgnored = (cwd = "") => (
|
|
1720
|
-
if (typeof
|
|
1721
|
-
return normalizePathToUnix(sp2.isAbsolute(
|
|
1486
|
+
var normalizePathToUnix = (path7) => toUnix(sp2.normalize(toUnix(path7)));
|
|
1487
|
+
var normalizeIgnored = (cwd = "") => (path7) => {
|
|
1488
|
+
if (typeof path7 === "string") {
|
|
1489
|
+
return normalizePathToUnix(sp2.isAbsolute(path7) ? path7 : sp2.join(cwd, path7));
|
|
1722
1490
|
} else {
|
|
1723
|
-
return
|
|
1491
|
+
return path7;
|
|
1724
1492
|
}
|
|
1725
1493
|
};
|
|
1726
|
-
var getAbsolutePath = (
|
|
1727
|
-
if (sp2.isAbsolute(
|
|
1728
|
-
return
|
|
1494
|
+
var getAbsolutePath = (path7, cwd) => {
|
|
1495
|
+
if (sp2.isAbsolute(path7)) {
|
|
1496
|
+
return path7;
|
|
1729
1497
|
}
|
|
1730
|
-
return sp2.join(cwd,
|
|
1498
|
+
return sp2.join(cwd, path7);
|
|
1731
1499
|
};
|
|
1732
1500
|
var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
1733
1501
|
var DirEntry = class {
|
|
@@ -1792,10 +1560,10 @@ var WatchHelper = class {
|
|
|
1792
1560
|
dirParts;
|
|
1793
1561
|
followSymlinks;
|
|
1794
1562
|
statMethod;
|
|
1795
|
-
constructor(
|
|
1563
|
+
constructor(path7, follow, fsw) {
|
|
1796
1564
|
this.fsw = fsw;
|
|
1797
|
-
const watchPath =
|
|
1798
|
-
this.path =
|
|
1565
|
+
const watchPath = path7;
|
|
1566
|
+
this.path = path7 = path7.replace(REPLACER_RE, "");
|
|
1799
1567
|
this.watchPath = watchPath;
|
|
1800
1568
|
this.fullWatchPath = sp2.resolve(watchPath);
|
|
1801
1569
|
this.dirParts = [];
|
|
@@ -1935,20 +1703,20 @@ var FSWatcher = class extends EventEmitter {
|
|
|
1935
1703
|
this._closePromise = void 0;
|
|
1936
1704
|
let paths = unifyPaths(paths_);
|
|
1937
1705
|
if (cwd) {
|
|
1938
|
-
paths = paths.map((
|
|
1939
|
-
const absPath = getAbsolutePath(
|
|
1706
|
+
paths = paths.map((path7) => {
|
|
1707
|
+
const absPath = getAbsolutePath(path7, cwd);
|
|
1940
1708
|
return absPath;
|
|
1941
1709
|
});
|
|
1942
1710
|
}
|
|
1943
|
-
paths.forEach((
|
|
1944
|
-
this._removeIgnoredPath(
|
|
1711
|
+
paths.forEach((path7) => {
|
|
1712
|
+
this._removeIgnoredPath(path7);
|
|
1945
1713
|
});
|
|
1946
1714
|
this._userIgnored = void 0;
|
|
1947
1715
|
if (!this._readyCount)
|
|
1948
1716
|
this._readyCount = 0;
|
|
1949
1717
|
this._readyCount += paths.length;
|
|
1950
|
-
Promise.all(paths.map(async (
|
|
1951
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
1718
|
+
Promise.all(paths.map(async (path7) => {
|
|
1719
|
+
const res = await this._nodeFsHandler._addToNodeFs(path7, !_internal, void 0, 0, _origAdd);
|
|
1952
1720
|
if (res)
|
|
1953
1721
|
this._emitReady();
|
|
1954
1722
|
return res;
|
|
@@ -1970,17 +1738,17 @@ var FSWatcher = class extends EventEmitter {
|
|
|
1970
1738
|
return this;
|
|
1971
1739
|
const paths = unifyPaths(paths_);
|
|
1972
1740
|
const { cwd } = this.options;
|
|
1973
|
-
paths.forEach((
|
|
1974
|
-
if (!sp2.isAbsolute(
|
|
1741
|
+
paths.forEach((path7) => {
|
|
1742
|
+
if (!sp2.isAbsolute(path7) && !this._closers.has(path7)) {
|
|
1975
1743
|
if (cwd)
|
|
1976
|
-
|
|
1977
|
-
|
|
1744
|
+
path7 = sp2.join(cwd, path7);
|
|
1745
|
+
path7 = sp2.resolve(path7);
|
|
1978
1746
|
}
|
|
1979
|
-
this._closePath(
|
|
1980
|
-
this._addIgnoredPath(
|
|
1981
|
-
if (this._watched.has(
|
|
1747
|
+
this._closePath(path7);
|
|
1748
|
+
this._addIgnoredPath(path7);
|
|
1749
|
+
if (this._watched.has(path7)) {
|
|
1982
1750
|
this._addIgnoredPath({
|
|
1983
|
-
path:
|
|
1751
|
+
path: path7,
|
|
1984
1752
|
recursive: true
|
|
1985
1753
|
});
|
|
1986
1754
|
}
|
|
@@ -2044,38 +1812,38 @@ var FSWatcher = class extends EventEmitter {
|
|
|
2044
1812
|
* @param stats arguments to be passed with event
|
|
2045
1813
|
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
2046
1814
|
*/
|
|
2047
|
-
async _emit(event,
|
|
1815
|
+
async _emit(event, path7, stats) {
|
|
2048
1816
|
if (this.closed)
|
|
2049
1817
|
return;
|
|
2050
1818
|
const opts = this.options;
|
|
2051
1819
|
if (isWindows)
|
|
2052
|
-
|
|
1820
|
+
path7 = sp2.normalize(path7);
|
|
2053
1821
|
if (opts.cwd)
|
|
2054
|
-
|
|
2055
|
-
const args = [
|
|
1822
|
+
path7 = sp2.relative(opts.cwd, path7);
|
|
1823
|
+
const args = [path7];
|
|
2056
1824
|
if (stats != null)
|
|
2057
1825
|
args.push(stats);
|
|
2058
1826
|
const awf = opts.awaitWriteFinish;
|
|
2059
1827
|
let pw;
|
|
2060
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
1828
|
+
if (awf && (pw = this._pendingWrites.get(path7))) {
|
|
2061
1829
|
pw.lastChange = /* @__PURE__ */ new Date();
|
|
2062
1830
|
return this;
|
|
2063
1831
|
}
|
|
2064
1832
|
if (opts.atomic) {
|
|
2065
1833
|
if (event === EVENTS.UNLINK) {
|
|
2066
|
-
this._pendingUnlinks.set(
|
|
1834
|
+
this._pendingUnlinks.set(path7, [event, ...args]);
|
|
2067
1835
|
setTimeout(() => {
|
|
2068
|
-
this._pendingUnlinks.forEach((entry,
|
|
1836
|
+
this._pendingUnlinks.forEach((entry, path8) => {
|
|
2069
1837
|
this.emit(...entry);
|
|
2070
1838
|
this.emit(EVENTS.ALL, ...entry);
|
|
2071
|
-
this._pendingUnlinks.delete(
|
|
1839
|
+
this._pendingUnlinks.delete(path8);
|
|
2072
1840
|
});
|
|
2073
1841
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
2074
1842
|
return this;
|
|
2075
1843
|
}
|
|
2076
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
1844
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path7)) {
|
|
2077
1845
|
event = EVENTS.CHANGE;
|
|
2078
|
-
this._pendingUnlinks.delete(
|
|
1846
|
+
this._pendingUnlinks.delete(path7);
|
|
2079
1847
|
}
|
|
2080
1848
|
}
|
|
2081
1849
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -2093,16 +1861,16 @@ var FSWatcher = class extends EventEmitter {
|
|
|
2093
1861
|
this.emitWithAll(event, args);
|
|
2094
1862
|
}
|
|
2095
1863
|
};
|
|
2096
|
-
this._awaitWriteFinish(
|
|
1864
|
+
this._awaitWriteFinish(path7, awf.stabilityThreshold, event, awfEmit);
|
|
2097
1865
|
return this;
|
|
2098
1866
|
}
|
|
2099
1867
|
if (event === EVENTS.CHANGE) {
|
|
2100
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
1868
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path7, 50);
|
|
2101
1869
|
if (isThrottled)
|
|
2102
1870
|
return this;
|
|
2103
1871
|
}
|
|
2104
1872
|
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
2105
|
-
const fullPath = opts.cwd ? sp2.join(opts.cwd,
|
|
1873
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path7) : path7;
|
|
2106
1874
|
let stats2;
|
|
2107
1875
|
try {
|
|
2108
1876
|
stats2 = await stat3(fullPath);
|
|
@@ -2133,23 +1901,23 @@ var FSWatcher = class extends EventEmitter {
|
|
|
2133
1901
|
* @param timeout duration of time to suppress duplicate actions
|
|
2134
1902
|
* @returns tracking object or false if action should be suppressed
|
|
2135
1903
|
*/
|
|
2136
|
-
_throttle(actionType,
|
|
1904
|
+
_throttle(actionType, path7, timeout) {
|
|
2137
1905
|
if (!this._throttled.has(actionType)) {
|
|
2138
1906
|
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
2139
1907
|
}
|
|
2140
1908
|
const action = this._throttled.get(actionType);
|
|
2141
1909
|
if (!action)
|
|
2142
1910
|
throw new Error("invalid throttle");
|
|
2143
|
-
const actionPath = action.get(
|
|
1911
|
+
const actionPath = action.get(path7);
|
|
2144
1912
|
if (actionPath) {
|
|
2145
1913
|
actionPath.count++;
|
|
2146
1914
|
return false;
|
|
2147
1915
|
}
|
|
2148
1916
|
let timeoutObject;
|
|
2149
1917
|
const clear = () => {
|
|
2150
|
-
const item = action.get(
|
|
1918
|
+
const item = action.get(path7);
|
|
2151
1919
|
const count = item ? item.count : 0;
|
|
2152
|
-
action.delete(
|
|
1920
|
+
action.delete(path7);
|
|
2153
1921
|
clearTimeout(timeoutObject);
|
|
2154
1922
|
if (item)
|
|
2155
1923
|
clearTimeout(item.timeoutObject);
|
|
@@ -2157,7 +1925,7 @@ var FSWatcher = class extends EventEmitter {
|
|
|
2157
1925
|
};
|
|
2158
1926
|
timeoutObject = setTimeout(clear, timeout);
|
|
2159
1927
|
const thr = { timeoutObject, clear, count: 0 };
|
|
2160
|
-
action.set(
|
|
1928
|
+
action.set(path7, thr);
|
|
2161
1929
|
return thr;
|
|
2162
1930
|
}
|
|
2163
1931
|
_incrReadyCount() {
|
|
@@ -2171,44 +1939,44 @@ var FSWatcher = class extends EventEmitter {
|
|
|
2171
1939
|
* @param event
|
|
2172
1940
|
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
2173
1941
|
*/
|
|
2174
|
-
_awaitWriteFinish(
|
|
1942
|
+
_awaitWriteFinish(path7, threshold, event, awfEmit) {
|
|
2175
1943
|
const awf = this.options.awaitWriteFinish;
|
|
2176
1944
|
if (typeof awf !== "object")
|
|
2177
1945
|
return;
|
|
2178
1946
|
const pollInterval = awf.pollInterval;
|
|
2179
1947
|
let timeoutHandler;
|
|
2180
|
-
let fullPath =
|
|
2181
|
-
if (this.options.cwd && !sp2.isAbsolute(
|
|
2182
|
-
fullPath = sp2.join(this.options.cwd,
|
|
1948
|
+
let fullPath = path7;
|
|
1949
|
+
if (this.options.cwd && !sp2.isAbsolute(path7)) {
|
|
1950
|
+
fullPath = sp2.join(this.options.cwd, path7);
|
|
2183
1951
|
}
|
|
2184
1952
|
const now = /* @__PURE__ */ new Date();
|
|
2185
1953
|
const writes = this._pendingWrites;
|
|
2186
1954
|
function awaitWriteFinishFn(prevStat) {
|
|
2187
1955
|
statcb(fullPath, (err, curStat) => {
|
|
2188
|
-
if (err || !writes.has(
|
|
1956
|
+
if (err || !writes.has(path7)) {
|
|
2189
1957
|
if (err && err.code !== "ENOENT")
|
|
2190
1958
|
awfEmit(err);
|
|
2191
1959
|
return;
|
|
2192
1960
|
}
|
|
2193
1961
|
const now2 = Number(/* @__PURE__ */ new Date());
|
|
2194
1962
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
2195
|
-
writes.get(
|
|
1963
|
+
writes.get(path7).lastChange = now2;
|
|
2196
1964
|
}
|
|
2197
|
-
const pw = writes.get(
|
|
1965
|
+
const pw = writes.get(path7);
|
|
2198
1966
|
const df = now2 - pw.lastChange;
|
|
2199
1967
|
if (df >= threshold) {
|
|
2200
|
-
writes.delete(
|
|
1968
|
+
writes.delete(path7);
|
|
2201
1969
|
awfEmit(void 0, curStat);
|
|
2202
1970
|
} else {
|
|
2203
1971
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
2204
1972
|
}
|
|
2205
1973
|
});
|
|
2206
1974
|
}
|
|
2207
|
-
if (!writes.has(
|
|
2208
|
-
writes.set(
|
|
1975
|
+
if (!writes.has(path7)) {
|
|
1976
|
+
writes.set(path7, {
|
|
2209
1977
|
lastChange: now,
|
|
2210
1978
|
cancelWait: () => {
|
|
2211
|
-
writes.delete(
|
|
1979
|
+
writes.delete(path7);
|
|
2212
1980
|
clearTimeout(timeoutHandler);
|
|
2213
1981
|
return event;
|
|
2214
1982
|
}
|
|
@@ -2219,8 +1987,8 @@ var FSWatcher = class extends EventEmitter {
|
|
|
2219
1987
|
/**
|
|
2220
1988
|
* Determines whether user has asked to ignore this path.
|
|
2221
1989
|
*/
|
|
2222
|
-
_isIgnored(
|
|
2223
|
-
if (this.options.atomic && DOT_RE.test(
|
|
1990
|
+
_isIgnored(path7, stats) {
|
|
1991
|
+
if (this.options.atomic && DOT_RE.test(path7))
|
|
2224
1992
|
return true;
|
|
2225
1993
|
if (!this._userIgnored) {
|
|
2226
1994
|
const { cwd } = this.options;
|
|
@@ -2230,17 +1998,17 @@ var FSWatcher = class extends EventEmitter {
|
|
|
2230
1998
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
2231
1999
|
this._userIgnored = anymatch(list, void 0);
|
|
2232
2000
|
}
|
|
2233
|
-
return this._userIgnored(
|
|
2001
|
+
return this._userIgnored(path7, stats);
|
|
2234
2002
|
}
|
|
2235
|
-
_isntIgnored(
|
|
2236
|
-
return !this._isIgnored(
|
|
2003
|
+
_isntIgnored(path7, stat4) {
|
|
2004
|
+
return !this._isIgnored(path7, stat4);
|
|
2237
2005
|
}
|
|
2238
2006
|
/**
|
|
2239
2007
|
* Provides a set of common helpers and properties relating to symlink handling.
|
|
2240
2008
|
* @param path file or directory pattern being watched
|
|
2241
2009
|
*/
|
|
2242
|
-
_getWatchHelpers(
|
|
2243
|
-
return new WatchHelper(
|
|
2010
|
+
_getWatchHelpers(path7) {
|
|
2011
|
+
return new WatchHelper(path7, this.options.followSymlinks, this);
|
|
2244
2012
|
}
|
|
2245
2013
|
// Directory helpers
|
|
2246
2014
|
// -----------------
|
|
@@ -2272,63 +2040,63 @@ var FSWatcher = class extends EventEmitter {
|
|
|
2272
2040
|
* @param item base path of item/directory
|
|
2273
2041
|
*/
|
|
2274
2042
|
_remove(directory, item, isDirectory) {
|
|
2275
|
-
const
|
|
2276
|
-
const fullPath = sp2.resolve(
|
|
2277
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
2278
|
-
if (!this._throttle("remove",
|
|
2043
|
+
const path7 = sp2.join(directory, item);
|
|
2044
|
+
const fullPath = sp2.resolve(path7);
|
|
2045
|
+
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path7) || this._watched.has(fullPath);
|
|
2046
|
+
if (!this._throttle("remove", path7, 100))
|
|
2279
2047
|
return;
|
|
2280
2048
|
if (!isDirectory && this._watched.size === 1) {
|
|
2281
2049
|
this.add(directory, item, true);
|
|
2282
2050
|
}
|
|
2283
|
-
const wp = this._getWatchedDir(
|
|
2051
|
+
const wp = this._getWatchedDir(path7);
|
|
2284
2052
|
const nestedDirectoryChildren = wp.getChildren();
|
|
2285
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
2053
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path7, nested));
|
|
2286
2054
|
const parent = this._getWatchedDir(directory);
|
|
2287
2055
|
const wasTracked = parent.has(item);
|
|
2288
2056
|
parent.remove(item);
|
|
2289
2057
|
if (this._symlinkPaths.has(fullPath)) {
|
|
2290
2058
|
this._symlinkPaths.delete(fullPath);
|
|
2291
2059
|
}
|
|
2292
|
-
let relPath =
|
|
2060
|
+
let relPath = path7;
|
|
2293
2061
|
if (this.options.cwd)
|
|
2294
|
-
relPath = sp2.relative(this.options.cwd,
|
|
2062
|
+
relPath = sp2.relative(this.options.cwd, path7);
|
|
2295
2063
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
2296
2064
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
2297
2065
|
if (event === EVENTS.ADD)
|
|
2298
2066
|
return;
|
|
2299
2067
|
}
|
|
2300
|
-
this._watched.delete(
|
|
2068
|
+
this._watched.delete(path7);
|
|
2301
2069
|
this._watched.delete(fullPath);
|
|
2302
2070
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
2303
|
-
if (wasTracked && !this._isIgnored(
|
|
2304
|
-
this._emit(eventName,
|
|
2305
|
-
this._closePath(
|
|
2071
|
+
if (wasTracked && !this._isIgnored(path7))
|
|
2072
|
+
this._emit(eventName, path7);
|
|
2073
|
+
this._closePath(path7);
|
|
2306
2074
|
}
|
|
2307
2075
|
/**
|
|
2308
2076
|
* Closes all watchers for a path
|
|
2309
2077
|
*/
|
|
2310
|
-
_closePath(
|
|
2311
|
-
this._closeFile(
|
|
2312
|
-
const dir = sp2.dirname(
|
|
2313
|
-
this._getWatchedDir(dir).remove(sp2.basename(
|
|
2078
|
+
_closePath(path7) {
|
|
2079
|
+
this._closeFile(path7);
|
|
2080
|
+
const dir = sp2.dirname(path7);
|
|
2081
|
+
this._getWatchedDir(dir).remove(sp2.basename(path7));
|
|
2314
2082
|
}
|
|
2315
2083
|
/**
|
|
2316
2084
|
* Closes only file-specific watchers
|
|
2317
2085
|
*/
|
|
2318
|
-
_closeFile(
|
|
2319
|
-
const closers = this._closers.get(
|
|
2086
|
+
_closeFile(path7) {
|
|
2087
|
+
const closers = this._closers.get(path7);
|
|
2320
2088
|
if (!closers)
|
|
2321
2089
|
return;
|
|
2322
2090
|
closers.forEach((closer) => closer());
|
|
2323
|
-
this._closers.delete(
|
|
2091
|
+
this._closers.delete(path7);
|
|
2324
2092
|
}
|
|
2325
|
-
_addPathCloser(
|
|
2093
|
+
_addPathCloser(path7, closer) {
|
|
2326
2094
|
if (!closer)
|
|
2327
2095
|
return;
|
|
2328
|
-
let list = this._closers.get(
|
|
2096
|
+
let list = this._closers.get(path7);
|
|
2329
2097
|
if (!list) {
|
|
2330
2098
|
list = [];
|
|
2331
|
-
this._closers.set(
|
|
2099
|
+
this._closers.set(path7, list);
|
|
2332
2100
|
}
|
|
2333
2101
|
list.push(closer);
|
|
2334
2102
|
}
|
|
@@ -2357,7 +2125,7 @@ function watch(paths, options = {}) {
|
|
|
2357
2125
|
}
|
|
2358
2126
|
|
|
2359
2127
|
// src/daemon/watcher.ts
|
|
2360
|
-
import
|
|
2128
|
+
import path3 from "path";
|
|
2361
2129
|
var PlanWatcher = class {
|
|
2362
2130
|
config;
|
|
2363
2131
|
fsWatcher = null;
|
|
@@ -2383,7 +2151,7 @@ var PlanWatcher = class {
|
|
|
2383
2151
|
source: "tool",
|
|
2384
2152
|
filePath,
|
|
2385
2153
|
sessionId: event.session_id,
|
|
2386
|
-
detail: `${event.tool_name} on plan file: ${
|
|
2154
|
+
detail: `${event.tool_name} on plan file: ${path3.basename(filePath)}`,
|
|
2387
2155
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2388
2156
|
});
|
|
2389
2157
|
}
|
|
@@ -2391,7 +2159,7 @@ var PlanWatcher = class {
|
|
|
2391
2159
|
}
|
|
2392
2160
|
startFileWatcher() {
|
|
2393
2161
|
const absPaths = this.config.watchPaths.map(
|
|
2394
|
-
(p) =>
|
|
2162
|
+
(p) => path3.resolve(this.config.projectRoot, p)
|
|
2395
2163
|
);
|
|
2396
2164
|
this.fsWatcher = watch(absPaths, {
|
|
2397
2165
|
ignoreInitial: true,
|
|
@@ -2407,7 +2175,7 @@ var PlanWatcher = class {
|
|
|
2407
2175
|
this.fsWatcher = null;
|
|
2408
2176
|
}
|
|
2409
2177
|
onFileChange(absolutePath, action) {
|
|
2410
|
-
const rel =
|
|
2178
|
+
const rel = path3.relative(this.config.projectRoot, absolutePath);
|
|
2411
2179
|
this.knownPlans.add(absolutePath);
|
|
2412
2180
|
this.config.onPlan({
|
|
2413
2181
|
source: "filesystem",
|
|
@@ -2417,95 +2185,17 @@ var PlanWatcher = class {
|
|
|
2417
2185
|
});
|
|
2418
2186
|
}
|
|
2419
2187
|
isInPlanDirectory(filePath) {
|
|
2420
|
-
const abs =
|
|
2188
|
+
const abs = path3.isAbsolute(filePath) ? filePath : path3.resolve(this.config.projectRoot, filePath);
|
|
2421
2189
|
return this.config.watchPaths.some(
|
|
2422
|
-
(wp) => abs.startsWith(
|
|
2190
|
+
(wp) => abs.startsWith(path3.resolve(this.config.projectRoot, wp))
|
|
2423
2191
|
);
|
|
2424
2192
|
}
|
|
2425
2193
|
};
|
|
2426
2194
|
|
|
2427
|
-
// src/capture/transcript-miner.ts
|
|
2428
|
-
var TranscriptMiner = class {
|
|
2429
|
-
registry;
|
|
2430
|
-
constructor(config) {
|
|
2431
|
-
this.registry = new AgentRegistry(config?.additionalAdapters);
|
|
2432
|
-
}
|
|
2433
|
-
/**
|
|
2434
|
-
* Extract all conversation turns for a session.
|
|
2435
|
-
* Convenience wrapper — delegates to getAllTurnsWithSource.
|
|
2436
|
-
*/
|
|
2437
|
-
getAllTurns(sessionId) {
|
|
2438
|
-
return this.getAllTurnsWithSource(sessionId).turns;
|
|
2439
|
-
}
|
|
2440
|
-
/**
|
|
2441
|
-
* Extract turns using the hook-provided transcript path first (fast, no scanning),
|
|
2442
|
-
* then fall back to adapter registry scanning if the path isn't provided.
|
|
2443
|
-
*/
|
|
2444
|
-
getAllTurnsWithSource(sessionId, transcriptPath) {
|
|
2445
|
-
if (transcriptPath) {
|
|
2446
|
-
const result2 = this.registry.parseTurnsFromPath(transcriptPath);
|
|
2447
|
-
if (result2) return result2;
|
|
2448
|
-
}
|
|
2449
|
-
const result = this.registry.getTranscriptTurns(sessionId);
|
|
2450
|
-
if (result) return result;
|
|
2451
|
-
return { turns: [], source: "none" };
|
|
2452
|
-
}
|
|
2453
|
-
};
|
|
2454
|
-
function extractTurnsFromBuffer(events) {
|
|
2455
|
-
const turns = [];
|
|
2456
|
-
let current = null;
|
|
2457
|
-
for (const event of events) {
|
|
2458
|
-
const type = event.type;
|
|
2459
|
-
if (type === "user_prompt") {
|
|
2460
|
-
if (current) turns.push(current);
|
|
2461
|
-
current = {
|
|
2462
|
-
prompt: String(event.prompt ?? "").slice(0, PROMPT_PREVIEW_CHARS),
|
|
2463
|
-
toolCount: 0,
|
|
2464
|
-
timestamp: String(event.timestamp ?? (/* @__PURE__ */ new Date()).toISOString())
|
|
2465
|
-
};
|
|
2466
|
-
} else if (type === "tool_use") {
|
|
2467
|
-
if (current) current.toolCount++;
|
|
2468
|
-
}
|
|
2469
|
-
}
|
|
2470
|
-
if (current) turns.push(current);
|
|
2471
|
-
return turns;
|
|
2472
|
-
}
|
|
2473
|
-
|
|
2474
|
-
// src/vault/observations.ts
|
|
2475
|
-
function writeObservationNotes(observations, sessionId, writer, index, vaultDir) {
|
|
2476
|
-
const results = [];
|
|
2477
|
-
for (const obs of observations) {
|
|
2478
|
-
const obsId = `${obs.type}-${sessionId.slice(-6)}-${Date.now()}`;
|
|
2479
|
-
const body = formatMemoryBody({
|
|
2480
|
-
title: obs.title,
|
|
2481
|
-
observationType: obs.type,
|
|
2482
|
-
content: obs.content,
|
|
2483
|
-
sessionId,
|
|
2484
|
-
root_cause: obs.root_cause,
|
|
2485
|
-
fix: obs.fix,
|
|
2486
|
-
rationale: obs.rationale,
|
|
2487
|
-
alternatives_rejected: obs.alternatives_rejected,
|
|
2488
|
-
gained: obs.gained,
|
|
2489
|
-
sacrificed: obs.sacrificed,
|
|
2490
|
-
tags: obs.tags
|
|
2491
|
-
});
|
|
2492
|
-
const relativePath = writer.writeMemory({
|
|
2493
|
-
id: obsId,
|
|
2494
|
-
observation_type: obs.type,
|
|
2495
|
-
session: sessionNoteId(sessionId),
|
|
2496
|
-
tags: obs.tags,
|
|
2497
|
-
content: body
|
|
2498
|
-
});
|
|
2499
|
-
indexNote(index, vaultDir, relativePath);
|
|
2500
|
-
results.push({ id: obsId, path: relativePath, observation: obs });
|
|
2501
|
-
}
|
|
2502
|
-
return results;
|
|
2503
|
-
}
|
|
2504
|
-
|
|
2505
2195
|
// src/artifacts/candidates.ts
|
|
2506
2196
|
import { execFileSync } from "child_process";
|
|
2507
|
-
import
|
|
2508
|
-
import
|
|
2197
|
+
import fs3 from "fs";
|
|
2198
|
+
import path4 from "path";
|
|
2509
2199
|
var EXCLUDED_FILENAMES = /* @__PURE__ */ new Set([
|
|
2510
2200
|
"claude.md",
|
|
2511
2201
|
"agents.md",
|
|
@@ -2526,7 +2216,7 @@ var EXCLUDED_PREFIXES = [
|
|
|
2526
2216
|
".github/"
|
|
2527
2217
|
];
|
|
2528
2218
|
function isExcludedPath(relativePath) {
|
|
2529
|
-
const basename3 =
|
|
2219
|
+
const basename3 = path4.basename(relativePath).toLowerCase();
|
|
2530
2220
|
if (EXCLUDED_FILENAMES.has(basename3)) return true;
|
|
2531
2221
|
const normalized = relativePath.replace(/\\/g, "/");
|
|
2532
2222
|
return EXCLUDED_PREFIXES.some((prefix) => normalized.startsWith(prefix));
|
|
@@ -2534,7 +2224,7 @@ function isExcludedPath(relativePath) {
|
|
|
2534
2224
|
function collectArtifactCandidates(filePaths, config, projectRoot) {
|
|
2535
2225
|
if (filePaths.size === 0) return [];
|
|
2536
2226
|
const extFiltered = [...filePaths].filter(
|
|
2537
|
-
(absPath) => config.artifact_extensions.includes(
|
|
2227
|
+
(absPath) => config.artifact_extensions.includes(path4.extname(absPath))
|
|
2538
2228
|
);
|
|
2539
2229
|
if (extFiltered.length === 0) return [];
|
|
2540
2230
|
const ignoredSet = getGitIgnored(extFiltered, projectRoot);
|
|
@@ -2542,8 +2232,8 @@ function collectArtifactCandidates(filePaths, config, projectRoot) {
|
|
|
2542
2232
|
for (const absPath of extFiltered) {
|
|
2543
2233
|
if (ignoredSet.has(absPath)) continue;
|
|
2544
2234
|
try {
|
|
2545
|
-
const content =
|
|
2546
|
-
const relativePath =
|
|
2235
|
+
const content = fs3.readFileSync(absPath, "utf-8");
|
|
2236
|
+
const relativePath = path4.relative(projectRoot, absPath);
|
|
2547
2237
|
if (isExcludedPath(relativePath)) continue;
|
|
2548
2238
|
candidates.push({ path: relativePath, content });
|
|
2549
2239
|
} catch {
|
|
@@ -2566,9 +2256,9 @@ function getGitIgnored(filePaths, cwd) {
|
|
|
2566
2256
|
|
|
2567
2257
|
// src/artifacts/slugify.ts
|
|
2568
2258
|
import crypto from "crypto";
|
|
2569
|
-
import
|
|
2259
|
+
import path5 from "path";
|
|
2570
2260
|
function slugifyPath(relativePath) {
|
|
2571
|
-
const ext =
|
|
2261
|
+
const ext = path5.extname(relativePath);
|
|
2572
2262
|
const withoutExt = ext ? relativePath.slice(0, -ext.length) : relativePath;
|
|
2573
2263
|
let slug = withoutExt.replace(/[/\\]/g, "-").toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "");
|
|
2574
2264
|
if (slug.length > MAX_SLUG_LENGTH) {
|
|
@@ -2580,8 +2270,8 @@ function slugifyPath(relativePath) {
|
|
|
2580
2270
|
|
|
2581
2271
|
// src/daemon/main.ts
|
|
2582
2272
|
var import_yaml = __toESM(require_dist(), 1);
|
|
2583
|
-
import
|
|
2584
|
-
import
|
|
2273
|
+
import fs4 from "fs";
|
|
2274
|
+
import path6 from "path";
|
|
2585
2275
|
function indexAndEmbed(relativePath, noteId, embeddingText, metadata, deps) {
|
|
2586
2276
|
indexNote(deps.index, deps.vaultDir, relativePath);
|
|
2587
2277
|
if (deps.vectorIndex && embeddingText) {
|
|
@@ -2634,28 +2324,28 @@ ${candidate.content}`,
|
|
|
2634
2324
|
}
|
|
2635
2325
|
}
|
|
2636
2326
|
function migrateMemoryFiles(vaultDir) {
|
|
2637
|
-
const memoriesDir =
|
|
2638
|
-
if (!
|
|
2327
|
+
const memoriesDir = path6.join(vaultDir, "memories");
|
|
2328
|
+
if (!fs4.existsSync(memoriesDir)) return 0;
|
|
2639
2329
|
let moved = 0;
|
|
2640
|
-
const entries =
|
|
2330
|
+
const entries = fs4.readdirSync(memoriesDir);
|
|
2641
2331
|
for (const entry of entries) {
|
|
2642
|
-
const fullPath =
|
|
2332
|
+
const fullPath = path6.join(memoriesDir, entry);
|
|
2643
2333
|
if (!entry.endsWith(".md")) continue;
|
|
2644
|
-
if (
|
|
2334
|
+
if (fs4.statSync(fullPath).isDirectory()) continue;
|
|
2645
2335
|
try {
|
|
2646
|
-
const content =
|
|
2336
|
+
const content = fs4.readFileSync(fullPath, "utf-8");
|
|
2647
2337
|
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
2648
2338
|
if (!fmMatch) continue;
|
|
2649
2339
|
const parsed = import_yaml.default.parse(fmMatch[1]);
|
|
2650
2340
|
const obsType = parsed.observation_type;
|
|
2651
2341
|
if (!obsType) continue;
|
|
2652
2342
|
const normalizedType = obsType.replace(/_/g, "-");
|
|
2653
|
-
const targetDir =
|
|
2654
|
-
|
|
2655
|
-
const targetPath =
|
|
2656
|
-
|
|
2343
|
+
const targetDir = path6.join(memoriesDir, normalizedType);
|
|
2344
|
+
fs4.mkdirSync(targetDir, { recursive: true });
|
|
2345
|
+
const targetPath = path6.join(targetDir, entry);
|
|
2346
|
+
fs4.renameSync(fullPath, targetPath);
|
|
2657
2347
|
const now = /* @__PURE__ */ new Date();
|
|
2658
|
-
|
|
2348
|
+
fs4.utimesSync(targetPath, now, now);
|
|
2659
2349
|
moved++;
|
|
2660
2350
|
} catch {
|
|
2661
2351
|
}
|
|
@@ -2668,9 +2358,9 @@ async function main() {
|
|
|
2668
2358
|
process.stderr.write("Usage: mycod --vault <path>\n");
|
|
2669
2359
|
process.exit(1);
|
|
2670
2360
|
}
|
|
2671
|
-
const vaultDir =
|
|
2361
|
+
const vaultDir = path6.resolve(vaultArg);
|
|
2672
2362
|
const config = loadConfig(vaultDir);
|
|
2673
|
-
const logger = new DaemonLogger(
|
|
2363
|
+
const logger = new DaemonLogger(path6.join(vaultDir, "logs"), {
|
|
2674
2364
|
level: config.daemon.log_level,
|
|
2675
2365
|
maxSize: config.daemon.max_log_size
|
|
2676
2366
|
});
|
|
@@ -2692,14 +2382,14 @@ async function main() {
|
|
|
2692
2382
|
let vectorIndex = null;
|
|
2693
2383
|
try {
|
|
2694
2384
|
const testEmbed = await embeddingProvider.embed("test");
|
|
2695
|
-
vectorIndex = new VectorIndex(
|
|
2385
|
+
vectorIndex = new VectorIndex(path6.join(vaultDir, "vectors.db"), testEmbed.dimensions);
|
|
2696
2386
|
logger.info("embeddings", "Vector index initialized", { dimensions: testEmbed.dimensions });
|
|
2697
2387
|
} catch (error) {
|
|
2698
2388
|
logger.warn("embeddings", "Vector index unavailable", { error: error.message });
|
|
2699
2389
|
}
|
|
2700
2390
|
const processor = new BufferProcessor(llmProvider, config.intelligence.llm.context_window);
|
|
2701
2391
|
const vault = new VaultWriter(vaultDir);
|
|
2702
|
-
const index = new MycoIndex(
|
|
2392
|
+
const index = new MycoIndex(path6.join(vaultDir, "index.db"));
|
|
2703
2393
|
const lineageGraph = new LineageGraph(vaultDir);
|
|
2704
2394
|
const transcriptMiner = new TranscriptMiner({
|
|
2705
2395
|
additionalAdapters: config.capture.transcript_paths.map(
|
|
@@ -2708,17 +2398,17 @@ async function main() {
|
|
|
2708
2398
|
});
|
|
2709
2399
|
let activeStopProcessing = null;
|
|
2710
2400
|
const indexDeps = { index, vaultDir, vectorIndex, embeddingProvider, logger };
|
|
2711
|
-
const bufferDir =
|
|
2401
|
+
const bufferDir = path6.join(vaultDir, "buffer");
|
|
2712
2402
|
const sessionBuffers = /* @__PURE__ */ new Map();
|
|
2713
2403
|
const sessionFilePaths = /* @__PURE__ */ new Map();
|
|
2714
2404
|
const capturedArtifactPaths = /* @__PURE__ */ new Map();
|
|
2715
|
-
if (
|
|
2405
|
+
if (fs4.existsSync(bufferDir)) {
|
|
2716
2406
|
const cutoff = Date.now() - STALE_BUFFER_MAX_AGE_MS;
|
|
2717
|
-
for (const file of
|
|
2718
|
-
const filePath =
|
|
2719
|
-
const stat4 =
|
|
2407
|
+
for (const file of fs4.readdirSync(bufferDir)) {
|
|
2408
|
+
const filePath = path6.join(bufferDir, file);
|
|
2409
|
+
const stat4 = fs4.statSync(filePath);
|
|
2720
2410
|
if (stat4.mtimeMs < cutoff) {
|
|
2721
|
-
|
|
2411
|
+
fs4.unlinkSync(filePath);
|
|
2722
2412
|
logger.debug("daemon", "Cleaned stale buffer", { file });
|
|
2723
2413
|
}
|
|
2724
2414
|
}
|
|
@@ -2754,10 +2444,10 @@ async function main() {
|
|
|
2754
2444
|
logger.info("watcher", "Plan detected", { source: event.source, file: event.filePath });
|
|
2755
2445
|
if (event.filePath) {
|
|
2756
2446
|
try {
|
|
2757
|
-
const content =
|
|
2758
|
-
const relativePath =
|
|
2759
|
-
const title = content.match(/^#\s+(.+)$/m)?.[1] ??
|
|
2760
|
-
const planId = `plan-${
|
|
2447
|
+
const content = fs4.readFileSync(event.filePath, "utf-8");
|
|
2448
|
+
const relativePath = path6.relative(vaultDir, event.filePath);
|
|
2449
|
+
const title = content.match(/^#\s+(.+)$/m)?.[1] ?? path6.basename(event.filePath);
|
|
2450
|
+
const planId = `plan-${path6.basename(event.filePath, ".md")}`;
|
|
2761
2451
|
indexAndEmbed(
|
|
2762
2452
|
relativePath,
|
|
2763
2453
|
planId,
|
|
@@ -2808,7 +2498,7 @@ ${content}`,
|
|
|
2808
2498
|
}
|
|
2809
2499
|
const captured = capturedArtifactPaths.get(sessionId);
|
|
2810
2500
|
for (const c of candidates) {
|
|
2811
|
-
const absPath =
|
|
2501
|
+
const absPath = path6.resolve(process.cwd(), c.path);
|
|
2812
2502
|
captured.add(absPath);
|
|
2813
2503
|
}
|
|
2814
2504
|
}).catch((err) => logger.warn("processor", "Incremental artifact capture failed", {
|
|
@@ -2847,14 +2537,14 @@ ${content}`,
|
|
|
2847
2537
|
registry.unregister(session_id);
|
|
2848
2538
|
try {
|
|
2849
2539
|
const cutoff = Date.now() - STALE_BUFFER_MAX_AGE_MS;
|
|
2850
|
-
for (const file of
|
|
2540
|
+
for (const file of fs4.readdirSync(bufferDir)) {
|
|
2851
2541
|
if (!file.endsWith(".jsonl")) continue;
|
|
2852
2542
|
const bufferSessionId = file.replace(".jsonl", "");
|
|
2853
2543
|
if (bufferSessionId === session_id) continue;
|
|
2854
|
-
const filePath =
|
|
2855
|
-
const stat4 =
|
|
2544
|
+
const filePath = path6.join(bufferDir, file);
|
|
2545
|
+
const stat4 = fs4.statSync(filePath);
|
|
2856
2546
|
if (stat4.mtimeMs < cutoff) {
|
|
2857
|
-
|
|
2547
|
+
fs4.unlinkSync(filePath);
|
|
2858
2548
|
logger.debug("daemon", "Cleaned stale buffer", { file });
|
|
2859
2549
|
}
|
|
2860
2550
|
}
|
|
@@ -2949,15 +2639,15 @@ ${content}`,
|
|
|
2949
2639
|
}
|
|
2950
2640
|
const ended = (/* @__PURE__ */ new Date()).toISOString();
|
|
2951
2641
|
let started = allTurns.length > 0 && allTurns[0].timestamp ? allTurns[0].timestamp : ended;
|
|
2952
|
-
const sessionsDir =
|
|
2642
|
+
const sessionsDir = path6.join(vaultDir, "sessions");
|
|
2953
2643
|
const sessionFileName = `${sessionNoteId(sessionId)}.md`;
|
|
2954
2644
|
let existingContent;
|
|
2955
2645
|
const duplicatePaths = [];
|
|
2956
2646
|
try {
|
|
2957
|
-
for (const dateDir of
|
|
2958
|
-
const candidate =
|
|
2647
|
+
for (const dateDir of fs4.readdirSync(sessionsDir)) {
|
|
2648
|
+
const candidate = path6.join(sessionsDir, dateDir, sessionFileName);
|
|
2959
2649
|
try {
|
|
2960
|
-
const content =
|
|
2650
|
+
const content = fs4.readFileSync(candidate, "utf-8");
|
|
2961
2651
|
if (!existingContent || content.length > existingContent.length) {
|
|
2962
2652
|
existingContent = content;
|
|
2963
2653
|
}
|
|
@@ -3017,20 +2707,20 @@ ${conversationText}`;
|
|
|
3017
2707
|
}
|
|
3018
2708
|
const date = started.slice(0, 10);
|
|
3019
2709
|
const relativePath = sessionRelativePath(sessionId, date);
|
|
3020
|
-
const targetFullPath =
|
|
2710
|
+
const targetFullPath = path6.join(vaultDir, relativePath);
|
|
3021
2711
|
for (const dup of duplicatePaths) {
|
|
3022
2712
|
if (dup !== targetFullPath) {
|
|
3023
2713
|
try {
|
|
3024
|
-
|
|
2714
|
+
fs4.unlinkSync(dup);
|
|
3025
2715
|
logger.debug("lifecycle", "Removed duplicate session file", { path: dup });
|
|
3026
2716
|
} catch {
|
|
3027
2717
|
}
|
|
3028
2718
|
}
|
|
3029
2719
|
}
|
|
3030
|
-
const attachmentsDir =
|
|
2720
|
+
const attachmentsDir = path6.join(vaultDir, "attachments");
|
|
3031
2721
|
const hasImages = allTurns.some((t) => t.images?.length);
|
|
3032
2722
|
if (hasImages) {
|
|
3033
|
-
|
|
2723
|
+
fs4.mkdirSync(attachmentsDir, { recursive: true });
|
|
3034
2724
|
}
|
|
3035
2725
|
const turnImageNames = /* @__PURE__ */ new Map();
|
|
3036
2726
|
for (let i = 0; i < allTurns.length; i++) {
|
|
@@ -3041,9 +2731,9 @@ ${conversationText}`;
|
|
|
3041
2731
|
const img = turn.images[j];
|
|
3042
2732
|
const ext = extensionForMimeType(img.mediaType);
|
|
3043
2733
|
const filename = `${bareSessionId(sessionId)}-t${i + 1}-${j + 1}.${ext}`;
|
|
3044
|
-
const filePath =
|
|
3045
|
-
if (!
|
|
3046
|
-
|
|
2734
|
+
const filePath = path6.join(attachmentsDir, filename);
|
|
2735
|
+
if (!fs4.existsSync(filePath)) {
|
|
2736
|
+
fs4.writeFileSync(filePath, Buffer.from(img.data, "base64"));
|
|
3047
2737
|
logger.debug("processor", "Image saved", { filename, turn: i + 1 });
|
|
3048
2738
|
}
|
|
3049
2739
|
names.push(filename);
|
|
@@ -3256,4 +2946,4 @@ export {
|
|
|
3256
2946
|
chokidar/index.js:
|
|
3257
2947
|
(*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) *)
|
|
3258
2948
|
*/
|
|
3259
|
-
//# sourceMappingURL=main-
|
|
2949
|
+
//# sourceMappingURL=main-DTWU4OAH.js.map
|