teleton 0.8.5 → 0.8.6

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.
Files changed (80) hide show
  1. package/README.md +24 -5
  2. package/dist/{bootstrap-SPDT3XBQ.js → bootstrap-PFBH6ALD.js} +10 -7
  3. package/dist/bridge-guards-HZTNH7IB.js +9 -0
  4. package/dist/{chunk-FSL2MOYK.js → chunk-2UUGRY5B.js} +144 -163
  5. package/dist/{chunk-LM6AL6LN.js → chunk-4MFN75ZK.js} +4449 -2776
  6. package/dist/{chunk-GUX6ZFVF.js → chunk-4MG2AROG.js} +4 -6
  7. package/dist/{chunk-6U6VA2OT.js → chunk-6IFNQWIM.js} +7276 -7300
  8. package/dist/chunk-7KI25UJU.js +215 -0
  9. package/dist/chunk-AX5NBEHX.js +12 -0
  10. package/dist/{chunk-7ZXUUDQQ.js → chunk-BLUES3FJ.js} +79 -100
  11. package/dist/{chunk-KYSAHDYE.js → chunk-BT2I3ETV.js} +1 -1
  12. package/dist/chunk-CXTZPOTA.js +107 -0
  13. package/dist/{chunk-4KURCUWD.js → chunk-D3GT6YIY.js} +59 -7
  14. package/dist/chunk-EKCXKL5M.js +53 -0
  15. package/dist/{chunk-5K4YDCVU.js → chunk-F6S3L3OV.js} +3 -3
  16. package/dist/{chunk-L3LPVF4Z.js → chunk-J4WDJ7XS.js} +2 -2
  17. package/dist/{chunk-Z63KUQX4.js → chunk-JYF2MM5I.js} +120 -110
  18. package/dist/{chunk-NVKBBTI6.js → chunk-K3QSIIMZ.js} +9 -6
  19. package/dist/chunk-OMQIAWEU.js +273 -0
  20. package/dist/chunk-PCT7GYBP.js +274 -0
  21. package/dist/{chunk-35X3V6OW.js → chunk-QYZBWU2D.js} +5 -5
  22. package/dist/{chunk-WTDAICGT.js → chunk-R6W4DJRK.js} +7 -7
  23. package/dist/{chunk-5SEMA47R.js → chunk-RILOEIK6.js} +1 -1
  24. package/dist/{chunk-6OOHHJ4N.js → chunk-TFTNZZDH.js} +20 -20
  25. package/dist/chunk-TTOZCZWE.js +96 -0
  26. package/dist/chunk-UJ54YT2T.js +12 -0
  27. package/dist/{chunk-2MZP75SH.js → chunk-ULVL2W3D.js} +152 -256
  28. package/dist/{chunk-NQ6FZKCE.js → chunk-V3S3NXBQ.js} +3 -1
  29. package/dist/{chunk-H7MFXJZK.js → chunk-WSL4KIOI.js} +31 -26
  30. package/dist/{chunk-PK3TVFBT.js → chunk-Z5WY7BSB.js} +5 -5
  31. package/dist/{chunk-LD24DWWE.js → chunk-ZGKE3OTA.js} +110 -47
  32. package/dist/{chunk-M6M4DCDU.js → chunk-ZHRDETCX.js} +3 -3
  33. package/dist/cli/index.d.ts +2 -0
  34. package/dist/cli/index.js +263 -163
  35. package/dist/{client-G62EZT6U.js → client-S5UIK6OG.js} +9 -7
  36. package/dist/daily-logs-3WXGYAQF.js +25 -0
  37. package/dist/{get-my-gifts-Y7EN7RK4.js → get-my-gifts-3YSYM3LI.js} +3 -2
  38. package/dist/{harden-permissions-6BLHRCQJ.js → harden-permissions-PV5SGV5D.js} +1 -1
  39. package/dist/index.d.ts +923 -0
  40. package/dist/index.js +28 -20
  41. package/dist/knowledge-RRWUIO3G.js +19 -0
  42. package/dist/{local-HQ3UJ7KR.js → local-MSZAXWUL.js} +2 -2
  43. package/dist/mcp-loader-OELDFR63.js +15 -0
  44. package/dist/{memory-BJH724PQ.js → memory-6U6HGRK2.js} +22 -12
  45. package/dist/{memory-hook-LUAKTXU5.js → memory-hook-T7Y235KY.js} +7 -7
  46. package/dist/messages-KV5ADNJB.js +17 -0
  47. package/dist/{migrate-C4LBLOZH.js → migrate-AX3HOKOO.js} +9 -7
  48. package/dist/{server-4J56HS62.js → server-MFRYOGHR.js} +20 -16
  49. package/dist/{server-I6TYJ36S.js → server-SFLCAZFR.js} +220 -19
  50. package/dist/{setup-server-VJ3MGUSM.js → setup-server-YWAPKZVE.js} +14 -13
  51. package/dist/{store-2IGAMTES.js → store-PGHQASBC.js} +10 -8
  52. package/dist/{task-dependency-resolver-CQ432Z7J.js → task-dependency-resolver-YQKADDEU.js} +24 -10
  53. package/dist/{task-executor-JELRREUV.js → task-executor-LWAWD225.js} +4 -4
  54. package/dist/{tool-adapter-IVX2XQJE.js → tool-adapter-VKLUZSQS.js} +1 -1
  55. package/dist/{tool-index-XPCMWBYY.js → tool-index-YEWDF5CK.js} +4 -4
  56. package/dist/{transcript-OEO3HA4Z.js → transcript-4Y3Z2BJ3.js} +2 -2
  57. package/dist/web/assets/Config-MNxA69ib.js +1 -0
  58. package/dist/web/assets/Conversations-Dk958paA.js +1 -0
  59. package/dist/web/assets/Dashboard-dM18fGOm.js +1 -0
  60. package/dist/web/assets/Hooks-D2griQnI.js +1 -0
  61. package/dist/web/assets/Mcp-CtWNzwsz.js +1 -0
  62. package/dist/web/assets/Memory-CfLwH45G.js +1 -0
  63. package/dist/web/assets/Plugins-3hoJprFo.js +1 -0
  64. package/dist/web/assets/SearchInput-CpcETdpE.js +1 -0
  65. package/dist/web/assets/Soul-BSxE73aK.js +1 -0
  66. package/dist/web/assets/Tasks-DkCkfu3A.js +1 -0
  67. package/dist/web/assets/TelegramSettingsPanel-BRzc5G6e.js +1 -0
  68. package/dist/web/assets/Tools-Du8B8Mb4.js +1 -0
  69. package/dist/web/assets/Wallet-BLILP2Gn.js +1 -0
  70. package/dist/web/assets/Workspace-qklcXpXV.js +1 -0
  71. package/dist/web/assets/index-BwEPTTKp.js +90 -0
  72. package/dist/web/assets/index-noejUsK7.css +1 -0
  73. package/dist/web/assets/{index.es-eSR4Qv6s.js → index.es-DdpKlnGb.js} +1 -1
  74. package/dist/web/assets/useToolManager-tdxkKn3H.js +1 -0
  75. package/dist/web/assets/utils-CnsbSMo4.js +1 -0
  76. package/dist/web/index.html +2 -2
  77. package/package.json +7 -8
  78. package/dist/web/assets/index-DmlyQVhR.css +0 -1
  79. package/dist/web/assets/index-Dn5ZH1Y6.js +0 -80
  80. package/dist/{chunk-WFTC3JJW.js → chunk-3NO7QU7W.js} +1 -1
