@lossless-claude/lcm 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/commands/lcm-compact.md +31 -0
- package/.claude-plugin/commands/lcm-curate.md +31 -0
- package/.claude-plugin/commands/lcm-diagnose.md +29 -0
- package/.claude-plugin/commands/lcm-doctor.md +23 -0
- package/.claude-plugin/commands/lcm-dogfood.md +101 -0
- package/.claude-plugin/commands/lcm-import.md +48 -0
- package/.claude-plugin/commands/lcm-promote.md +29 -0
- package/.claude-plugin/commands/lcm-sensitive.md +55 -0
- package/.claude-plugin/commands/lcm-stats.md +19 -0
- package/.claude-plugin/commands/lcm-status.md +27 -0
- package/.claude-plugin/hooks/README.md +47 -0
- package/.claude-plugin/marketplace.json +20 -0
- package/.claude-plugin/mcp.mjs +12 -0
- package/.claude-plugin/plugin.json +46 -0
- package/.claude-plugin/skills/lcm-context/SKILL.md +107 -0
- package/.claude-plugin/skills/lcm-dogfood/SKILL.md +102 -0
- package/.claude-plugin/skills/lcm-dogfood/references/checks.md +239 -0
- package/.claude-plugin/skills/lcm-dogfood/references/known-issues.md +11 -0
- package/.claude-plugin/skills/lcm-dogfood/scripts/db-integrity.js +40 -0
- package/.claude-plugin/skills/lcm-dogfood/scripts/prompt-search-test.js +35 -0
- package/.claude-plugin/skills/lcm-e2e/SKILL.md +61 -0
- package/.claude-plugin/skills/lcm-e2e/checklist.md +367 -0
- package/.claude-plugin/skills/lossless-claude-upgrade/SKILL.md +47 -0
- package/LICENSE +21 -0
- package/README.md +231 -0
- package/dist/bin/lcm.d.ts +2 -0
- package/dist/bin/lcm.js +461 -0
- package/dist/bin/lcm.js.map +1 -0
- package/dist/installer/dry-run-deps.d.ts +23 -0
- package/dist/installer/dry-run-deps.js +66 -0
- package/dist/installer/dry-run-deps.js.map +1 -0
- package/dist/installer/install.d.ts +39 -0
- package/dist/installer/install.js +236 -0
- package/dist/installer/install.js.map +1 -0
- package/dist/installer/uninstall.d.ts +11 -0
- package/dist/installer/uninstall.js +80 -0
- package/dist/installer/uninstall.js.map +1 -0
- package/dist/src/batch-compact.d.ts +16 -0
- package/dist/src/batch-compact.js +121 -0
- package/dist/src/batch-compact.js.map +1 -0
- package/dist/src/compaction.d.ts +198 -0
- package/dist/src/compaction.js +964 -0
- package/dist/src/compaction.js.map +1 -0
- package/dist/src/connectors/constants.d.ts +5 -0
- package/dist/src/connectors/constants.js +6 -0
- package/dist/src/connectors/constants.js.map +1 -0
- package/dist/src/connectors/installer.d.ts +16 -0
- package/dist/src/connectors/installer.js +200 -0
- package/dist/src/connectors/installer.js.map +1 -0
- package/dist/src/connectors/registry.d.ts +4 -0
- package/dist/src/connectors/registry.js +264 -0
- package/dist/src/connectors/registry.js.map +1 -0
- package/dist/src/connectors/template-service.d.ts +5 -0
- package/dist/src/connectors/template-service.js +54 -0
- package/dist/src/connectors/template-service.js.map +1 -0
- package/dist/src/connectors/templates/base.md +1 -0
- package/dist/src/connectors/templates/mcp-base.md +1 -0
- package/dist/src/connectors/templates/sections/command-reference.md +15 -0
- package/dist/src/connectors/templates/sections/mcp-workflow.md +18 -0
- package/dist/src/connectors/templates/sections/workflow.md +29 -0
- package/dist/src/connectors/templates/skill/SKILL.md +74 -0
- package/dist/src/connectors/types.d.ts +19 -0
- package/dist/src/connectors/types.js +10 -0
- package/dist/src/connectors/types.js.map +1 -0
- package/dist/src/daemon/client.d.ts +9 -0
- package/dist/src/daemon/client.js +28 -0
- package/dist/src/daemon/client.js.map +1 -0
- package/dist/src/daemon/config.d.ts +48 -0
- package/dist/src/daemon/config.js +67 -0
- package/dist/src/daemon/config.js.map +1 -0
- package/dist/src/daemon/lifecycle.d.ts +19 -0
- package/dist/src/daemon/lifecycle.js +102 -0
- package/dist/src/daemon/lifecycle.js.map +1 -0
- package/dist/src/daemon/orientation.d.ts +1 -0
- package/dist/src/daemon/orientation.js +9 -0
- package/dist/src/daemon/orientation.js.map +1 -0
- package/dist/src/daemon/project-queue.d.ts +1 -0
- package/dist/src/daemon/project-queue.js +17 -0
- package/dist/src/daemon/project-queue.js.map +1 -0
- package/dist/src/daemon/project.d.ts +7 -0
- package/dist/src/daemon/project.js +25 -0
- package/dist/src/daemon/project.js.map +1 -0
- package/dist/src/daemon/proxy-manager.d.ts +21 -0
- package/dist/src/daemon/proxy-manager.js +205 -0
- package/dist/src/daemon/proxy-manager.js.map +1 -0
- package/dist/src/daemon/routes/compact.d.ts +13 -0
- package/dist/src/daemon/routes/compact.js +195 -0
- package/dist/src/daemon/routes/compact.js.map +1 -0
- package/dist/src/daemon/routes/describe.d.ts +3 -0
- package/dist/src/daemon/routes/describe.js +39 -0
- package/dist/src/daemon/routes/describe.js.map +1 -0
- package/dist/src/daemon/routes/expand.d.ts +3 -0
- package/dist/src/daemon/routes/expand.js +41 -0
- package/dist/src/daemon/routes/expand.js.map +1 -0
- package/dist/src/daemon/routes/grep.d.ts +3 -0
- package/dist/src/daemon/routes/grep.js +43 -0
- package/dist/src/daemon/routes/grep.js.map +1 -0
- package/dist/src/daemon/routes/ingest.d.ts +3 -0
- package/dist/src/daemon/routes/ingest.js +101 -0
- package/dist/src/daemon/routes/ingest.js.map +1 -0
- package/dist/src/daemon/routes/promote.d.ts +4 -0
- package/dist/src/daemon/routes/promote.js +104 -0
- package/dist/src/daemon/routes/promote.js.map +1 -0
- package/dist/src/daemon/routes/prompt-search.d.ts +3 -0
- package/dist/src/daemon/routes/prompt-search.js +65 -0
- package/dist/src/daemon/routes/prompt-search.js.map +1 -0
- package/dist/src/daemon/routes/recent.d.ts +3 -0
- package/dist/src/daemon/routes/recent.js +37 -0
- package/dist/src/daemon/routes/recent.js.map +1 -0
- package/dist/src/daemon/routes/restore.d.ts +3 -0
- package/dist/src/daemon/routes/restore.js +120 -0
- package/dist/src/daemon/routes/restore.js.map +1 -0
- package/dist/src/daemon/routes/search.d.ts +2 -0
- package/dist/src/daemon/routes/search.js +66 -0
- package/dist/src/daemon/routes/search.js.map +1 -0
- package/dist/src/daemon/routes/status.d.ts +3 -0
- package/dist/src/daemon/routes/status.js +80 -0
- package/dist/src/daemon/routes/status.js.map +1 -0
- package/dist/src/daemon/routes/store.d.ts +2 -0
- package/dist/src/daemon/routes/store.js +46 -0
- package/dist/src/daemon/routes/store.js.map +1 -0
- package/dist/src/daemon/server.d.ts +19 -0
- package/dist/src/daemon/server.js +183 -0
- package/dist/src/daemon/server.js.map +1 -0
- package/dist/src/daemon/summarizer.d.ts +11 -0
- package/dist/src/daemon/summarizer.js +51 -0
- package/dist/src/daemon/summarizer.js.map +1 -0
- package/dist/src/db/config.d.ts +31 -0
- package/dist/src/db/config.js +83 -0
- package/dist/src/db/config.js.map +1 -0
- package/dist/src/db/connection.d.ts +3 -0
- package/dist/src/db/connection.js +62 -0
- package/dist/src/db/connection.js.map +1 -0
- package/dist/src/db/features.d.ts +11 -0
- package/dist/src/db/features.js +36 -0
- package/dist/src/db/features.js.map +1 -0
- package/dist/src/db/migration.d.ts +4 -0
- package/dist/src/db/migration.js +499 -0
- package/dist/src/db/migration.js.map +1 -0
- package/dist/src/db/promoted.d.ts +47 -0
- package/dist/src/db/promoted.js +96 -0
- package/dist/src/db/promoted.js.map +1 -0
- package/dist/src/db/redaction-stats.d.ts +6 -0
- package/dist/src/db/redaction-stats.js +16 -0
- package/dist/src/db/redaction-stats.js.map +1 -0
- package/dist/src/diagnose.d.ts +39 -0
- package/dist/src/diagnose.js +432 -0
- package/dist/src/diagnose.js.map +1 -0
- package/dist/src/doctor/doctor.d.ts +4 -0
- package/dist/src/doctor/doctor.js +378 -0
- package/dist/src/doctor/doctor.js.map +1 -0
- package/dist/src/doctor/types.d.ts +24 -0
- package/dist/src/doctor/types.js +2 -0
- package/dist/src/doctor/types.js.map +1 -0
- package/dist/src/expansion.d.ts +100 -0
- package/dist/src/expansion.js +268 -0
- package/dist/src/expansion.js.map +1 -0
- package/dist/src/hooks/auto-heal.d.ts +12 -0
- package/dist/src/hooks/auto-heal.js +49 -0
- package/dist/src/hooks/auto-heal.js.map +1 -0
- package/dist/src/hooks/compact.d.ts +5 -0
- package/dist/src/hooks/compact.js +22 -0
- package/dist/src/hooks/compact.js.map +1 -0
- package/dist/src/hooks/dispatch.d.ts +7 -0
- package/dist/src/hooks/dispatch.js +36 -0
- package/dist/src/hooks/dispatch.js.map +1 -0
- package/dist/src/hooks/probe-precompact.d.ts +2 -0
- package/dist/src/hooks/probe-precompact.js +17 -0
- package/dist/src/hooks/probe-precompact.js.map +1 -0
- package/dist/src/hooks/probe-sessionstart.d.ts +2 -0
- package/dist/src/hooks/probe-sessionstart.js +18 -0
- package/dist/src/hooks/probe-sessionstart.js.map +1 -0
- package/dist/src/hooks/restore.d.ts +5 -0
- package/dist/src/hooks/restore.js +19 -0
- package/dist/src/hooks/restore.js.map +1 -0
- package/dist/src/hooks/session-end.d.ts +16 -0
- package/dist/src/hooks/session-end.js +73 -0
- package/dist/src/hooks/session-end.js.map +1 -0
- package/dist/src/hooks/user-prompt.d.ts +5 -0
- package/dist/src/hooks/user-prompt.js +31 -0
- package/dist/src/hooks/user-prompt.js.map +1 -0
- package/dist/src/import.d.ts +24 -0
- package/dist/src/import.js +119 -0
- package/dist/src/import.js.map +1 -0
- package/dist/src/large-files.d.ts +28 -0
- package/dist/src/large-files.js +413 -0
- package/dist/src/large-files.js.map +1 -0
- package/dist/src/llm/anthropic.d.ts +9 -0
- package/dist/src/llm/anthropic.js +54 -0
- package/dist/src/llm/anthropic.js.map +1 -0
- package/dist/src/llm/claude-process.d.ts +2 -0
- package/dist/src/llm/claude-process.js +55 -0
- package/dist/src/llm/claude-process.js.map +1 -0
- package/dist/src/llm/codex-process.d.ts +15 -0
- package/dist/src/llm/codex-process.js +142 -0
- package/dist/src/llm/codex-process.js.map +1 -0
- package/dist/src/llm/mock-summarizer.d.ts +9 -0
- package/dist/src/llm/mock-summarizer.js +17 -0
- package/dist/src/llm/mock-summarizer.js.map +1 -0
- package/dist/src/llm/openai.d.ts +10 -0
- package/dist/src/llm/openai.js +52 -0
- package/dist/src/llm/openai.js.map +1 -0
- package/dist/src/llm/types.d.ts +6 -0
- package/dist/src/llm/types.js +2 -0
- package/dist/src/llm/types.js.map +1 -0
- package/dist/src/mcp/server.d.ts +9 -0
- package/dist/src/mcp/server.js +128 -0
- package/dist/src/mcp/server.js.map +1 -0
- package/dist/src/mcp/tools/lcm-describe.d.ts +14 -0
- package/dist/src/mcp/tools/lcm-describe.js +12 -0
- package/dist/src/mcp/tools/lcm-describe.js.map +1 -0
- package/dist/src/mcp/tools/lcm-doctor.d.ts +8 -0
- package/dist/src/mcp/tools/lcm-doctor.js +9 -0
- package/dist/src/mcp/tools/lcm-doctor.js.map +1 -0
- package/dist/src/mcp/tools/lcm-expand.d.ts +18 -0
- package/dist/src/mcp/tools/lcm-expand.js +13 -0
- package/dist/src/mcp/tools/lcm-expand.js.map +1 -0
- package/dist/src/mcp/tools/lcm-grep.d.ts +27 -0
- package/dist/src/mcp/tools/lcm-grep.js +15 -0
- package/dist/src/mcp/tools/lcm-grep.js.map +1 -0
- package/dist/src/mcp/tools/lcm-search.d.ts +33 -0
- package/dist/src/mcp/tools/lcm-search.js +15 -0
- package/dist/src/mcp/tools/lcm-search.js.map +1 -0
- package/dist/src/mcp/tools/lcm-stats.d.ts +14 -0
- package/dist/src/mcp/tools/lcm-stats.js +11 -0
- package/dist/src/mcp/tools/lcm-stats.js.map +1 -0
- package/dist/src/mcp/tools/lcm-store.d.ts +26 -0
- package/dist/src/mcp/tools/lcm-store.js +22 -0
- package/dist/src/mcp/tools/lcm-store.js.map +1 -0
- package/dist/src/memory/index.d.ts +22 -0
- package/dist/src/memory/index.js +21 -0
- package/dist/src/memory/index.js.map +1 -0
- package/dist/src/promotion/dedup.d.ts +19 -0
- package/dist/src/promotion/dedup.js +42 -0
- package/dist/src/promotion/dedup.js.map +1 -0
- package/dist/src/promotion/detector.d.ts +15 -0
- package/dist/src/promotion/detector.js +31 -0
- package/dist/src/promotion/detector.js.map +1 -0
- package/dist/src/prompts/condensed-d1.yaml +38 -0
- package/dist/src/prompts/condensed-d2.yaml +32 -0
- package/dist/src/prompts/condensed-d3plus.yaml +32 -0
- package/dist/src/prompts/leaf-aggressive.yaml +34 -0
- package/dist/src/prompts/leaf-normal.yaml +34 -0
- package/dist/src/prompts/loader.d.ts +9 -0
- package/dist/src/prompts/loader.js +37 -0
- package/dist/src/prompts/loader.js.map +1 -0
- package/dist/src/prompts/promoted-merge.yaml +18 -0
- package/dist/src/prompts/system.yaml +5 -0
- package/dist/src/retrieval.d.ts +122 -0
- package/dist/src/retrieval.js +214 -0
- package/dist/src/retrieval.js.map +1 -0
- package/dist/src/scrub.d.ts +46 -0
- package/dist/src/scrub.js +184 -0
- package/dist/src/scrub.js.map +1 -0
- package/dist/src/sensitive.d.ts +4 -0
- package/dist/src/sensitive.js +258 -0
- package/dist/src/sensitive.js.map +1 -0
- package/dist/src/stats.d.ts +34 -0
- package/dist/src/stats.js +260 -0
- package/dist/src/stats.js.map +1 -0
- package/dist/src/store/conversation-store.d.ts +115 -0
- package/dist/src/store/conversation-store.js +447 -0
- package/dist/src/store/conversation-store.js.map +1 -0
- package/dist/src/store/fts5-sanitize.d.ts +23 -0
- package/dist/src/store/fts5-sanitize.js +30 -0
- package/dist/src/store/fts5-sanitize.js.map +1 -0
- package/dist/src/store/full-text-fallback.d.ts +16 -0
- package/dist/src/store/full-text-fallback.js +60 -0
- package/dist/src/store/full-text-fallback.js.map +1 -0
- package/dist/src/store/index.d.ts +4 -0
- package/dist/src/store/index.js +3 -0
- package/dist/src/store/index.js.map +1 -0
- package/dist/src/store/summary-store.d.ts +118 -0
- package/dist/src/store/summary-store.js +570 -0
- package/dist/src/store/summary-store.js.map +1 -0
- package/dist/src/summarize.d.ts +59 -0
- package/dist/src/summarize.js +619 -0
- package/dist/src/summarize.js.map +1 -0
- package/dist/src/transcript.d.ts +7 -0
- package/dist/src/transcript.js +51 -0
- package/dist/src/transcript.js.map +1 -0
- package/dist/src/types.d.ts +116 -0
- package/dist/src/types.js +8 -0
- package/dist/src/types.js.map +1 -0
- package/docs/agent-tools.md +187 -0
- package/docs/architecture.md +224 -0
- package/docs/configuration.md +168 -0
- package/docs/fts5.md +161 -0
- package/docs/hook-protocol.md +41 -0
- package/docs/privacy.md +101 -0
- package/mcp.mjs +17 -0
- package/package.json +79 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { join, dirname } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { LCM_MARKERS, LCM_TAG } from "./constants.js";
|
|
5
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
const TEMPLATES_DIR = join(__dirname, "templates");
|
|
7
|
+
function loadFile(path) {
|
|
8
|
+
return readFileSync(join(TEMPLATES_DIR, path), "utf-8");
|
|
9
|
+
}
|
|
10
|
+
function substituteVariables(template, context) {
|
|
11
|
+
let result = template;
|
|
12
|
+
for (const [key, value] of Object.entries(context)) {
|
|
13
|
+
result = result.replaceAll(`{{${key}}}`, value);
|
|
14
|
+
}
|
|
15
|
+
return result;
|
|
16
|
+
}
|
|
17
|
+
function wrapWithMarkers(content, agentName, header) {
|
|
18
|
+
const parts = [];
|
|
19
|
+
if (header)
|
|
20
|
+
parts.push(header);
|
|
21
|
+
parts.push(LCM_MARKERS.START);
|
|
22
|
+
parts.push(content);
|
|
23
|
+
parts.push('---');
|
|
24
|
+
parts.push(`${LCM_TAG} ${agentName}`);
|
|
25
|
+
parts.push(LCM_MARKERS.END);
|
|
26
|
+
return parts.join('\n');
|
|
27
|
+
}
|
|
28
|
+
export function generateRulesContent(agent) {
|
|
29
|
+
const workflow = loadFile("sections/workflow.md");
|
|
30
|
+
const commandRef = loadFile("sections/command-reference.md");
|
|
31
|
+
const base = loadFile("base.md");
|
|
32
|
+
const content = substituteVariables(base, {
|
|
33
|
+
workflow: substituteVariables(workflow, { command_reference: commandRef }),
|
|
34
|
+
});
|
|
35
|
+
return wrapWithMarkers(content, agent.name, agent.header);
|
|
36
|
+
}
|
|
37
|
+
export function generateMcpContent(agent) {
|
|
38
|
+
const mcpWorkflow = loadFile("sections/mcp-workflow.md");
|
|
39
|
+
const base = loadFile("mcp-base.md");
|
|
40
|
+
const content = substituteVariables(base, { mcp_workflow: mcpWorkflow });
|
|
41
|
+
return wrapWithMarkers(content, agent.name, agent.header);
|
|
42
|
+
}
|
|
43
|
+
export function generateSkillContent(_agent) {
|
|
44
|
+
return loadFile("skill/SKILL.md"); // Skills don't need markers — they're standalone files
|
|
45
|
+
}
|
|
46
|
+
export function generateContent(agent, type) {
|
|
47
|
+
switch (type) {
|
|
48
|
+
case 'rules': return generateRulesContent(agent);
|
|
49
|
+
case 'mcp': return generateMcpContent(agent);
|
|
50
|
+
case 'skill': return generateSkillContent(agent);
|
|
51
|
+
case 'hook': throw new Error('Hook connectors are managed by the plugin system, not the template service');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=template-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-service.js","sourceRoot":"","sources":["../../../src/connectors/template-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{{workflow}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{{mcp_workflow}}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
## Available Commands
|
|
2
|
+
|
|
3
|
+
- `lcm search "query"` — Full-text search across memory
|
|
4
|
+
- `lcm grep "pattern"` — Regex search across conversations
|
|
5
|
+
- `lcm expand "topic"` — Expand on a specific memory topic
|
|
6
|
+
- `lcm describe` — Show memory metadata and stats
|
|
7
|
+
- `lcm store "content"` — Persist knowledge to promoted memory
|
|
8
|
+
- `lcm stats` — Show compression ratios and token savings
|
|
9
|
+
- `lcm doctor` — Run diagnostics
|
|
10
|
+
- `lcm diagnose` — Scan recent Claude Code transcripts for hook and MCP issues
|
|
11
|
+
- `lcm import` — Import Claude Code session transcripts into memory
|
|
12
|
+
- `lcm import --all` — Import from all projects
|
|
13
|
+
- `lcm compact --all` — Summarize all uncompacted sessions
|
|
14
|
+
|
|
15
|
+
Run `lcm --help` for all options.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Workflow Instruction
|
|
2
|
+
|
|
3
|
+
You are a coding agent integrated with lossless-claude via MCP (Model Context Protocol).
|
|
4
|
+
|
|
5
|
+
## Core Rules
|
|
6
|
+
|
|
7
|
+
- Use the `lcm_search` tool to query memory before starting code tasks.
|
|
8
|
+
- Use the `lcm_store` tool to persist important decisions after completing work.
|
|
9
|
+
|
|
10
|
+
## Tool Usage
|
|
11
|
+
|
|
12
|
+
- `lcm_search` — Full-text search across memory
|
|
13
|
+
- `lcm_grep` — Regex search across conversations
|
|
14
|
+
- `lcm_expand` — Expand on a specific memory topic
|
|
15
|
+
- `lcm_describe` — Show memory metadata
|
|
16
|
+
- `lcm_store` — Persist knowledge to promoted memory
|
|
17
|
+
- `lcm_stats` — Show compression ratios and token savings
|
|
18
|
+
- `lcm_doctor` — Run diagnostics
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Workflow Instruction
|
|
2
|
+
|
|
3
|
+
You are a coding agent. Use the lcm CLI to manage persistent memory across sessions.
|
|
4
|
+
|
|
5
|
+
## Core Rules
|
|
6
|
+
|
|
7
|
+
- **Search first.** Before starting any code task, retrieve relevant context with `lcm search`.
|
|
8
|
+
- **Store what matters.** After completing work, use `lcm store` to persist key decisions and learnings.
|
|
9
|
+
|
|
10
|
+
## When to Search
|
|
11
|
+
|
|
12
|
+
- Writing, editing, or modifying code in this project
|
|
13
|
+
- Understanding how something works in this codebase
|
|
14
|
+
- Debugging, fixing, or troubleshooting issues
|
|
15
|
+
- Before making architectural or design decisions
|
|
16
|
+
|
|
17
|
+
## When to Store
|
|
18
|
+
|
|
19
|
+
- Completed a feature, fix, or refactor
|
|
20
|
+
- An architectural decision was made
|
|
21
|
+
- Discovered something non-obvious about the codebase
|
|
22
|
+
|
|
23
|
+
## When to Skip
|
|
24
|
+
|
|
25
|
+
- General programming concepts (not codebase-specific)
|
|
26
|
+
- Meta tasks: run tests, build, commit, create PR
|
|
27
|
+
- Simple clarifications about a previous response
|
|
28
|
+
|
|
29
|
+
{{command_reference}}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lcm-memory
|
|
3
|
+
description: Lossless context management — search and store persistent memory across sessions
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Lossless Context Management
|
|
7
|
+
|
|
8
|
+
> **Before responding to code tasks, check memory first.**
|
|
9
|
+
> Code task? → `lcm search` FIRST. Completed work? → `lcm store` BEFORE done.
|
|
10
|
+
|
|
11
|
+
You have access to a persistent memory system that survives across conversations.
|
|
12
|
+
|
|
13
|
+
## Workflow
|
|
14
|
+
|
|
15
|
+
Code task received → `lcm search` FIRST → Work → `lcm store` → Done
|
|
16
|
+
Non-code task → Just respond normally
|
|
17
|
+
|
|
18
|
+
## Commands
|
|
19
|
+
|
|
20
|
+
### 1. Search Memory
|
|
21
|
+
Retrieve relevant context before starting work.
|
|
22
|
+
```bash
|
|
23
|
+
lcm search "How is authentication implemented?"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### 2. Grep Memory
|
|
27
|
+
Regex pattern search for precise matches.
|
|
28
|
+
```bash
|
|
29
|
+
lcm grep "createDaemon|startMcpServer"
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### 3. Expand Topic
|
|
33
|
+
Get detailed expansion on a memory topic.
|
|
34
|
+
```bash
|
|
35
|
+
lcm expand "hook auto-heal system"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### 4. Store Knowledge
|
|
39
|
+
Persist important knowledge after completing work.
|
|
40
|
+
```bash
|
|
41
|
+
lcm store "Auth middleware uses JWT with 24h expiry. See src/middleware/auth.ts"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### 5. Describe Memory
|
|
45
|
+
Show metadata about the memory system.
|
|
46
|
+
```bash
|
|
47
|
+
lcm describe
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### 6. Stats
|
|
51
|
+
Show token savings and compression ratios.
|
|
52
|
+
```bash
|
|
53
|
+
lcm stats
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Decision Table
|
|
57
|
+
|
|
58
|
+
| Task Type | Search? | Store? |
|
|
59
|
+
|-----------|---------|--------|
|
|
60
|
+
| Add/create/implement feature | MUST | MUST |
|
|
61
|
+
| Fix/debug/resolve bug | MUST | MUST |
|
|
62
|
+
| Refactor/optimize/move code | MUST | MUST |
|
|
63
|
+
| Write/add tests | MUST | MUST |
|
|
64
|
+
| "How does X work?" (codebase) | MUST | Only if insights |
|
|
65
|
+
| General concept question | NO | NO |
|
|
66
|
+
| Meta task (run tests, build) | NO | NO |
|
|
67
|
+
| Git task (commit, PR, push) | NO | NO |
|
|
68
|
+
|
|
69
|
+
## Error Handling
|
|
70
|
+
|
|
71
|
+
- If `lcm` is not found: run `npm install -g @lossless-claude/lcm`
|
|
72
|
+
- If daemon is down: run `lcm daemon start --detach`
|
|
73
|
+
- If search returns nothing: memory may be empty — proceed normally
|
|
74
|
+
- Check status: `lcm doctor`
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare const CONNECTOR_TYPES: readonly ["rules", "hook", "mcp", "skill"];
|
|
2
|
+
export type ConnectorType = (typeof CONNECTOR_TYPES)[number];
|
|
3
|
+
export type AgentCategory = 'cli' | 'ai-ide' | 'vscode-ext' | 'other';
|
|
4
|
+
export interface Agent {
|
|
5
|
+
id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
category: AgentCategory;
|
|
8
|
+
defaultType: ConnectorType;
|
|
9
|
+
supportedTypes: ConnectorType[];
|
|
10
|
+
configPaths: Partial<Record<ConnectorType, string>>;
|
|
11
|
+
writeMode?: 'append' | 'overwrite';
|
|
12
|
+
header?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Whether the connector type requires an agent restart to take effect.
|
|
16
|
+
* Rules connectors are passive (agent reads on each prompt).
|
|
17
|
+
* Hook, MCP, and skill connectors need restart.
|
|
18
|
+
*/
|
|
19
|
+
export declare function requiresRestart(type: ConnectorType): boolean;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export const CONNECTOR_TYPES = ['rules', 'hook', 'mcp', 'skill'];
|
|
2
|
+
/**
|
|
3
|
+
* Whether the connector type requires an agent restart to take effect.
|
|
4
|
+
* Rules connectors are passive (agent reads on each prompt).
|
|
5
|
+
* Hook, MCP, and skill connectors need restart.
|
|
6
|
+
*/
|
|
7
|
+
export function requiresRestart(type) {
|
|
8
|
+
return type !== 'rules';
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/connectors/types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAU,CAAC;AAgB1E;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,IAAmB;IACjD,OAAO,IAAI,KAAK,OAAO,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export class DaemonClient {
|
|
2
|
+
baseUrl;
|
|
3
|
+
constructor(baseUrl) {
|
|
4
|
+
this.baseUrl = baseUrl;
|
|
5
|
+
}
|
|
6
|
+
async health() {
|
|
7
|
+
try {
|
|
8
|
+
const res = await fetch(`${this.baseUrl}/health`);
|
|
9
|
+
return res.ok ? await res.json() : null;
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
async post(path, body) {
|
|
16
|
+
const res = await fetch(`${this.baseUrl}${path}`, {
|
|
17
|
+
method: "POST",
|
|
18
|
+
headers: { "Content-Type": "application/json" },
|
|
19
|
+
body: JSON.stringify(body),
|
|
20
|
+
});
|
|
21
|
+
if (!res.ok) {
|
|
22
|
+
const err = await res.json().catch(() => ({ error: res.statusText }));
|
|
23
|
+
throw new Error(err.error ?? `HTTP ${res.status}`);
|
|
24
|
+
}
|
|
25
|
+
return await res.json();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/daemon/client.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,YAAY;IACH;IAApB,YAAoB,OAAe;QAAf,YAAO,GAAP,OAAO,CAAQ;IAAG,CAAC;IAEvC,KAAK,CAAC,MAAM;QACV,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,SAAS,CAAC,CAAC;YAClD,OAAO,GAAG,CAAC,EAAE,CAAC,CAAC,CAAE,MAAM,GAAG,CAAC,IAAI,EAAyC,CAAC,CAAC,CAAC,IAAI,CAAC;QAClF,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,IAAI,CAAC;QAAC,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,IAAI,CAAc,IAAY,EAAE,IAAa;QACjD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,EAAE;YAChD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,UAAU,EAAE,CAAC,CAAuB,CAAC;YAC5F,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,KAAK,IAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QACrD,CAAC;QACD,OAAO,MAAM,GAAG,CAAC,IAAI,EAAO,CAAC;IAC/B,CAAC;CACF"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export interface SecurityConfig {
|
|
2
|
+
/** User-defined global regex patterns (plain strings, no /.../ delimiters). */
|
|
3
|
+
sensitivePatterns: string[];
|
|
4
|
+
}
|
|
5
|
+
export type DaemonConfig = {
|
|
6
|
+
version: number;
|
|
7
|
+
daemon: {
|
|
8
|
+
port: number;
|
|
9
|
+
socketPath: string;
|
|
10
|
+
logLevel: string;
|
|
11
|
+
logMaxSizeMB: number;
|
|
12
|
+
logRetentionDays: number;
|
|
13
|
+
idleTimeoutMs: number;
|
|
14
|
+
};
|
|
15
|
+
compaction: {
|
|
16
|
+
leafTokens: number;
|
|
17
|
+
maxDepth: number;
|
|
18
|
+
autoCompactMinTokens: number;
|
|
19
|
+
promotionThresholds: {
|
|
20
|
+
minDepth: number;
|
|
21
|
+
compressionRatio: number;
|
|
22
|
+
keywords: Record<string, string[]>;
|
|
23
|
+
architecturePatterns: string[];
|
|
24
|
+
dedupBm25Threshold: number;
|
|
25
|
+
mergeMaxEntries: number;
|
|
26
|
+
confidenceDecayRate: number;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
restoration: {
|
|
30
|
+
recentSummaries: number;
|
|
31
|
+
promptSearchMinScore: number;
|
|
32
|
+
promptSearchMaxResults: number;
|
|
33
|
+
promptSnippetLength: number;
|
|
34
|
+
recencyHalfLifeHours: number;
|
|
35
|
+
crossSessionAffinity: number;
|
|
36
|
+
};
|
|
37
|
+
llm: {
|
|
38
|
+
provider: "auto" | "claude-process" | "codex-process" | "anthropic" | "openai" | "disabled";
|
|
39
|
+
model: string;
|
|
40
|
+
apiKey?: string;
|
|
41
|
+
baseURL: string;
|
|
42
|
+
};
|
|
43
|
+
summarizer: {
|
|
44
|
+
mock: boolean;
|
|
45
|
+
};
|
|
46
|
+
security: SecurityConfig;
|
|
47
|
+
};
|
|
48
|
+
export declare function loadDaemonConfig(configPath: string, overrides?: any, env?: Record<string, string | undefined>): DaemonConfig;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
const DEFAULTS = {
|
|
5
|
+
version: 1,
|
|
6
|
+
daemon: { port: 3737, socketPath: join(homedir(), ".lossless-claude", "daemon.sock"), logLevel: "info", logMaxSizeMB: 10, logRetentionDays: 7, idleTimeoutMs: 1800000 },
|
|
7
|
+
compaction: {
|
|
8
|
+
leafTokens: 1000, maxDepth: 5, autoCompactMinTokens: 10000,
|
|
9
|
+
promotionThresholds: {
|
|
10
|
+
minDepth: 2, compressionRatio: 0.3,
|
|
11
|
+
keywords: { decision: ["decided", "agreed", "will use", "going with", "chosen"], fix: ["fixed", "root cause", "workaround", "resolved"] },
|
|
12
|
+
architecturePatterns: ["src/[\\w/]+\\.ts", "[A-Z][a-zA-Z]+(Engine|Store|Service|Manager|Handler|Client)", "interface [A-Z]", "class [A-Z]"],
|
|
13
|
+
dedupBm25Threshold: 15,
|
|
14
|
+
mergeMaxEntries: 3,
|
|
15
|
+
confidenceDecayRate: 0.1,
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
restoration: { recentSummaries: 3, promptSearchMinScore: 2, promptSearchMaxResults: 3, promptSnippetLength: 200, recencyHalfLifeHours: 24, crossSessionAffinity: 0.85 },
|
|
19
|
+
llm: { provider: "auto", model: "", apiKey: "", baseURL: "" },
|
|
20
|
+
summarizer: { mock: false },
|
|
21
|
+
security: {
|
|
22
|
+
sensitivePatterns: [],
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
function deepMerge(target, source) {
|
|
26
|
+
if (!source || typeof source !== "object")
|
|
27
|
+
return target;
|
|
28
|
+
const result = { ...target };
|
|
29
|
+
for (const key of Object.keys(source)) {
|
|
30
|
+
if (source[key] !== undefined) {
|
|
31
|
+
result[key] = (typeof source[key] === "object" && !Array.isArray(source[key]) && typeof target[key] === "object")
|
|
32
|
+
? deepMerge(target[key], source[key]) : source[key];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return result;
|
|
36
|
+
}
|
|
37
|
+
export function loadDaemonConfig(configPath, overrides, env) {
|
|
38
|
+
const e = env ?? process.env;
|
|
39
|
+
let fileConfig = {};
|
|
40
|
+
try {
|
|
41
|
+
fileConfig = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
42
|
+
}
|
|
43
|
+
catch { }
|
|
44
|
+
const merged = deepMerge(structuredClone(DEFAULTS), deepMerge(fileConfig, overrides));
|
|
45
|
+
if (merged.llm.apiKey)
|
|
46
|
+
merged.llm.apiKey = merged.llm.apiKey.replace(/\$\{(\w+)\}/g, (_, k) => e[k] ?? "");
|
|
47
|
+
// Env var override: LCM_SUMMARY_PROVIDER takes precedence over config
|
|
48
|
+
const VALID_PROVIDERS = new Set(["auto", "claude-process", "codex-process", "anthropic", "openai", "disabled"]);
|
|
49
|
+
if (e.LCM_SUMMARY_PROVIDER) {
|
|
50
|
+
if (!VALID_PROVIDERS.has(e.LCM_SUMMARY_PROVIDER)) {
|
|
51
|
+
throw new Error(`[lcm] Invalid LCM_SUMMARY_PROVIDER="${e.LCM_SUMMARY_PROVIDER}". ` +
|
|
52
|
+
`Valid values: ${[...VALID_PROVIDERS].join(", ")}`);
|
|
53
|
+
}
|
|
54
|
+
merged.llm.provider = e.LCM_SUMMARY_PROVIDER;
|
|
55
|
+
}
|
|
56
|
+
// Anthropic API key fallback from env
|
|
57
|
+
if (!merged.llm.apiKey && merged.llm.provider === "anthropic" && e.ANTHROPIC_API_KEY) {
|
|
58
|
+
merged.llm.apiKey = e.ANTHROPIC_API_KEY;
|
|
59
|
+
}
|
|
60
|
+
// Validate: anthropic provider requires an API key
|
|
61
|
+
if (merged.llm.provider === "anthropic" && !merged.llm.apiKey) {
|
|
62
|
+
throw new Error("[lcm] LCM_SUMMARY_API_KEY is required when using the Anthropic provider. " +
|
|
63
|
+
"Set it in your environment or switch to 'auto', 'claude-process', or another provider.");
|
|
64
|
+
}
|
|
65
|
+
return merged;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/daemon/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
export type EnsureDaemonOptions = {
|
|
3
|
+
port: number;
|
|
4
|
+
pidFilePath: string;
|
|
5
|
+
spawnTimeoutMs: number;
|
|
6
|
+
expectedVersion?: string;
|
|
7
|
+
spawnCommand?: string;
|
|
8
|
+
spawnArgs?: string[];
|
|
9
|
+
_skipSpawn?: boolean;
|
|
10
|
+
_spawnOverride?: typeof spawn;
|
|
11
|
+
_skipHealthWait?: boolean;
|
|
12
|
+
_fetchOverride?: typeof globalThis.fetch;
|
|
13
|
+
};
|
|
14
|
+
export type EnsureDaemonResult = {
|
|
15
|
+
connected: boolean;
|
|
16
|
+
port: number;
|
|
17
|
+
spawned: boolean;
|
|
18
|
+
};
|
|
19
|
+
export declare function ensureDaemon(opts: EnsureDaemonOptions): Promise<EnsureDaemonResult>;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, unlinkSync } from "node:fs";
|
|
2
|
+
import { spawn } from "node:child_process";
|
|
3
|
+
function sleep(ms) {
|
|
4
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
5
|
+
}
|
|
6
|
+
function isProcessAlive(pid) {
|
|
7
|
+
try {
|
|
8
|
+
process.kill(pid, 0);
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function cleanStalePid(pidFilePath) {
|
|
16
|
+
try {
|
|
17
|
+
if (existsSync(pidFilePath))
|
|
18
|
+
unlinkSync(pidFilePath);
|
|
19
|
+
}
|
|
20
|
+
catch { /* ignore */ }
|
|
21
|
+
}
|
|
22
|
+
async function checkDaemonHealth(port, fetchFn) {
|
|
23
|
+
try {
|
|
24
|
+
const res = await fetchFn(`http://127.0.0.1:${port}/health`);
|
|
25
|
+
if (!res.ok)
|
|
26
|
+
return null;
|
|
27
|
+
return (await res.json());
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export async function ensureDaemon(opts) {
|
|
34
|
+
const fetchFn = opts._fetchOverride ?? globalThis.fetch;
|
|
35
|
+
// Step 1: Check if daemon is already running via health check
|
|
36
|
+
const health = await checkDaemonHealth(opts.port, fetchFn);
|
|
37
|
+
if (health?.status === "ok") {
|
|
38
|
+
// Version check — if mismatch, kill and respawn
|
|
39
|
+
if (opts.expectedVersion && health.version && health.version !== opts.expectedVersion) {
|
|
40
|
+
if (existsSync(opts.pidFilePath)) {
|
|
41
|
+
try {
|
|
42
|
+
const pid = parseInt(readFileSync(opts.pidFilePath, "utf-8").trim(), 10);
|
|
43
|
+
if (!isNaN(pid) && isProcessAlive(pid)) {
|
|
44
|
+
process.kill(pid, "SIGTERM");
|
|
45
|
+
await sleep(500);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch { /* ignore */ }
|
|
49
|
+
cleanStalePid(opts.pidFilePath);
|
|
50
|
+
}
|
|
51
|
+
// Fall through to spawn
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
return { connected: true, port: opts.port, spawned: false };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// Step 2: Check PID file for stale process
|
|
58
|
+
if (existsSync(opts.pidFilePath)) {
|
|
59
|
+
try {
|
|
60
|
+
const pid = parseInt(readFileSync(opts.pidFilePath, "utf-8").trim(), 10);
|
|
61
|
+
if (!isNaN(pid) && isProcessAlive(pid)) {
|
|
62
|
+
await sleep(1000);
|
|
63
|
+
const retry = await checkDaemonHealth(opts.port, fetchFn);
|
|
64
|
+
if (retry?.status === "ok") {
|
|
65
|
+
return { connected: true, port: opts.port, spawned: false };
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch { /* ignore */ }
|
|
70
|
+
cleanStalePid(opts.pidFilePath);
|
|
71
|
+
}
|
|
72
|
+
// Step 3: Spawn daemon (unless skipped for testing)
|
|
73
|
+
if (opts._skipSpawn) {
|
|
74
|
+
return { connected: false, port: opts.port, spawned: false };
|
|
75
|
+
}
|
|
76
|
+
const spawnCommand = opts.spawnCommand ?? process.execPath;
|
|
77
|
+
const spawnArgs = opts.spawnArgs ?? [process.argv[1], "daemon", "start"];
|
|
78
|
+
const spawnImpl = opts._spawnOverride ?? spawn;
|
|
79
|
+
const child = spawnImpl(spawnCommand, spawnArgs, {
|
|
80
|
+
detached: true,
|
|
81
|
+
stdio: "ignore",
|
|
82
|
+
env: { ...process.env },
|
|
83
|
+
});
|
|
84
|
+
child.unref();
|
|
85
|
+
if (child.pid) {
|
|
86
|
+
writeFileSync(opts.pidFilePath, String(child.pid));
|
|
87
|
+
}
|
|
88
|
+
if (opts._skipHealthWait) {
|
|
89
|
+
return { connected: false, port: opts.port, spawned: true };
|
|
90
|
+
}
|
|
91
|
+
// Step 4: Wait for health
|
|
92
|
+
const deadline = Date.now() + opts.spawnTimeoutMs;
|
|
93
|
+
while (Date.now() < deadline) {
|
|
94
|
+
const h = await checkDaemonHealth(opts.port, fetchFn);
|
|
95
|
+
if (h?.status === "ok") {
|
|
96
|
+
return { connected: true, port: opts.port, spawned: true };
|
|
97
|
+
}
|
|
98
|
+
await sleep(300);
|
|
99
|
+
}
|
|
100
|
+
return { connected: false, port: opts.port, spawned: true };
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=lifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../../src/daemon/lifecycle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function buildOrientationPrompt(): string;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function buildOrientationPrompt() {
|
|
2
|
+
return `<memory-orientation>
|
|
3
|
+
Memory system active. Guidelines:
|
|
4
|
+
- lcm_grep / lcm_expand / lcm_describe / lcm_search → conversation history and project memory
|
|
5
|
+
- Do not store directly to any memory system — lossless-claude manages persistence automatically
|
|
6
|
+
- When uncertain what was discussed or decided, use lcm_search before asking the user
|
|
7
|
+
</memory-orientation>`;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=orientation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orientation.js","sourceRoot":"","sources":["../../../src/daemon/orientation.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,sBAAsB;IACpC,OAAO;;;;;sBAKa,CAAC;AACvB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function enqueue<T>(projectId: string, fn: () => Promise<T>): Promise<T>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const queues = new Map();
|
|
2
|
+
export function enqueue(projectId, fn) {
|
|
3
|
+
const entry = queues.get(projectId) ?? { chain: Promise.resolve(), pending: 0 };
|
|
4
|
+
entry.pending++;
|
|
5
|
+
queues.set(projectId, entry);
|
|
6
|
+
const result = entry.chain.then(fn, fn); // run fn regardless of previous result
|
|
7
|
+
entry.chain = result.then(() => { }, () => { }); // swallow for chain continuity
|
|
8
|
+
// Clean up when all pending operations complete (swallow rejection to avoid unhandled promise)
|
|
9
|
+
entry.chain.then(() => {
|
|
10
|
+
entry.pending--;
|
|
11
|
+
if (entry.pending === 0) {
|
|
12
|
+
queues.delete(projectId);
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
return result;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=project-queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-queue.js","sourceRoot":"","sources":["../../../src/daemon/project-queue.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,GAAG,IAAI,GAAG,EAAqD,CAAA;AAE3E,MAAM,UAAU,OAAO,CAAI,SAAiB,EAAE,EAAoB;IAChE,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAA;IAC/E,KAAK,CAAC,OAAO,EAAE,CAAA;IACf,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;IAE5B,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA,CAAC,uCAAuC;IAC/E,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA,CAAC,+BAA+B;IAE7E,+FAA+F;IAC/F,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE;QACpB,KAAK,CAAC,OAAO,EAAE,CAAA;QACf,IAAI,KAAK,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;YACxB,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;QAC1B,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const BASE_DIR: string;
|
|
2
|
+
export declare const projectId: (cwd: string) => string;
|
|
3
|
+
export declare const projectDir: (cwd: string) => string;
|
|
4
|
+
export declare const projectDbPath: (cwd: string) => string;
|
|
5
|
+
export declare const projectMetaPath: (cwd: string) => string;
|
|
6
|
+
/** Ensures the project dir exists and writes cwd to meta.json. */
|
|
7
|
+
export declare const ensureProjectDir: (cwd: string) => string;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
export const BASE_DIR = join(homedir(), ".lossless-claude");
|
|
6
|
+
export const projectId = (cwd) => createHash("sha256").update(cwd).digest("hex");
|
|
7
|
+
export const projectDir = (cwd) => join(BASE_DIR, "projects", projectId(cwd));
|
|
8
|
+
export const projectDbPath = (cwd) => join(projectDir(cwd), "db.sqlite");
|
|
9
|
+
export const projectMetaPath = (cwd) => join(projectDir(cwd), "meta.json");
|
|
10
|
+
/** Ensures the project dir exists and writes cwd to meta.json. */
|
|
11
|
+
export const ensureProjectDir = (cwd) => {
|
|
12
|
+
const dir = projectDir(cwd);
|
|
13
|
+
mkdirSync(dir, { recursive: true });
|
|
14
|
+
const metaPath = join(dir, "meta.json");
|
|
15
|
+
let meta = { cwd };
|
|
16
|
+
if (existsSync(metaPath)) {
|
|
17
|
+
try {
|
|
18
|
+
meta = { ...JSON.parse(readFileSync(metaPath, "utf-8")), cwd };
|
|
19
|
+
}
|
|
20
|
+
catch { /* keep default */ }
|
|
21
|
+
}
|
|
22
|
+
writeFileSync(metaPath, JSON.stringify(meta, null, 2));
|
|
23
|
+
return dir;
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.js","sourceRoot":"","sources":["../../../src/daemon/project.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,kBAAkB,CAAC,CAAC;AAE5D,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAW,EAAU,EAAE,CAC/C,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAEjD,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,GAAW,EAAU,EAAE,CAChD,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;AAE7C,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,GAAW,EAAU,EAAE,CACnD,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC,CAAC;AAErC,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,GAAW,EAAU,EAAE,CACrD,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC,CAAC;AAErC,kEAAkE;AAClE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,GAAW,EAAU,EAAE;IACtD,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAC5B,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IACxC,IAAI,IAAI,GAA4B,EAAE,GAAG,EAAE,CAAC;IAC5C,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,IAAI,CAAC;YAAC,IAAI,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;IACtG,CAAC;IACD,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACvD,OAAO,GAAG,CAAC;AACb,CAAC,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface ProxyManager {
|
|
2
|
+
start(): Promise<void>;
|
|
3
|
+
stop(): Promise<void>;
|
|
4
|
+
isHealthy(): Promise<boolean>;
|
|
5
|
+
readonly port: number;
|
|
6
|
+
readonly available: boolean;
|
|
7
|
+
}
|
|
8
|
+
export type ProxyManagerOptions = {
|
|
9
|
+
port: number;
|
|
10
|
+
startupTimeoutMs: number;
|
|
11
|
+
model: string;
|
|
12
|
+
pidFilePath?: string;
|
|
13
|
+
healthPollIntervalMs?: number;
|
|
14
|
+
healthMonitorIntervalMs?: number;
|
|
15
|
+
maxHealthMisses?: number;
|
|
16
|
+
/** Override fetch for testing */
|
|
17
|
+
_fetchOverride?: typeof globalThis.fetch;
|
|
18
|
+
/** Override process.kill(pid, 0) check for testing */
|
|
19
|
+
_killCheck?: (pid: number) => boolean;
|
|
20
|
+
};
|
|
21
|
+
export declare function createClaudeCliProxyManager(opts: ProxyManagerOptions): ProxyManager;
|