tlc-claude-code 2.9.2 → 2.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/commands/tlc/build.md +7 -9
- package/.claude/commands/tlc/init.md +55 -2
- package/.claude/commands/tlc/quick.md +6 -11
- package/.claude/commands/tlc/recall.md +37 -11
- package/.claude/commands/tlc/remember.md +41 -15
- package/.claude/commands/tlc/tlc.md +40 -2
- package/.claude/hooks/tlc-session-init.sh +86 -11
- package/CLAUDE.md +1 -0
- package/package.json +1 -1
- package/server/index.js +96 -66
- package/server/package-lock.json +26 -0
- package/server/package.json +1 -0
- package/server/setup.sh +271 -271
package/server/index.js
CHANGED
|
@@ -23,9 +23,9 @@ const { parsePlan, parseBugs } = require('./lib/plan-parser');
|
|
|
23
23
|
const { autoProvision, stopDatabase } = require('./lib/auto-database');
|
|
24
24
|
const { GlobalConfig } = require('./lib/global-config');
|
|
25
25
|
const { ProjectScanner } = require('./lib/project-scanner');
|
|
26
|
-
const { createWorkspaceRouter } = require('./lib/workspace-api');
|
|
27
|
-
const { createMemoryApi } = require('./lib/memory-api');
|
|
28
|
-
const { createMemoryStoreAdapter } = require('./lib/memory-store-adapter');
|
|
26
|
+
const { createWorkspaceRouter } = require('./lib/workspace-api');
|
|
27
|
+
const { createMemoryApi } = require('./lib/memory-api');
|
|
28
|
+
const { createMemoryStoreAdapter } = require('./lib/memory-store-adapter');
|
|
29
29
|
const {
|
|
30
30
|
createUserStore,
|
|
31
31
|
createAuthMiddleware,
|
|
@@ -86,12 +86,11 @@ const cors = require('cors');
|
|
|
86
86
|
app.use(cors({ origin: true, credentials: true }));
|
|
87
87
|
|
|
88
88
|
// Workspace API
|
|
89
|
-
const globalConfig = new GlobalConfig();
|
|
90
|
-
const projectScanner = new ProjectScanner();
|
|
91
|
-
const { observeAndRemember } = require('./lib/memory-observer');
|
|
92
|
-
const { createServerMemoryCapture } = require('./lib/memory-hooks');
|
|
93
|
-
const {
|
|
94
|
-
const { checkOllamaHealth } = require('./lib/ollama-health');
|
|
89
|
+
const globalConfig = new GlobalConfig();
|
|
90
|
+
const projectScanner = new ProjectScanner();
|
|
91
|
+
const { observeAndRemember } = require('./lib/memory-observer');
|
|
92
|
+
const { createServerMemoryCapture } = require('./lib/memory-hooks');
|
|
93
|
+
const { checkOllamaHealth } = require('./lib/ollama-health');
|
|
95
94
|
|
|
96
95
|
// Initialize memory directory structure (non-blocking)
|
|
97
96
|
(async () => {
|
|
@@ -110,72 +109,103 @@ const memoryCapture = createServerMemoryCapture({
|
|
|
110
109
|
});
|
|
111
110
|
|
|
112
111
|
// Lazy-initialized memory dependencies (ESM modules loaded async)
|
|
113
|
-
const memoryDeps = {
|
|
114
|
-
observeAndRemember,
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
};
|
|
112
|
+
const memoryDeps = {
|
|
113
|
+
observeAndRemember,
|
|
114
|
+
contextEngine: null,
|
|
115
|
+
contextSearch: null,
|
|
116
|
+
semanticRecall: null,
|
|
117
|
+
vectorIndexer: null,
|
|
118
|
+
};
|
|
120
119
|
|
|
121
120
|
// Lazy init: load ESM memory modules on first use
|
|
122
121
|
let memoryInitPromise = null;
|
|
123
|
-
async function initMemoryPipeline() {
|
|
124
|
-
if (memoryInitPromise) return memoryInitPromise;
|
|
125
|
-
memoryInitPromise = (async () => {
|
|
126
|
-
try {
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
122
|
+
async function initMemoryPipeline() {
|
|
123
|
+
if (memoryInitPromise) return memoryInitPromise;
|
|
124
|
+
memoryInitPromise = (async () => {
|
|
125
|
+
try {
|
|
126
|
+
const dbPath = path.join(PROJECT_DIR, '.tlc', 'context.sqlite');
|
|
127
|
+
|
|
128
|
+
// Ensure directory exists
|
|
129
|
+
const dbDir = path.dirname(dbPath);
|
|
130
|
+
if (!fs.existsSync(dbDir)) {
|
|
131
|
+
fs.mkdirSync(dbDir, { recursive: true });
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const [{ createContextEngine }, { createSearchPipeline }, { createSearch }, { indexProject }] = await Promise.all([
|
|
135
|
+
import('@tlc/context-engine'),
|
|
136
|
+
import('@tlc/context-engine/search-pipeline'),
|
|
137
|
+
import('@tlc/context-engine/retrieval/search'),
|
|
138
|
+
import('@tlc/context-engine/retrieval/indexer'),
|
|
139
|
+
]);
|
|
140
|
+
|
|
141
|
+
const contextEngine = createContextEngine({ dbPath });
|
|
142
|
+
const search = createSearch({
|
|
143
|
+
embeddingStore: {
|
|
144
|
+
findSimilar(db, queryVec, options) {
|
|
145
|
+
return contextEngine.embeddings.findSimilar(queryVec, options);
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
const searchPipeline = createSearchPipeline({
|
|
150
|
+
search: (db, query, options = {}) => search(db, query, options),
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
memoryDeps.contextEngine = contextEngine;
|
|
154
|
+
memoryDeps.contextSearch = searchPipeline;
|
|
155
|
+
memoryDeps.vectorIndexer = {
|
|
156
|
+
indexAll: async (projectRoot) => indexProject(contextEngine.db, projectRoot),
|
|
157
|
+
};
|
|
158
|
+
memoryDeps.semanticRecall = {
|
|
159
|
+
recall: async (query, _context = {}, options = {}) => {
|
|
160
|
+
const scope = options.scope ? [options.scope] : undefined;
|
|
161
|
+
const results = await searchPipeline(contextEngine.db, query, {
|
|
162
|
+
limit: options.limit,
|
|
163
|
+
scopes: scope,
|
|
164
|
+
queryVec: options.queryVec ?? null,
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
return results.map((result) => ({
|
|
168
|
+
id: result.uri,
|
|
169
|
+
uri: result.uri,
|
|
170
|
+
text: result.body || result.title || '',
|
|
171
|
+
title: result.title || result.uri,
|
|
172
|
+
body: result.body || '',
|
|
173
|
+
score: Number.isFinite(result.score) ? result.score : 0,
|
|
174
|
+
type: result.source === 'context' ? 'context' : 'codedb',
|
|
175
|
+
source: {
|
|
176
|
+
sourceFile: result.uri,
|
|
177
|
+
provider: result.source,
|
|
178
|
+
},
|
|
179
|
+
sourceFile: result.uri,
|
|
180
|
+
permanent: false,
|
|
181
|
+
}));
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
console.log('[TLC] Memory pipeline initialized (context engine at', dbPath + ')');
|
|
186
|
+
} catch (err) {
|
|
187
|
+
console.warn('[TLC] Memory pipeline unavailable:', err.message);
|
|
188
|
+
// Non-fatal: server works without vector store
|
|
189
|
+
}
|
|
190
|
+
})();
|
|
158
191
|
return memoryInitPromise;
|
|
159
192
|
}
|
|
160
193
|
|
|
161
194
|
// Start memory init in background (non-blocking)
|
|
162
195
|
initMemoryPipeline();
|
|
163
196
|
|
|
164
|
-
const memoryApi = createMemoryApi({
|
|
165
|
-
semanticRecall: { recall: async (...args) => {
|
|
166
|
-
await initMemoryPipeline();
|
|
167
|
-
return memoryDeps.semanticRecall ? memoryDeps.semanticRecall.recall(...args) : [];
|
|
168
|
-
}},
|
|
169
|
-
vectorIndexer: { indexAll: async (...args) => {
|
|
170
|
-
await initMemoryPipeline();
|
|
171
|
-
return memoryDeps.vectorIndexer ? memoryDeps.vectorIndexer.indexAll(...args) : { indexed: 0 };
|
|
172
|
-
}},
|
|
173
|
-
richCapture: { processChunk: async () => ({ stored: false }) },
|
|
174
|
-
embeddingClient: { embed: async (
|
|
175
|
-
|
|
176
|
-
return memoryDeps.embeddingClient ? memoryDeps.embeddingClient.embed(...args) : [];
|
|
177
|
-
}},
|
|
178
|
-
memoryStore: (() => {
|
|
197
|
+
const memoryApi = createMemoryApi({
|
|
198
|
+
semanticRecall: { recall: async (...args) => {
|
|
199
|
+
await initMemoryPipeline();
|
|
200
|
+
return memoryDeps.semanticRecall ? memoryDeps.semanticRecall.recall(...args) : [];
|
|
201
|
+
}},
|
|
202
|
+
vectorIndexer: { indexAll: async (...args) => {
|
|
203
|
+
await initMemoryPipeline();
|
|
204
|
+
return memoryDeps.vectorIndexer ? memoryDeps.vectorIndexer.indexAll(...args) : { indexed: 0 };
|
|
205
|
+
}},
|
|
206
|
+
richCapture: { processChunk: async () => ({ stored: false }) },
|
|
207
|
+
embeddingClient: { embed: async () => [] },
|
|
208
|
+
memoryStore: (() => {
|
|
179
209
|
const adapter = createMemoryStoreAdapter(PROJECT_DIR);
|
|
180
210
|
return {
|
|
181
211
|
listConversations: async () => ({ items: [], total: 0 }), // TODO Phase 74: rich conversation capture
|
package/server/package-lock.json
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@electric-sql/pglite": "^0.3.15",
|
|
12
12
|
"@electric-sql/pglite-socket": "^0.0.20",
|
|
13
|
+
"@tlc/context-engine": "file:../../tlc-context-engine",
|
|
13
14
|
"better-sqlite3": "^12.6.2",
|
|
14
15
|
"chokidar": "^3.5.3",
|
|
15
16
|
"cookie-parser": "^1.4.7",
|
|
@@ -22,6 +23,7 @@
|
|
|
22
23
|
"sqlite-vec": "^0.1.7-alpha.2",
|
|
23
24
|
"ssh2": "^1.17.0",
|
|
24
25
|
"sudo-prompt": "^9.2.1",
|
|
26
|
+
"tlc-context-engine": "^0.1.0",
|
|
25
27
|
"typescript": "^5.9.3",
|
|
26
28
|
"ws": "^8.14.2"
|
|
27
29
|
},
|
|
@@ -33,6 +35,17 @@
|
|
|
33
35
|
"vitest": "^4.0.18"
|
|
34
36
|
}
|
|
35
37
|
},
|
|
38
|
+
"../../tlc-context-engine": {
|
|
39
|
+
"version": "0.1.0",
|
|
40
|
+
"license": "MIT",
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"better-sqlite3": "^11.9.1",
|
|
43
|
+
"vitest": "^3.2.4"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"better-sqlite3": ">=11.0.0"
|
|
47
|
+
}
|
|
48
|
+
},
|
|
36
49
|
"node_modules/@balena/dockerignore": {
|
|
37
50
|
"version": "1.0.2",
|
|
38
51
|
"resolved": "https://registry.npmjs.org/@balena/dockerignore/-/dockerignore-1.0.2.tgz",
|
|
@@ -1009,6 +1022,10 @@
|
|
|
1009
1022
|
"dev": true,
|
|
1010
1023
|
"license": "MIT"
|
|
1011
1024
|
},
|
|
1025
|
+
"node_modules/@tlc/context-engine": {
|
|
1026
|
+
"resolved": "../../tlc-context-engine",
|
|
1027
|
+
"link": true
|
|
1028
|
+
},
|
|
1012
1029
|
"node_modules/@types/chai": {
|
|
1013
1030
|
"version": "5.2.3",
|
|
1014
1031
|
"resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz",
|
|
@@ -3714,6 +3731,15 @@
|
|
|
3714
3731
|
"node": ">=14.0.0"
|
|
3715
3732
|
}
|
|
3716
3733
|
},
|
|
3734
|
+
"node_modules/tlc-context-engine": {
|
|
3735
|
+
"version": "0.1.0",
|
|
3736
|
+
"resolved": "https://registry.npmjs.org/tlc-context-engine/-/tlc-context-engine-0.1.0.tgz",
|
|
3737
|
+
"integrity": "sha512-OhLcPBmHuAYSv3XniJPnGcyDB2RaBi8wk/TsWQAaokkX7NkYhDFWWCrVsOqHTSKNMVf1M+xx+gvUFib5qaUCXA==",
|
|
3738
|
+
"license": "MIT",
|
|
3739
|
+
"peerDependencies": {
|
|
3740
|
+
"better-sqlite3": ">=11.0.0"
|
|
3741
|
+
}
|
|
3742
|
+
},
|
|
3717
3743
|
"node_modules/to-regex-range": {
|
|
3718
3744
|
"version": "5.0.1",
|
|
3719
3745
|
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|