@@ -0,0 +1,273 @@
1
+ import {
2
+ hashText,
3
+ serializeEmbedding
4
+ } from "./chunk-Z5WY7BSB.js";
5
+ import {
6
+ KNOWLEDGE_CHUNK_SIZE
7
+ } from "./chunk-J4WDJ7XS.js";
8
+
9
+ // src/memory/agent/knowledge.ts
10
+ import { readFileSync, existsSync, readdirSync, statSync } from "fs";
11
+ import { join } from "path";
12
+ var _instance = null;
13
+ function setKnowledgeIndexer(indexer) {
14
+ _instance = indexer;
15
+ }
16
+ function getKnowledgeIndexer() {
17
+ return _instance;
18
+ }
19
+ var KnowledgeIndexer = class {
20
+ constructor(db, workspaceDir, embedder, vectorEnabled) {
21
+ this.db = db;
22
+ this.workspaceDir = workspaceDir;
23
+ this.embedder = embedder;
24
+ this.vectorEnabled = vectorEnabled;
25
+ }
26
+ getEmbedder() {
27
+ return this.embedder;
28
+ }
29
+ async indexAll(options) {
30
+ const files = this.listMemoryFiles();
31
+ let indexed = 0;
32
+ let skipped = 0;
33
+ for (const file of files) {
34
+ const wasIndexed = await this.indexFile(file, options?.force);
35
+ if (wasIndexed) {
36
+ indexed++;
37
+ } else {
38
+ skipped++;
39
+ }
40
+ }
41
+ return { indexed, skipped };
42
+ }
43
+ async indexFile(absPath, force) {
44
+ if (!existsSync(absPath) || !absPath.endsWith(".md")) {
45
+ return false;
46
+ }
47
+ const content = readFileSync(absPath, "utf-8");
48
+ const relPath = absPath.replace(this.workspaceDir + "/", "");
49
+ const fileHash = hashText(content);
50
+ if (!force) {
51
+ const existing = this.db.prepare(`SELECT hash FROM knowledge WHERE path = ? AND source = 'memory' LIMIT 1`).get(relPath);
52
+ if (existing?.hash === fileHash) {
53
+ return false;
54
+ }
55
+ }
56
+ const chunks = this.chunkMarkdown(content, relPath);
57
+ const texts = chunks.map((c) => c.text);
58
+ const embeddings = await this.embedder.embedBatch(texts);
59
+ const chunksToInsert = [];
60
+ const idsToSupersede = [];
61
+ if (this.vectorEnabled) {
62
+ const vecQuery = this.db.prepare(`
63
+ SELECT kv.id, kv.distance
64
+ FROM (
65
+ SELECT id, distance
66
+ FROM knowledge_vec
67
+ WHERE embedding MATCH ? AND k = 5
68
+ ) kv
69
+ JOIN knowledge k ON k.id = kv.id
70
+ WHERE k.path != ? AND (k.status = 'active' OR k.status IS NULL)
71
+ ORDER BY kv.distance
72
+ `);
73
+ for (let i = 0; i < chunks.length; i++) {
74
+ const chunk = chunks[i];
75
+ const embedding = embeddings[i] ?? [];
76
+ if (embedding.length === 0) {
77
+ chunksToInsert.push({ chunk, embedding });
78
+ continue;
79
+ }
80
+ let skip = false;
81
+ try {
82
+ const similar = vecQuery.all(serializeEmbedding(embedding), relPath);
83
+ const exactDup = similar.find((r) => r.distance < 0.1);
84
+ if (exactDup) {
85
+ skip = true;
86
+ } else {
87
+ const nearDup = similar.find((r) => r.distance < 0.15);
88
+ if (nearDup) {
89
+ idsToSupersede.push(nearDup.id);
90
+ }
91
+ }
92
+ } catch {
93
+ }
94
+ if (!skip) {
95
+ chunksToInsert.push({ chunk, embedding });
96
+ }
97
+ }
98
+ } else {
99
+ for (let i = 0; i < chunks.length; i++) {
100
+ chunksToInsert.push({ chunk: chunks[i], embedding: embeddings[i] ?? [] });
101
+ }
102
+ }
103
+ this.db.transaction(() => {
104
+ if (this.vectorEnabled) {
105
+ this.db.prepare(
106
+ `DELETE FROM knowledge_vec WHERE id IN (
107
+ SELECT id FROM knowledge WHERE path = ? AND source = 'memory'
108
+ )`
109
+ ).run(relPath);
110
+ }
111
+ this.db.prepare(`DELETE FROM knowledge WHERE path = ? AND source = 'memory'`).run(relPath);
112
+ if (idsToSupersede.length > 0) {
113
+ const placeholders = idsToSupersede.map(() => "?").join(", ");
114
+ this.db.prepare(
115
+ `UPDATE knowledge SET status = 'superseded', updated_at = unixepoch() WHERE id IN (${placeholders})`
116
+ ).run(...idsToSupersede);
117
+ }
118
+ const insert = this.db.prepare(`
119
+ INSERT INTO knowledge (id, source, path, text, embedding, start_line, end_line, hash, status, memory_type)
120
+ VALUES (?, 'memory', ?, ?, ?, ?, ?, ?, 'active', ?)
121
+ `);
122
+ const insertVec = this.vectorEnabled ? this.db.prepare(`INSERT INTO knowledge_vec (id, embedding) VALUES (?, ?)`) : null;
123
+ const memoryType = this.getMemoryType(relPath);
124
+ for (const { chunk, embedding } of chunksToInsert) {
125
+ insert.run(
126
+ chunk.id,
127
+ chunk.path,
128
+ chunk.text,
129
+ serializeEmbedding(embedding),
130
+ chunk.startLine,
131
+ chunk.endLine,
132
+ fileHash,
133
+ memoryType
134
+ );
135
+ if (insertVec && embedding.length > 0) {
136
+ insertVec.run(chunk.id, serializeEmbedding(embedding));
137
+ }
138
+ }
139
+ })();
140
+ return true;
141
+ }
142
+ async pruneOrphans() {
143
+ const paths = this.db.prepare(
144
+ `SELECT DISTINCT path FROM knowledge WHERE path IS NOT NULL AND source = 'memory'
145
+ AND (status = 'active' OR status IS NULL)`
146
+ ).all();
147
+ let markedInactive = 0;
148
+ const orphanedPaths = [];
149
+ for (const { path } of paths) {
150
+ const absPath = join(this.workspaceDir, path);
151
+ const archivedPath = join(
152
+ this.workspaceDir,
153
+ "memory",
154
+ "archived",
155
+ path.replace(/^memory\//, "")
156
+ );
157
+ if (!existsSync(absPath) && !existsSync(archivedPath)) {
158
+ orphanedPaths.push(path);
159
+ }
160
+ }
161
+ if (orphanedPaths.length > 0) {
162
+ const ph = orphanedPaths.map(() => "?").join(", ");
163
+ const result = this.db.prepare(
164
+ `UPDATE knowledge SET status = 'inactive', updated_at = unixepoch()
165
+ WHERE path IN (${ph}) AND source = 'memory'`
166
+ ).run(...orphanedPaths);
167
+ markedInactive = result.changes;
168
+ }
169
+ const staleIds = this.db.prepare(
170
+ `SELECT id FROM knowledge WHERE status = 'inactive' AND updated_at < unixepoch() - ?`
171
+ ).all(30 * 86400);
172
+ let deleted = 0;
173
+ if (staleIds.length > 0) {
174
+ const ids = staleIds.map((r) => r.id);
175
+ const placeholders = ids.map(() => "?").join(", ");
176
+ this.db.transaction(() => {
177
+ if (this.vectorEnabled) {
178
+ this.db.prepare(`DELETE FROM knowledge_vec WHERE id IN (${placeholders})`).run(...ids);
179
+ }
180
+ this.db.prepare(`DELETE FROM knowledge WHERE id IN (${placeholders})`).run(...ids);
181
+ })();
182
+ deleted = ids.length;
183
+ }
184
+ return { markedInactive, deleted };
185
+ }
186
+ listMemoryFiles() {
187
+ const files = [];
188
+ const memoryMd = join(this.workspaceDir, "MEMORY.md");
189
+ if (existsSync(memoryMd)) {
190
+ files.push(memoryMd);
191
+ }
192
+ const memoryDir = join(this.workspaceDir, "memory");
193
+ if (existsSync(memoryDir)) {
194
+ const entries = readdirSync(memoryDir);
195
+ for (const entry of entries) {
196
+ const absPath = join(memoryDir, entry);
197
+ if (statSync(absPath).isFile() && entry.endsWith(".md")) {
198
+ files.push(absPath);
199
+ }
200
+ }
201
+ }
202
+ return files;
203
+ }
204
+ getMemoryType(relPath) {
205
+ if (relPath === "MEMORY.md") return "procedural";
206
+ if (/^memory\/(\d{4}-\d{2}-\d{2}|consolidated-)/.test(relPath)) return "episodic";
207
+ return "semantic";
208
+ }
209
+ /**
210
+ * Chunk markdown content with structure awareness.
211
+ * Respects heading boundaries, code blocks, and list groups.
212
+ * Target: KNOWLEDGE_CHUNK_SIZE chars, hard max: 2x target.
213
+ */
214
+ chunkMarkdown(content, path) {
215
+ const lines = content.split("\n");
216
+ const chunks = [];
217
+ const targetSize = KNOWLEDGE_CHUNK_SIZE;
218
+ const hardMax = targetSize * 2;
219
+ let currentChunk = "";
220
+ let startLine = 1;
221
+ let currentLine = 1;
222
+ let inCodeBlock = false;
223
+ let overlapPrefix = "";
224
+ const flushChunk = () => {
225
+ const text = currentChunk.trim();
226
+ if (text.length > 0) {
227
+ chunks.push({
228
+ id: hashText(`${path}:${startLine}:${currentLine - 1}`),
229
+ source: "memory",
230
+ path,
231
+ text,
232
+ startLine,
233
+ endLine: currentLine - 1,
234
+ hash: hashText(text)
235
+ });
236
+ const nonEmpty = text.split("\n").filter((l) => l.trim());
237
+ overlapPrefix = nonEmpty.length > 0 ? nonEmpty.slice(-2).join("\n") + "\n" : "";
238
+ }
239
+ currentChunk = overlapPrefix;
240
+ startLine = currentLine;
241
+ };
242
+ for (const line of lines) {
243
+ if (line.trimStart().startsWith("```")) {
244
+ inCodeBlock = !inCodeBlock;
245
+ }
246
+ if (!inCodeBlock && currentChunk.length >= targetSize) {
247
+ const isHeading = /^#{1,6}\s/.test(line);
248
+ const isBlankLine = line.trim() === "";
249
+ const isHorizontalRule = /^(-{3,}|\*{3,}|_{3,})\s*$/.test(line.trim());
250
+ if (isHeading) {
251
+ flushChunk();
252
+ } else if ((isBlankLine || isHorizontalRule) && currentChunk.length >= targetSize) {
253
+ currentChunk += line + "\n";
254
+ currentLine++;
255
+ flushChunk();
256
+ continue;
257
+ } else if (currentChunk.length >= hardMax) {
258
+ flushChunk();
259
+ }
260
+ }
261
+ currentChunk += line + "\n";
262
+ currentLine++;
263
+ }
264
+ flushChunk();
265
+ return chunks;
266
+ }
267
+ };
268
+
269
+ export {
270
+ setKnowledgeIndexer,
271
+ getKnowledgeIndexer,
272
+ KnowledgeIndexer
273
+ };
@@ -0,0 +1,274 @@
1
+ import {
2
+ ALLOWED_EXTENSIONS,
3
+ WORKSPACE_PATHS,
4
+ WORKSPACE_ROOT
5
+ } from "./chunk-L653KKCR.js";
6
+ import {
7
+ createLogger
8
+ } from "./chunk-V3S3NXBQ.js";
9
+
10
+ // src/memory/daily-logs.ts
11
+ import { existsSync as existsSync2, mkdirSync, appendFileSync, readFileSync, readdirSync as readdirSync2, unlinkSync } from "fs";
12
+ import { join } from "path";
13
+
14
+ // src/workspace/validator.ts
15
+ import { existsSync, lstatSync, readdirSync } from "fs";
16
+ import { resolve, normalize, relative, extname, basename } from "path";
17
+ import { homedir } from "os";
18
+ var WorkspaceSecurityError = class extends Error {
19
+ constructor(message, attemptedPath) {
20
+ super(message);
21
+ this.attemptedPath = attemptedPath;
22
+ this.name = "WorkspaceSecurityError";
23
+ }
24
+ };
25
+ function decodeRecursive(str) {
26
+ let decoded = str;
27
+ let prev = "";
28
+ let iterations = 0;
29
+ const maxIterations = 10;
30
+ while (decoded !== prev && iterations < maxIterations) {
31
+ prev = decoded;
32
+ try {
33
+ decoded = decodeURIComponent(decoded);
34
+ } catch {
35
+ break;
36
+ }
37
+ iterations++;
38
+ }
39
+ return decoded;
40
+ }
41
+ function validatePath(inputPath, allowCreate = false) {
42
+ if (!inputPath || inputPath.trim() === "") {
43
+ throw new WorkspaceSecurityError("Path cannot be empty.", inputPath);
44
+ }
45
+ const trimmedPath = inputPath.trim().replace(/\\/g, "/");
46
+ const decodedPath = decodeRecursive(trimmedPath);
47
+ let absolutePath;
48
+ if (decodedPath.startsWith("/")) {
49
+ absolutePath = resolve(normalize(decodedPath));
50
+ } else if (decodedPath.startsWith("~/")) {
51
+ const expanded = decodedPath.replace(/^~(?=$|[\\/])/, homedir());
52
+ absolutePath = resolve(expanded);
53
+ } else {
54
+ absolutePath = resolve(WORKSPACE_ROOT, normalize(decodedPath));
55
+ }
56
+ const relativePath = relative(WORKSPACE_ROOT, absolutePath);
57
+ if (relativePath.startsWith("..") || relativePath.startsWith("/")) {
58
+ throw new WorkspaceSecurityError(
59
+ `Access denied: Path '${inputPath}' is outside the workspace. Only files in ~/.teleton/workspace/ are accessible.`,
60
+ inputPath
61
+ );
62
+ }
63
+ const exists = existsSync(absolutePath);
64
+ if (!exists && !allowCreate) {
65
+ throw new WorkspaceSecurityError(
66
+ `File not found: '${inputPath}' does not exist in workspace.`,
67
+ inputPath
68
+ );
69
+ }
70
+ if (exists) {
71
+ const stats = lstatSync(absolutePath);
72
+ if (stats.isSymbolicLink()) {
73
+ throw new WorkspaceSecurityError(
74
+ `Access denied: Symbolic links are not allowed for security reasons.`,
75
+ inputPath
76
+ );
77
+ }
78
+ }
79
+ return {
80
+ absolutePath,
81
+ relativePath,
82
+ exists,
83
+ isDirectory: exists ? lstatSync(absolutePath).isDirectory() : false,
84
+ extension: extname(absolutePath).toLowerCase(),
85
+ filename: basename(absolutePath)
86
+ };
87
+ }
88
+ function validateReadPath(inputPath) {
89
+ const validated = validatePath(inputPath, false);
90
+ if (validated.isDirectory) {
91
+ throw new WorkspaceSecurityError(`Cannot read directory as file: '${inputPath}'`, inputPath);
92
+ }
93
+ return validated;
94
+ }
95
+ var IMMUTABLE_FILES = ["SOUL.md", "STRATEGY.md", "SECURITY.md"];
96
+ function validateWritePath(inputPath, fileType) {
97
+ const validated = validatePath(inputPath, true);
98
+ if (IMMUTABLE_FILES.includes(validated.filename)) {
99
+ throw new WorkspaceSecurityError(
100
+ `Cannot write to ${validated.filename}. This file is configured by the owner. Use memory_write instead.`,
101
+ inputPath
102
+ );
103
+ }
104
+ if (fileType && ALLOWED_EXTENSIONS[fileType]) {
105
+ const allowedExts = ALLOWED_EXTENSIONS[fileType];
106
+ if (!allowedExts.includes(validated.extension)) {
107
+ throw new WorkspaceSecurityError(
108
+ `Invalid file type: '${validated.extension}' is not allowed for ${fileType}. Allowed: ${allowedExts.join(", ")}`,
109
+ inputPath
110
+ );
111
+ }
112
+ }
113
+ return validated;
114
+ }
115
+ function validateDirectory(inputPath) {
116
+ const validated = validatePath(inputPath, true);
117
+ if (validated.exists && !validated.isDirectory) {
118
+ throw new WorkspaceSecurityError(
119
+ `Path exists but is not a directory: '${inputPath}'`,
120
+ inputPath
121
+ );
122
+ }
123
+ return validated;
124
+ }
125
+
126
+ // src/memory/daily-logs.ts
127
+ var log = createLogger("Memory");
128
+ var MEMORY_DIR = WORKSPACE_PATHS.MEMORY_DIR;
129
+ function formatDate(date) {
130
+ const year = date.getFullYear();
131
+ const month = String(date.getMonth() + 1).padStart(2, "0");
132
+ const day = String(date.getDate()).padStart(2, "0");
133
+ return `${year}-${month}-${day}`;
134
+ }
135
+ function getDailyLogPath(date = /* @__PURE__ */ new Date()) {
136
+ return join(MEMORY_DIR, `${formatDate(date)}.md`);
137
+ }
138
+ function ensureMemoryDir() {
139
+ if (!existsSync2(MEMORY_DIR)) {
140
+ mkdirSync(MEMORY_DIR, { recursive: true });
141
+ }
142
+ }
143
+ function appendToDailyLog(content, date = /* @__PURE__ */ new Date()) {
144
+ try {
145
+ ensureMemoryDir();
146
+ const logPath = getDailyLogPath(date);
147
+ const timestamp = date.toLocaleTimeString("en-US", { hour12: false });
148
+ if (!existsSync2(logPath)) {
149
+ const header = `# Daily Log - ${formatDate(date)}
150
+
151
+ `;
152
+ appendFileSync(logPath, header, { encoding: "utf-8", mode: 384 });
153
+ }
154
+ const entry = `## ${timestamp}
155
+
156
+ ${content}
157
+
158
+ ---
159
+
160
+ `;
161
+ appendFileSync(logPath, entry, "utf-8");
162
+ log.info(`Daily log updated: ${logPath}`);
163
+ } catch (error) {
164
+ log.error({ err: error }, "Failed to write daily log");
165
+ }
166
+ }
167
+ function readDailyLog(date = /* @__PURE__ */ new Date()) {
168
+ try {
169
+ const logPath = getDailyLogPath(date);
170
+ if (!existsSync2(logPath)) return null;
171
+ return readFileSync(logPath, "utf-8");
172
+ } catch {
173
+ return null;
174
+ }
175
+ }
176
+ var DAILY_LOG_LINE_LIMIT = 100;
177
+ function truncateDailyLog(content) {
178
+ const lines = content.split("\n");
179
+ if (lines.length <= DAILY_LOG_LINE_LIMIT) return content;
180
+ const truncated = lines.slice(-DAILY_LOG_LINE_LIMIT).join("\n");
181
+ const dropped = lines.length - DAILY_LOG_LINE_LIMIT;
182
+ return `_[... ${dropped} earlier lines omitted]_
183
+
184
+ ${truncated}`;
185
+ }
186
+ function readRecentMemory() {
187
+ const today = /* @__PURE__ */ new Date();
188
+ const yesterday = new Date(today);
189
+ yesterday.setDate(yesterday.getDate() - 1);
190
+ const parts = [];
191
+ const yesterdayLog = readDailyLog(yesterday);
192
+ if (yesterdayLog) {
193
+ parts.push(`## Yesterday (${formatDate(yesterday)})
194
+
195
+ ${truncateDailyLog(yesterdayLog)}`);
196
+ }
197
+ const todayLog = readDailyLog(today);
198
+ if (todayLog) {
199
+ parts.push(`## Today (${formatDate(today)})
200
+
201
+ ${truncateDailyLog(todayLog)}`);
202
+ }
203
+ if (parts.length === 0) {
204
+ return null;
205
+ }
206
+ return `# Recent Memory
207
+
208
+ ${parts.join("\n\n---\n\n")}`;
209
+ }
210
+ function writeSessionEndSummary(summary, reason) {
211
+ const content = `### Session End (${reason})
212
+
213
+ ${summary}`;
214
+ appendToDailyLog(content);
215
+ }
216
+ function writeSummaryToDailyLog(summary) {
217
+ appendToDailyLog(`### Memory Flush (Pre-Compaction)
218
+
219
+ ${summary}`);
220
+ }
221
+ function cleanupOldDailyLogs(maxAgeDays = 60) {
222
+ if (!existsSync2(MEMORY_DIR)) return 0;
223
+ const cutoffMs = Date.now() - maxAgeDays * 864e5;
224
+ const datePattern = /^(\d{4}-\d{2}-\d{2})\.md$/;
225
+ let deleted = 0;
226
+ try {
227
+ const files = readdirSync2(MEMORY_DIR);
228
+ for (const file of files) {
229
+ const match = datePattern.exec(file);
230
+ if (!match) continue;
231
+ const fileDate = new Date(match[1]).getTime();
232
+ if (Number.isNaN(fileDate)) continue;
233
+ if (fileDate < cutoffMs) {
234
+ try {
235
+ unlinkSync(join(MEMORY_DIR, file));
236
+ deleted++;
237
+ } catch (innerError) {
238
+ log.warn({ err: innerError, file }, "Failed to delete old daily log");
239
+ }
240
+ }
241
+ }
242
+ } catch (error) {
243
+ log.error({ err: error }, "Failed to list memory directory for cleanup");
244
+ }
245
+ if (deleted > 0) {
246
+ log.info(`Cleaned up ${deleted} daily log file(s) older than ${maxAgeDays} days`);
247
+ }
248
+ return deleted;
249
+ }
250
+ function writeConversationMilestone(chatId, topic, details) {
251
+ const content = `### Conversation Milestone
252
+
253
+ **Chat**: ${chatId}
254
+ **Topic**: ${topic}
255
+
256
+ ${details}`;
257
+ appendToDailyLog(content);
258
+ }
259
+
260
+ export {
261
+ WorkspaceSecurityError,
262
+ validatePath,
263
+ validateReadPath,
264
+ validateWritePath,
265
+ validateDirectory,
266
+ getDailyLogPath,
267
+ appendToDailyLog,
268
+ readDailyLog,
269
+ readRecentMemory,
270
+ writeSessionEndSummary,
271
+ writeSummaryToDailyLog,
272
+ cleanupOldDailyLogs,
273
+ writeConversationMilestone
274
+ };
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-L653KKCR.js";
4
4
  import {
5
5
  createLogger
6
- } from "./chunk-NQ6FZKCE.js";
6
+ } from "./chunk-V3S3NXBQ.js";
7
7
 
8
8
  // src/utils/module-db.ts
9
9
  import Database from "better-sqlite3";
@@ -115,13 +115,13 @@ function migrateFromMainDb(moduleDb, tables) {
115
115
  );
116
116
  totalMigrated += src.c;
117
117
  log.info(`Migrated ${src.c} rows from memory.db \u2192 ${table}`);
118
- } catch (e) {
119
- log.warn({ err: e }, `Could not migrate table ${table}`);
118
+ } catch (innerError) {
119
+ log.warn({ err: innerError }, `Could not migrate table ${table}`);
120
120
  }
121
121
  }
122
122
  moduleDb.exec(`DETACH DATABASE main_db`);
123
- } catch (e) {
124
- log.warn({ err: e }, `Migration from memory.db failed`);
123
+ } catch (error) {
124
+ log.warn({ err: error }, `Migration from memory.db failed`);
125
125
  try {
126
126
  moduleDb.exec(`DETACH DATABASE main_db`);
127
127
  } catch {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createLogger
3
- } from "./chunk-NQ6FZKCE.js";
3
+ } from "./chunk-V3S3NXBQ.js";
4
4
 
5
5
  // src/providers/claude-code-credentials.ts
6
6
  import { readFileSync, writeFileSync, existsSync } from "fs";
@@ -26,8 +26,8 @@ function readCredentialsFile() {
26
26
  try {
27
27
  const raw = readFileSync(filePath, "utf-8");
28
28
  return JSON.parse(raw);
29
- } catch (e) {
30
- log.warn({ err: e, path: filePath }, "Failed to parse Claude Code credentials file");
29
+ } catch (error) {
30
+ log.warn({ err: error, path: filePath }, "Failed to parse Claude Code credentials file");
31
31
  return null;
32
32
  }
33
33
  }
@@ -122,16 +122,16 @@ async function performOAuthRefresh(refreshToken) {
122
122
  }
123
123
  };
124
124
  writeFileSync(filePath, JSON.stringify(updated, null, 2), { mode: 384 });
125
- } catch (e) {
126
- log.warn({ err: e }, "Failed to persist refreshed OAuth credentials to disk");
125
+ } catch (innerError) {
126
+ log.warn({ err: innerError }, "Failed to persist refreshed OAuth credentials to disk");
127
127
  }
128
128
  cachedToken = data.access_token;
129
129
  cachedExpiresAt = newExpiresAt;
130
130
  cachedRefreshToken = newRefreshToken;
131
131
  log.info("Claude Code OAuth token refreshed successfully");
132
132
  return cachedToken;
133
- } catch (e) {
134
- log.warn({ err: e }, "OAuth token refresh request failed");
133
+ } catch (error) {
134
+ log.warn({ err: error }, "OAuth token refresh request failed");
135
135
  return null;
136
136
  }
137
137
  }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createLogger
3
- } from "./chunk-NQ6FZKCE.js";
3
+ } from "./chunk-V3S3NXBQ.js";
4
4
 
5
5
  // src/api/tls.ts
6
6
  import { existsSync, readFileSync, writeFileSync } from "fs";
@@ -1,23 +1,35 @@
1
1
  // src/config/providers.ts
2
2
  var PROVIDER_REGISTRY = {
3
- anthropic: {
4
- id: "anthropic",
5
- displayName: "Anthropic (Claude)",
3
+ "claude-code": {
4
+ id: "claude-code",
5
+ displayName: "Claude Code (Auto)",
6
6
  envVar: "ANTHROPIC_API_KEY",
7
7
  keyPrefix: "sk-ant-",
8
- keyHint: "sk-ant-api03-...",
8
+ keyHint: "Auto-detected from Claude Code",
9
9
  consoleUrl: "https://console.anthropic.com/",
10
10
  defaultModel: "claude-opus-4-6",
11
11
  utilityModel: "claude-haiku-4-5-20251001",
12
12
  toolLimit: null,
13
13
  piAiProvider: "anthropic"
14
14
  },
15
- "claude-code": {
16
- id: "claude-code",
17
- displayName: "Claude Code (Auto)",
15
+ zai: {
16
+ id: "zai",
17
+ displayName: "ZAI (Zhipu)",
18
+ envVar: "ZAI_API_KEY",
19
+ keyPrefix: null,
20
+ keyHint: "...",
21
+ consoleUrl: "https://z.ai/manage-apikey/apikey-list",
22
+ defaultModel: "glm-4.7-flash",
23
+ utilityModel: "glm-4.5-flash",
24
+ toolLimit: 128,
25
+ piAiProvider: "zai"
26
+ },
27
+ anthropic: {
28
+ id: "anthropic",
29
+ displayName: "Anthropic (Claude)",
18
30
  envVar: "ANTHROPIC_API_KEY",
19
31
  keyPrefix: "sk-ant-",
20
- keyHint: "Auto-detected from Claude Code",
32
+ keyHint: "sk-ant-api03-...",
21
33
  consoleUrl: "https://console.anthropic.com/",
22
34
  defaultModel: "claude-opus-4-6",
23
35
  utilityModel: "claude-haiku-4-5-20251001",
@@ -120,18 +132,6 @@ var PROVIDER_REGISTRY = {
120
132
  toolLimit: 128,
121
133
  piAiProvider: "cerebras"
122
134
  },
123
- zai: {
124
- id: "zai",
125
- displayName: "ZAI (Zhipu)",
126
- envVar: "ZAI_API_KEY",
127
- keyPrefix: null,
128
- keyHint: "...",
129
- consoleUrl: "https://z.ai/manage-apikey/apikey-list",
130
- defaultModel: "glm-4.7",
131
- utilityModel: "glm-4.7-flash",
132
- toolLimit: 128,
133
- piAiProvider: "zai"
134
- },
135
135
  minimax: {
136
136
  id: "minimax",
137
137
  displayName: "MiniMax",