titan-agent 2026.4.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.
Files changed (43) hide show
  1. package/.env.example +21 -0
  2. package/LICENSE +29 -0
  3. package/README.md +305 -0
  4. package/assets/titan-logo.png +0 -0
  5. package/dist/agent/agent.js +1458 -0
  6. package/dist/agent/agent.js.map +1 -0
  7. package/dist/agent/generator.js +1078 -0
  8. package/dist/agent/generator.js.map +1 -0
  9. package/dist/cli/index.js +5064 -0
  10. package/dist/cli/index.js.map +1 -0
  11. package/dist/gateway/server.js +4462 -0
  12. package/dist/gateway/server.js.map +1 -0
  13. package/dist/skills/builtin/apply_patch.js +368 -0
  14. package/dist/skills/builtin/apply_patch.js.map +1 -0
  15. package/dist/skills/builtin/auto_generate.js +1129 -0
  16. package/dist/skills/builtin/auto_generate.js.map +1 -0
  17. package/dist/skills/builtin/browser.js +357 -0
  18. package/dist/skills/builtin/browser.js.map +1 -0
  19. package/dist/skills/builtin/cron.js +410 -0
  20. package/dist/skills/builtin/cron.js.map +1 -0
  21. package/dist/skills/builtin/filesystem.js +386 -0
  22. package/dist/skills/builtin/filesystem.js.map +1 -0
  23. package/dist/skills/builtin/memory_skill.js +430 -0
  24. package/dist/skills/builtin/memory_skill.js.map +1 -0
  25. package/dist/skills/builtin/process.js +421 -0
  26. package/dist/skills/builtin/process.js.map +1 -0
  27. package/dist/skills/builtin/sessions.js +1729 -0
  28. package/dist/skills/builtin/sessions.js.map +1 -0
  29. package/dist/skills/builtin/shell.js +327 -0
  30. package/dist/skills/builtin/shell.js.map +1 -0
  31. package/dist/skills/builtin/vision.js +491 -0
  32. package/dist/skills/builtin/vision.js.map +1 -0
  33. package/dist/skills/builtin/voice.js +468 -0
  34. package/dist/skills/builtin/voice.js.map +1 -0
  35. package/dist/skills/builtin/web_fetch.js +331 -0
  36. package/dist/skills/builtin/web_fetch.js.map +1 -0
  37. package/dist/skills/builtin/web_search.js +317 -0
  38. package/dist/skills/builtin/web_search.js.map +1 -0
  39. package/dist/skills/builtin/webhook.js +323 -0
  40. package/dist/skills/builtin/webhook.js.map +1 -0
  41. package/dist/skills/registry.js +3369 -0
  42. package/dist/skills/registry.js.map +1 -0
  43. package/package.json +118 -0
@@ -0,0 +1,430 @@
1
+ #!/usr/bin/env node
2
+ var __getOwnPropNames = Object.getOwnPropertyNames;
3
+ var __esm = (fn, res) => function __init() {
4
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
5
+ };
6
+
7
+ // src/utils/constants.ts
8
+ import { homedir } from "os";
9
+ import { join } from "path";
10
+ var TITAN_VERSION, TITAN_ASCII_LOGO, TITAN_HOME, TITAN_CONFIG_PATH, TITAN_DB_PATH, TITAN_WORKSPACE, TITAN_SKILLS_DIR, TITAN_LOGS_DIR, TITAN_MEMORY_DIR, AGENTS_MD, SOUL_MD, TOOLS_MD, DEFAULT_GATEWAY_HOST, DEFAULT_GATEWAY_PORT, DEFAULT_WEB_PORT, DEFAULT_MODEL, DEFAULT_MAX_TOKENS, DEFAULT_TEMPERATURE, SESSION_TIMEOUT_MS, DEFAULT_SANDBOX_MODE, ALLOWED_TOOLS_DEFAULT;
11
+ var init_constants = __esm({
12
+ "src/utils/constants.ts"() {
13
+ "use strict";
14
+ TITAN_VERSION = "2026.4.0";
15
+ TITAN_ASCII_LOGO = `
16
+ \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
17
+ \u2551 \u2551
18
+ \u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2551
19
+ \u2551 \u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u2588\u2588\u2551\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2551
20
+ \u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2554\u2588\u2588\u2557 \u2588\u2588\u2551 \u2551
21
+ \u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2557\u2588\u2588\u2551 \u2551
22
+ \u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2551 \u2551
23
+ \u2551 \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D \u2551
24
+ \u2551 \u2551
25
+ \u2551 The Intelligent Task Automation Network \u2551
26
+ \u2551 v${TITAN_VERSION} \u2551
27
+ \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D`;
28
+ TITAN_HOME = join(homedir(), ".titan");
29
+ TITAN_CONFIG_PATH = join(TITAN_HOME, "titan.json");
30
+ TITAN_DB_PATH = join(TITAN_HOME, "titan.db");
31
+ TITAN_WORKSPACE = join(TITAN_HOME, "workspace");
32
+ TITAN_SKILLS_DIR = join(TITAN_WORKSPACE, "skills");
33
+ TITAN_LOGS_DIR = join(TITAN_HOME, "logs");
34
+ TITAN_MEMORY_DIR = join(TITAN_HOME, "memory");
35
+ AGENTS_MD = join(TITAN_WORKSPACE, "AGENTS.md");
36
+ SOUL_MD = join(TITAN_WORKSPACE, "SOUL.md");
37
+ TOOLS_MD = join(TITAN_WORKSPACE, "TOOLS.md");
38
+ DEFAULT_GATEWAY_HOST = "127.0.0.1";
39
+ DEFAULT_GATEWAY_PORT = 18789;
40
+ DEFAULT_WEB_PORT = 18790;
41
+ DEFAULT_MODEL = "anthropic/claude-sonnet-4-20250514";
42
+ DEFAULT_MAX_TOKENS = 8192;
43
+ DEFAULT_TEMPERATURE = 0.7;
44
+ SESSION_TIMEOUT_MS = 30 * 60 * 1e3;
45
+ DEFAULT_SANDBOX_MODE = "host";
46
+ ALLOWED_TOOLS_DEFAULT = [
47
+ "shell",
48
+ "read_file",
49
+ "write_file",
50
+ "edit_file",
51
+ "list_dir",
52
+ "web_search",
53
+ "browser",
54
+ "cron",
55
+ "webhook",
56
+ "email",
57
+ "memory"
58
+ ];
59
+ }
60
+ });
61
+
62
+ // src/utils/logger.ts
63
+ import chalk from "chalk";
64
+ function formatTimestamp() {
65
+ return chalk.gray((/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19));
66
+ }
67
+ function log(level, component, message, ...args) {
68
+ if (level < currentLevel) return;
69
+ const prefix = `${formatTimestamp()} ${LEVEL_LABELS[level]} ${chalk.blue(`[${component}]`)}`;
70
+ console.log(`${prefix} ${message}`, ...args);
71
+ }
72
+ var LEVEL_LABELS, currentLevel, logger, logger_default;
73
+ var init_logger = __esm({
74
+ "src/utils/logger.ts"() {
75
+ "use strict";
76
+ LEVEL_LABELS = {
77
+ [0 /* DEBUG */]: chalk.gray("DEBUG"),
78
+ [1 /* INFO */]: chalk.cyan("INFO "),
79
+ [2 /* WARN */]: chalk.yellow("WARN "),
80
+ [3 /* ERROR */]: chalk.red("ERROR"),
81
+ [4 /* SILENT */]: ""
82
+ };
83
+ currentLevel = 1 /* INFO */;
84
+ logger = {
85
+ debug: (component, msg, ...args) => log(0 /* DEBUG */, component, msg, ...args),
86
+ info: (component, msg, ...args) => log(1 /* INFO */, component, msg, ...args),
87
+ warn: (component, msg, ...args) => log(2 /* WARN */, component, msg, ...args),
88
+ error: (component, msg, ...args) => log(3 /* ERROR */, component, msg, ...args)
89
+ };
90
+ logger_default = logger;
91
+ }
92
+ });
93
+
94
+ // src/utils/helpers.ts
95
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
96
+ function ensureDir(dirPath) {
97
+ if (!existsSync(dirPath)) {
98
+ mkdirSync(dirPath, { recursive: true });
99
+ }
100
+ }
101
+ var init_helpers = __esm({
102
+ "src/utils/helpers.ts"() {
103
+ "use strict";
104
+ }
105
+ });
106
+
107
+ // src/config/schema.ts
108
+ import { z } from "zod";
109
+ var ProviderConfigSchema, ChannelConfigSchema, SecurityConfigSchema, GatewayConfigSchema, AgentConfigSchema, TitanConfigSchema;
110
+ var init_schema = __esm({
111
+ "src/config/schema.ts"() {
112
+ "use strict";
113
+ init_constants();
114
+ ProviderConfigSchema = z.object({
115
+ apiKey: z.string().optional(),
116
+ baseUrl: z.string().optional(),
117
+ model: z.string().optional(),
118
+ maxTokens: z.number().optional(),
119
+ temperature: z.number().min(0).max(2).optional()
120
+ });
121
+ ChannelConfigSchema = z.object({
122
+ enabled: z.boolean().default(false),
123
+ token: z.string().optional(),
124
+ apiKey: z.string().optional(),
125
+ allowFrom: z.array(z.string()).default([]),
126
+ dmPolicy: z.enum(["pairing", "open", "closed"]).default("pairing")
127
+ });
128
+ SecurityConfigSchema = z.object({
129
+ sandboxMode: z.enum(["host", "docker", "none"]).default(DEFAULT_SANDBOX_MODE),
130
+ allowedTools: z.array(z.string()).default(ALLOWED_TOOLS_DEFAULT),
131
+ deniedTools: z.array(z.string()).default([]),
132
+ maxConcurrentTasks: z.number().default(5),
133
+ commandTimeout: z.number().default(3e4),
134
+ fileSystemAllowlist: z.array(z.string()).default([]),
135
+ networkAllowlist: z.array(z.string()).default(["*"]),
136
+ shield: z.object({
137
+ enabled: z.boolean().default(true),
138
+ mode: z.enum(["standard", "strict"]).default("strict")
139
+ }).default({})
140
+ });
141
+ GatewayConfigSchema = z.object({
142
+ host: z.string().default(DEFAULT_GATEWAY_HOST),
143
+ port: z.number().default(DEFAULT_GATEWAY_PORT),
144
+ webPort: z.number().default(DEFAULT_WEB_PORT),
145
+ auth: z.object({
146
+ mode: z.enum(["none", "token", "password"]).default("token"),
147
+ token: z.string().optional(),
148
+ password: z.string().optional()
149
+ }).default({})
150
+ });
151
+ AgentConfigSchema = z.object({
152
+ model: z.string().default(DEFAULT_MODEL),
153
+ maxTokens: z.number().default(DEFAULT_MAX_TOKENS),
154
+ temperature: z.number().default(DEFAULT_TEMPERATURE),
155
+ systemPrompt: z.string().optional(),
156
+ workspace: z.string().optional(),
157
+ thinkingMode: z.enum(["off", "low", "medium", "high"]).default("medium")
158
+ });
159
+ TitanConfigSchema = z.object({
160
+ agent: AgentConfigSchema.default({}),
161
+ providers: z.object({
162
+ anthropic: ProviderConfigSchema.default({}),
163
+ openai: ProviderConfigSchema.default({}),
164
+ google: ProviderConfigSchema.default({}),
165
+ ollama: ProviderConfigSchema.default({})
166
+ }).default({}),
167
+ channels: z.object({
168
+ discord: ChannelConfigSchema.default({}),
169
+ telegram: ChannelConfigSchema.default({}),
170
+ slack: ChannelConfigSchema.default({}),
171
+ whatsapp: ChannelConfigSchema.default({}),
172
+ webchat: ChannelConfigSchema.default({}),
173
+ googlechat: ChannelConfigSchema.default({}),
174
+ matrix: ChannelConfigSchema.default({}),
175
+ signal: ChannelConfigSchema.default({}),
176
+ msteams: ChannelConfigSchema.default({}),
177
+ bluebubbles: ChannelConfigSchema.default({})
178
+ }).default({}),
179
+ gateway: GatewayConfigSchema.default({}),
180
+ security: SecurityConfigSchema.default({}),
181
+ memory: z.object({
182
+ enabled: z.boolean().default(true),
183
+ maxHistoryMessages: z.number().default(50),
184
+ vectorSearchEnabled: z.boolean().default(false)
185
+ }).default({}),
186
+ skills: z.object({
187
+ enabled: z.boolean().default(true),
188
+ autoDiscover: z.boolean().default(true),
189
+ marketplace: z.boolean().default(false)
190
+ }).default({}),
191
+ logging: z.object({
192
+ level: z.enum(["debug", "info", "warn", "error", "silent"]).default("info"),
193
+ file: z.boolean().default(true)
194
+ }).default({}),
195
+ autonomy: z.object({
196
+ /** autonomous = full auto, supervised = asks for dangerous ops, locked = asks for everything */
197
+ mode: z.enum(["autonomous", "supervised", "locked"]).default("supervised"),
198
+ /** Auto-approve moderate-risk tools in main session (cli/webchat) */
199
+ autoApproveMainSession: z.boolean().default(true),
200
+ /** Timeout for HITL approval requests (ms). Auto-deny after timeout. */
201
+ approvalTimeoutMs: z.number().default(6e4),
202
+ /** Notify user of auto-approved actions */
203
+ notifyOnAutoApprove: z.boolean().default(true)
204
+ }).default({})
205
+ });
206
+ }
207
+ });
208
+
209
+ // src/config/config.ts
210
+ var init_config = __esm({
211
+ "src/config/config.ts"() {
212
+ "use strict";
213
+ init_constants();
214
+ init_helpers();
215
+ init_schema();
216
+ init_logger();
217
+ }
218
+ });
219
+
220
+ // src/agent/toolRunner.ts
221
+ function registerTool(handler) {
222
+ toolRegistry.set(handler.name, handler);
223
+ logger_default.debug(COMPONENT, `Registered tool: ${handler.name}`);
224
+ }
225
+ var COMPONENT, toolRegistry;
226
+ var init_toolRunner = __esm({
227
+ "src/agent/toolRunner.ts"() {
228
+ "use strict";
229
+ init_logger();
230
+ init_config();
231
+ COMPONENT = "ToolRunner";
232
+ toolRegistry = /* @__PURE__ */ new Map();
233
+ }
234
+ });
235
+
236
+ // src/skills/registry.ts
237
+ function registerSkill(meta, handler) {
238
+ registeredSkills.set(meta.name, meta);
239
+ registerTool(handler);
240
+ logger_default.debug(COMPONENT2, `Registered skill: ${meta.name} (${meta.source})`);
241
+ }
242
+ var COMPONENT2, registeredSkills;
243
+ var init_registry = __esm({
244
+ "src/skills/registry.ts"() {
245
+ "use strict";
246
+ init_constants();
247
+ init_toolRunner();
248
+ init_helpers();
249
+ init_logger();
250
+ COMPONENT2 = "Skills";
251
+ registeredSkills = /* @__PURE__ */ new Map();
252
+ }
253
+ });
254
+
255
+ // src/security/encryption.ts
256
+ var init_encryption = __esm({
257
+ "src/security/encryption.ts"() {
258
+ "use strict";
259
+ init_logger();
260
+ }
261
+ });
262
+
263
+ // src/memory/memory.ts
264
+ import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
265
+ import { join as join2 } from "path";
266
+ function getDefaultStore() {
267
+ return {
268
+ conversations: [],
269
+ memories: [],
270
+ sessions: [],
271
+ usageStats: [],
272
+ cronJobs: [],
273
+ skillsInstalled: []
274
+ };
275
+ }
276
+ function loadStore() {
277
+ if (store) return store;
278
+ ensureDir(TITAN_HOME);
279
+ if (existsSync2(DB_FILE)) {
280
+ try {
281
+ const raw = readFileSync2(DB_FILE, "utf-8");
282
+ store = JSON.parse(raw);
283
+ store.conversations = store.conversations || [];
284
+ store.memories = store.memories || [];
285
+ store.sessions = store.sessions || [];
286
+ store.usageStats = store.usageStats || [];
287
+ store.cronJobs = store.cronJobs || [];
288
+ store.skillsInstalled = store.skillsInstalled || [];
289
+ } catch {
290
+ logger_default.warn(COMPONENT3, "Could not load data store, creating fresh one");
291
+ store = getDefaultStore();
292
+ }
293
+ } else {
294
+ store = getDefaultStore();
295
+ }
296
+ return store;
297
+ }
298
+ function saveStore() {
299
+ if (!store) return;
300
+ ensureDir(TITAN_HOME);
301
+ try {
302
+ writeFileSync2(DB_FILE, JSON.stringify(store, null, 2), "utf-8");
303
+ } catch (e) {
304
+ logger_default.error(COMPONENT3, `Failed to save data: ${e.message}`);
305
+ }
306
+ }
307
+ function debouncedSave() {
308
+ if (saveTimeout) clearTimeout(saveTimeout);
309
+ saveTimeout = setTimeout(saveStore, 1e3);
310
+ }
311
+ function rememberFact(category, key, value, metadata) {
312
+ const s = loadStore();
313
+ const id = `${category}:${key}`;
314
+ const existingIdx = s.memories.findIndex((m) => m.id === id);
315
+ const now = (/* @__PURE__ */ new Date()).toISOString();
316
+ if (existingIdx >= 0) {
317
+ s.memories[existingIdx].value = value;
318
+ s.memories[existingIdx].metadata = metadata ? JSON.stringify(metadata) : void 0;
319
+ s.memories[existingIdx].updatedAt = now;
320
+ } else {
321
+ s.memories.push({
322
+ id,
323
+ category,
324
+ key,
325
+ value,
326
+ metadata: metadata ? JSON.stringify(metadata) : void 0,
327
+ createdAt: now,
328
+ updatedAt: now
329
+ });
330
+ }
331
+ debouncedSave();
332
+ }
333
+ function recallFact(category, key) {
334
+ const s = loadStore();
335
+ const entry = s.memories.find((m) => m.category === category && m.key === key);
336
+ return entry?.value || null;
337
+ }
338
+ function searchMemories(category, query) {
339
+ const s = loadStore();
340
+ let results = s.memories;
341
+ if (category) {
342
+ results = results.filter((m) => m.category === category);
343
+ }
344
+ if (query) {
345
+ const q = query.toLowerCase();
346
+ results = results.filter(
347
+ (m) => m.key.toLowerCase().includes(q) || m.value.toLowerCase().includes(q)
348
+ );
349
+ }
350
+ return results.slice(-50).map((m) => ({ key: m.key, value: m.value, category: m.category }));
351
+ }
352
+ var COMPONENT3, DB_FILE, store, saveTimeout;
353
+ var init_memory = __esm({
354
+ "src/memory/memory.ts"() {
355
+ "use strict";
356
+ init_constants();
357
+ init_helpers();
358
+ init_logger();
359
+ init_encryption();
360
+ COMPONENT3 = "Memory";
361
+ DB_FILE = join2(TITAN_HOME, "titan-data.json");
362
+ store = null;
363
+ saveTimeout = null;
364
+ }
365
+ });
366
+
367
+ // src/skills/builtin/memory_skill.ts
368
+ function registerMemorySkill() {
369
+ registerSkill(
370
+ { name: "memory", description: "Persistent memory management", version: "1.0.0", source: "bundled", enabled: true },
371
+ {
372
+ name: "memory",
373
+ description: "Store and recall persistent memories. Use this to remember user preferences, important facts, project details, and anything that should persist across conversations.",
374
+ parameters: {
375
+ type: "object",
376
+ properties: {
377
+ action: { type: "string", enum: ["remember", "recall", "search", "list"], description: "Action" },
378
+ category: { type: "string", description: 'Memory category (e.g., "preference", "fact", "project")' },
379
+ key: { type: "string", description: "Memory key/name" },
380
+ value: { type: "string", description: "Value to remember" },
381
+ query: { type: "string", description: "Search query (for search action)" }
382
+ },
383
+ required: ["action"]
384
+ },
385
+ execute: async (args) => {
386
+ const action = args.action;
387
+ const category = args.category || "general";
388
+ switch (action) {
389
+ case "remember": {
390
+ const key = args.key;
391
+ const value = args.value;
392
+ if (!key || !value) return "Error: key and value are required";
393
+ rememberFact(category, key, value);
394
+ return `Remembered: [${category}] ${key} = ${value}`;
395
+ }
396
+ case "recall": {
397
+ const rKey = args.key;
398
+ if (!rKey) return "Error: key is required";
399
+ const value = recallFact(category, rKey);
400
+ return value ? `[${category}] ${rKey} = ${value}` : `No memory found for [${category}] ${rKey}`;
401
+ }
402
+ case "search": {
403
+ const query = args.query;
404
+ const results = searchMemories(category !== "general" ? category : void 0, query);
405
+ if (results.length === 0) return "No matching memories found.";
406
+ return results.map((m) => `\u2022 [${m.category}] ${m.key}: ${m.value}`).join("\n");
407
+ }
408
+ case "list": {
409
+ const all = searchMemories(category !== "general" ? category : void 0);
410
+ if (all.length === 0) return "No memories stored yet.";
411
+ return all.map((m) => `\u2022 [${m.category}] ${m.key}: ${m.value}`).join("\n");
412
+ }
413
+ default:
414
+ return `Unknown action: ${action}`;
415
+ }
416
+ }
417
+ }
418
+ );
419
+ }
420
+ var init_memory_skill = __esm({
421
+ "src/skills/builtin/memory_skill.ts"() {
422
+ init_registry();
423
+ init_memory();
424
+ }
425
+ });
426
+ init_memory_skill();
427
+ export {
428
+ registerMemorySkill
429
+ };
430
+ //# sourceMappingURL=memory_skill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/utils/constants.ts","../../../src/utils/logger.ts","../../../src/utils/helpers.ts","../../../src/config/schema.ts","../../../src/config/config.ts","../../../src/agent/toolRunner.ts","../../../src/skills/registry.ts","../../../src/security/encryption.ts","../../../src/memory/memory.ts","../../../src/skills/builtin/memory_skill.ts"],"sourcesContent":["/**\n * TITAN Constants\n */\nimport { homedir } from 'os';\nimport { join } from 'path';\n\nexport const TITAN_VERSION = '2026.4.0';\nexport const TITAN_NAME = 'TITAN';\nexport const TITAN_FULL_NAME = 'The Intelligent Task Automation Network';\nexport const TITAN_ASCII_LOGO = `\n╔════════════════════════════════════════════════════╗\n║ ║\n║ ████████╗██╗████████╗ █████╗ ███╗ ██╗ ║\n║ ╚══██╔══╝██║╚══██╔══╝██╔══██╗████╗ ██║ ║\n║ ██║ ██║ ██║ ███████║██╔██╗ ██║ ║\n║ ██║ ██║ ██║ ██╔══██║██║╚██╗██║ ║\n║ ██║ ██║ ██║ ██║ ██║██║ ╚████║ ║\n║ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝ ║\n║ ║\n║ The Intelligent Task Automation Network ║\n║ v${TITAN_VERSION} ║\n╚════════════════════════════════════════════════════╝`;\n\n// Paths\nexport const TITAN_HOME = join(homedir(), '.titan');\nexport const TITAN_CONFIG_PATH = join(TITAN_HOME, 'titan.json');\nexport const TITAN_DB_PATH = join(TITAN_HOME, 'titan.db');\nexport const TITAN_WORKSPACE = join(TITAN_HOME, 'workspace');\nexport const TITAN_SKILLS_DIR = join(TITAN_WORKSPACE, 'skills');\nexport const TITAN_LOGS_DIR = join(TITAN_HOME, 'logs');\nexport const TITAN_MEMORY_DIR = join(TITAN_HOME, 'memory');\n\n// Workspace prompt files (injected into agent context)\nexport const AGENTS_MD = join(TITAN_WORKSPACE, 'AGENTS.md');\nexport const SOUL_MD = join(TITAN_WORKSPACE, 'SOUL.md');\nexport const TOOLS_MD = join(TITAN_WORKSPACE, 'TOOLS.md');\n\n// Gateway defaults\nexport const DEFAULT_GATEWAY_HOST = '127.0.0.1';\nexport const DEFAULT_GATEWAY_PORT = 18789;\nexport const DEFAULT_WEB_PORT = 18790;\n\n// Agent defaults\nexport const DEFAULT_MODEL = 'anthropic/claude-sonnet-4-20250514';\nexport const DEFAULT_MAX_TOKENS = 8192;\nexport const DEFAULT_TEMPERATURE = 0.7;\nexport const MAX_CONTEXT_MESSAGES = 50;\nexport const SESSION_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes\n\n// Security\nexport const DEFAULT_SANDBOX_MODE = 'host';\nexport const ALLOWED_TOOLS_DEFAULT = [\n 'shell', 'read_file', 'write_file', 'edit_file', 'list_dir',\n 'web_search', 'browser', 'cron', 'webhook', 'email', 'memory',\n];\nexport const DENIED_TOOLS_DEFAULT: string[] = [];\n","/**\n * TITAN Logger — Structured logging with levels and colors\n */\nimport chalk from 'chalk';\n\nexport enum LogLevel {\n DEBUG = 0,\n INFO = 1,\n WARN = 2,\n ERROR = 3,\n SILENT = 4,\n}\n\nconst LEVEL_LABELS: Record<LogLevel, string> = {\n [LogLevel.DEBUG]: chalk.gray('DEBUG'),\n [LogLevel.INFO]: chalk.cyan('INFO '),\n [LogLevel.WARN]: chalk.yellow('WARN '),\n [LogLevel.ERROR]: chalk.red('ERROR'),\n [LogLevel.SILENT]: '',\n};\n\nlet currentLevel: LogLevel = LogLevel.INFO;\n\nexport function setLogLevel(level: LogLevel): void {\n currentLevel = level;\n}\n\nexport function getLogLevel(): LogLevel {\n return currentLevel;\n}\n\nfunction formatTimestamp(): string {\n return chalk.gray(new Date().toISOString().replace('T', ' ').slice(0, 19));\n}\n\nfunction log(level: LogLevel, component: string, message: string, ...args: unknown[]): void {\n if (level < currentLevel) return;\n const prefix = `${formatTimestamp()} ${LEVEL_LABELS[level]} ${chalk.blue(`[${component}]`)}`;\n console.log(`${prefix} ${message}`, ...args);\n}\n\nexport const logger = {\n debug: (component: string, msg: string, ...args: unknown[]) => log(LogLevel.DEBUG, component, msg, ...args),\n info: (component: string, msg: string, ...args: unknown[]) => log(LogLevel.INFO, component, msg, ...args),\n warn: (component: string, msg: string, ...args: unknown[]) => log(LogLevel.WARN, component, msg, ...args),\n error: (component: string, msg: string, ...args: unknown[]) => log(LogLevel.ERROR, component, msg, ...args),\n};\n\nexport default logger;\n","/**\n * TITAN Helper Utilities\n */\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\nimport { dirname } from 'path';\n\n/** Ensure a directory exists, creating it recursively if needed */\nexport function ensureDir(dirPath: string): void {\n if (!existsSync(dirPath)) {\n mkdirSync(dirPath, { recursive: true });\n }\n}\n\n/** Safely read a JSON file, returning null on failure */\nexport function readJsonFile<T = unknown>(filePath: string): T | null {\n try {\n if (!existsSync(filePath)) return null;\n const content = readFileSync(filePath, 'utf-8');\n return JSON.parse(content) as T;\n } catch {\n return null;\n }\n}\n\n/** Safely write a JSON file, creating parent dirs if needed */\nexport function writeJsonFile(filePath: string, data: unknown): void {\n ensureDir(dirname(filePath));\n writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');\n}\n\n/** Safe string truncation */\nexport function truncate(str: string, maxLength: number): string {\n if (str.length <= maxLength) return str;\n return str.slice(0, maxLength - 3) + '...';\n}\n\n/** Sleep for a given number of milliseconds */\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/** Generate a short ID */\nexport function shortId(): string {\n return Math.random().toString(36).slice(2, 10);\n}\n\n/** Format bytes into human-readable string */\nexport function formatBytes(bytes: number): string {\n if (bytes === 0) return '0 B';\n const k = 1024;\n const sizes = ['B', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;\n}\n\n/** Format a duration in ms to human-readable */\nexport function formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`;\n if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;\n if (ms < 3600000) return `${Math.floor(ms / 60000)}m ${Math.floor((ms % 60000) / 1000)}s`;\n return `${Math.floor(ms / 3600000)}h ${Math.floor((ms % 3600000) / 60000)}m`;\n}\n\n/** Deep merge two objects */\nexport function deepMerge<T extends Record<string, unknown>>(target: T, source: Partial<T>): T {\n const result = { ...target };\n for (const key of Object.keys(source) as Array<keyof T>) {\n const sourceVal = source[key];\n const targetVal = result[key];\n if (\n sourceVal &&\n typeof sourceVal === 'object' &&\n !Array.isArray(sourceVal) &&\n targetVal &&\n typeof targetVal === 'object' &&\n !Array.isArray(targetVal)\n ) {\n result[key] = deepMerge(\n targetVal as Record<string, unknown>,\n sourceVal as Record<string, unknown>,\n ) as T[keyof T];\n } else if (sourceVal !== undefined) {\n result[key] = sourceVal as T[keyof T];\n }\n }\n return result;\n}\n","/**\n * TITAN Configuration Schema — Zod-based validation with full type inference\n */\nimport { z } from 'zod';\nimport {\n DEFAULT_GATEWAY_HOST,\n DEFAULT_GATEWAY_PORT,\n DEFAULT_WEB_PORT,\n DEFAULT_MODEL,\n DEFAULT_MAX_TOKENS,\n DEFAULT_TEMPERATURE,\n DEFAULT_SANDBOX_MODE,\n ALLOWED_TOOLS_DEFAULT,\n} from '../utils/constants.js';\n\nexport const ProviderConfigSchema = z.object({\n apiKey: z.string().optional(),\n baseUrl: z.string().optional(),\n model: z.string().optional(),\n maxTokens: z.number().optional(),\n temperature: z.number().min(0).max(2).optional(),\n});\n\nexport const ChannelConfigSchema = z.object({\n enabled: z.boolean().default(false),\n token: z.string().optional(),\n apiKey: z.string().optional(),\n allowFrom: z.array(z.string()).default([]),\n dmPolicy: z.enum(['pairing', 'open', 'closed']).default('pairing'),\n});\n\nexport const SecurityConfigSchema = z.object({\n sandboxMode: z.enum(['host', 'docker', 'none']).default(DEFAULT_SANDBOX_MODE as 'host'),\n allowedTools: z.array(z.string()).default(ALLOWED_TOOLS_DEFAULT),\n deniedTools: z.array(z.string()).default([]),\n maxConcurrentTasks: z.number().default(5),\n commandTimeout: z.number().default(30000),\n fileSystemAllowlist: z.array(z.string()).default([]),\n networkAllowlist: z.array(z.string()).default(['*']),\n shield: z.object({\n enabled: z.boolean().default(true),\n mode: z.enum(['standard', 'strict']).default('strict'),\n }).default({}),\n});\n\nexport const GatewayConfigSchema = z.object({\n host: z.string().default(DEFAULT_GATEWAY_HOST),\n port: z.number().default(DEFAULT_GATEWAY_PORT),\n webPort: z.number().default(DEFAULT_WEB_PORT),\n auth: z.object({\n mode: z.enum(['none', 'token', 'password']).default('token'),\n token: z.string().optional(),\n password: z.string().optional(),\n }).default({}),\n});\n\nexport const AgentConfigSchema = z.object({\n model: z.string().default(DEFAULT_MODEL),\n maxTokens: z.number().default(DEFAULT_MAX_TOKENS),\n temperature: z.number().default(DEFAULT_TEMPERATURE),\n systemPrompt: z.string().optional(),\n workspace: z.string().optional(),\n thinkingMode: z.enum(['off', 'low', 'medium', 'high']).default('medium'),\n});\n\nexport const TitanConfigSchema = z.object({\n agent: AgentConfigSchema.default({}),\n providers: z.object({\n anthropic: ProviderConfigSchema.default({}),\n openai: ProviderConfigSchema.default({}),\n google: ProviderConfigSchema.default({}),\n ollama: ProviderConfigSchema.default({}),\n }).default({}),\n channels: z.object({\n discord: ChannelConfigSchema.default({}),\n telegram: ChannelConfigSchema.default({}),\n slack: ChannelConfigSchema.default({}),\n whatsapp: ChannelConfigSchema.default({}),\n webchat: ChannelConfigSchema.default({}),\n googlechat: ChannelConfigSchema.default({}),\n matrix: ChannelConfigSchema.default({}),\n signal: ChannelConfigSchema.default({}),\n msteams: ChannelConfigSchema.default({}),\n bluebubbles: ChannelConfigSchema.default({}),\n }).default({}),\n gateway: GatewayConfigSchema.default({}),\n security: SecurityConfigSchema.default({}),\n memory: z.object({\n enabled: z.boolean().default(true),\n maxHistoryMessages: z.number().default(50),\n vectorSearchEnabled: z.boolean().default(false),\n }).default({}),\n skills: z.object({\n enabled: z.boolean().default(true),\n autoDiscover: z.boolean().default(true),\n marketplace: z.boolean().default(false),\n }).default({}),\n logging: z.object({\n level: z.enum(['debug', 'info', 'warn', 'error', 'silent']).default('info'),\n file: z.boolean().default(true),\n }).default({}),\n autonomy: z.object({\n /** autonomous = full auto, supervised = asks for dangerous ops, locked = asks for everything */\n mode: z.enum(['autonomous', 'supervised', 'locked']).default('supervised'),\n /** Auto-approve moderate-risk tools in main session (cli/webchat) */\n autoApproveMainSession: z.boolean().default(true),\n /** Timeout for HITL approval requests (ms). Auto-deny after timeout. */\n approvalTimeoutMs: z.number().default(60000),\n /** Notify user of auto-approved actions */\n notifyOnAutoApprove: z.boolean().default(true),\n }).default({}),\n});\n\nexport type TitanConfig = z.infer<typeof TitanConfigSchema>;\nexport type ProviderConfig = z.infer<typeof ProviderConfigSchema>;\nexport type ChannelConfig = z.infer<typeof ChannelConfigSchema>;\nexport type SecurityConfig = z.infer<typeof SecurityConfigSchema>;\nexport type GatewayConfig = z.infer<typeof GatewayConfigSchema>;\nexport type AgentConfig = z.infer<typeof AgentConfigSchema>;\n","/**\n * TITAN Configuration Manager\n * Loads, validates, and persists configuration from ~/.titan/titan.json\n */\nimport { existsSync } from 'fs';\nimport { TITAN_CONFIG_PATH, TITAN_HOME } from '../utils/constants.js';\nimport { readJsonFile, writeJsonFile, ensureDir, deepMerge } from '../utils/helpers.js';\nimport { TitanConfigSchema, type TitanConfig } from './schema.js';\nimport logger from '../utils/logger.js';\n\nconst COMPONENT = 'Config';\n\nlet cachedConfig: TitanConfig | null = null;\n\n/** Get the default configuration */\nexport function getDefaultConfig(): TitanConfig {\n return TitanConfigSchema.parse({});\n}\n\n/** Load configuration from disk, merging with defaults */\nexport function loadConfig(): TitanConfig {\n if (cachedConfig) return cachedConfig;\n\n ensureDir(TITAN_HOME);\n\n let rawConfig: Record<string, unknown> = {};\n\n if (existsSync(TITAN_CONFIG_PATH)) {\n const loaded = readJsonFile<Record<string, unknown>>(TITAN_CONFIG_PATH);\n if (loaded) {\n rawConfig = loaded;\n logger.debug(COMPONENT, `Loaded config from ${TITAN_CONFIG_PATH}`);\n } else {\n logger.warn(COMPONENT, `Failed to parse config at ${TITAN_CONFIG_PATH}, using defaults`);\n }\n } else {\n logger.info(COMPONENT, 'No config file found, using defaults');\n }\n\n // Apply environment variables\n applyEnvOverrides(rawConfig);\n\n // Validate and merge with defaults via Zod\n const result = TitanConfigSchema.safeParse(rawConfig);\n if (!result.success) {\n logger.warn(COMPONENT, 'Config validation issues, using defaults for invalid fields');\n logger.debug(COMPONENT, result.error.message);\n cachedConfig = getDefaultConfig();\n } else {\n cachedConfig = result.data;\n }\n\n return cachedConfig;\n}\n\n/** Save current configuration to disk */\nexport function saveConfig(config: TitanConfig): void {\n ensureDir(TITAN_HOME);\n writeJsonFile(TITAN_CONFIG_PATH, config);\n cachedConfig = config;\n logger.info(COMPONENT, `Config saved to ${TITAN_CONFIG_PATH}`);\n}\n\n/** Update specific fields in the config */\nexport function updateConfig(partial: Partial<TitanConfig>): TitanConfig {\n const current = loadConfig();\n const updated = deepMerge(current as Record<string, unknown>, partial as Record<string, unknown>) as TitanConfig;\n const validated = TitanConfigSchema.parse(updated);\n saveConfig(validated);\n return validated;\n}\n\n/** Reset config cache (useful for testing) */\nexport function resetConfigCache(): void {\n cachedConfig = null;\n}\n\n/** Check if the configuration file exists */\nexport function configExists(): boolean {\n return existsSync(TITAN_CONFIG_PATH);\n}\n\n/** Apply environment variable overrides to raw config */\nfunction applyEnvOverrides(config: Record<string, unknown>): void {\n const envMap: Record<string, (val: string) => void> = {\n TITAN_MODEL: (val) => setNested(config, 'agent.model', val),\n TITAN_GATEWAY_PORT: (val) => setNested(config, 'gateway.port', parseInt(val, 10)),\n TITAN_GATEWAY_HOST: (val) => setNested(config, 'gateway.host', val),\n TITAN_LOG_LEVEL: (val) => setNested(config, 'logging.level', val),\n ANTHROPIC_API_KEY: (val) => setNested(config, 'providers.anthropic.apiKey', val),\n OPENAI_API_KEY: (val) => setNested(config, 'providers.openai.apiKey', val),\n GOOGLE_API_KEY: (val) => setNested(config, 'providers.google.apiKey', val),\n OLLAMA_BASE_URL: (val) => setNested(config, 'providers.ollama.baseUrl', val),\n DISCORD_TOKEN: (val) => setNested(config, 'channels.discord.token', val),\n TELEGRAM_TOKEN: (val) => setNested(config, 'channels.telegram.token', val),\n SLACK_TOKEN: (val) => setNested(config, 'channels.slack.token', val),\n };\n\n for (const [envKey, setter] of Object.entries(envMap)) {\n const val = process.env[envKey];\n if (val) {\n setter(val);\n logger.debug(COMPONENT, `Applied env override: ${envKey}`);\n }\n }\n}\n\n/** Set a nested property by dot-notation path */\nfunction setNested(obj: Record<string, unknown>, path: string, value: unknown): void {\n const parts = path.split('.');\n let current: Record<string, unknown> = obj;\n for (let i = 0; i < parts.length - 1; i++) {\n if (!current[parts[i]] || typeof current[parts[i]] !== 'object') {\n current[parts[i]] = {};\n }\n current = current[parts[i]] as Record<string, unknown>;\n }\n current[parts[parts.length - 1]] = value;\n}\n","/**\n * TITAN — Tool Runner\n * Executes tool calls from the LLM with sandboxing, timeouts, and result formatting.\n */\nimport type { ToolCall, ToolDefinition } from '../providers/base.js';\nimport logger from '../utils/logger.js';\nimport { loadConfig } from '../config/config.js';\n\nconst COMPONENT = 'ToolRunner';\n\n/** Tool execution result */\nexport interface ToolResult {\n toolCallId: string;\n name: string;\n content: string;\n success: boolean;\n durationMs: number;\n}\n\n/** A registered tool handler */\nexport interface ToolHandler {\n name: string;\n description: string;\n parameters: Record<string, unknown>;\n execute: (args: Record<string, unknown>) => Promise<string>;\n}\n\n/** Global tool registry */\nconst toolRegistry: Map<string, ToolHandler> = new Map();\n\n/** Register a tool */\nexport function registerTool(handler: ToolHandler): void {\n toolRegistry.set(handler.name, handler);\n logger.debug(COMPONENT, `Registered tool: ${handler.name}`);\n}\n\n/** Unregister a tool */\nexport function unregisterTool(name: string): void {\n toolRegistry.delete(name);\n}\n\n/** Get all registered tools */\nexport function getRegisteredTools(): ToolHandler[] {\n return Array.from(toolRegistry.values());\n}\n\n/** Convert registered tools to LLM tool definitions */\nexport function getToolDefinitions(): ToolDefinition[] {\n const config = loadConfig();\n const allowed = new Set(config.security.allowedTools);\n const denied = new Set(config.security.deniedTools);\n\n return Array.from(toolRegistry.values())\n .filter((tool) => {\n if (denied.has(tool.name)) return false;\n if (allowed.size > 0 && !allowed.has(tool.name)) return false;\n return true;\n })\n .map((tool) => ({\n type: 'function' as const,\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.parameters,\n },\n }));\n}\n\n/** Execute a single tool call */\nexport async function executeTool(toolCall: ToolCall): Promise<ToolResult> {\n const config = loadConfig();\n const startTime = Date.now();\n const handler = toolRegistry.get(toolCall.function.name);\n\n if (!handler) {\n return {\n toolCallId: toolCall.id,\n name: toolCall.function.name,\n content: `Error: Unknown tool \"${toolCall.function.name}\"`,\n success: false,\n durationMs: Date.now() - startTime,\n };\n }\n\n // Check permissions\n if (config.security.deniedTools.includes(handler.name)) {\n return {\n toolCallId: toolCall.id,\n name: handler.name,\n content: `Error: Tool \"${handler.name}\" is denied by security policy`,\n success: false,\n durationMs: Date.now() - startTime,\n };\n }\n\n try {\n // Parse arguments\n let args: Record<string, unknown> = {};\n try {\n args = JSON.parse(toolCall.function.arguments);\n } catch {\n args = {};\n }\n\n logger.info(COMPONENT, `Executing tool: ${handler.name}`);\n\n // Execute with timeout\n const timeout = config.security.commandTimeout || 30000;\n const result = await Promise.race([\n handler.execute(args),\n new Promise<string>((_, reject) =>\n setTimeout(() => reject(new Error(`Tool \"${handler.name}\" timed out after ${timeout}ms`)), timeout)\n ),\n ]);\n\n const durationMs = Date.now() - startTime;\n logger.info(COMPONENT, `Tool ${handler.name} completed in ${durationMs}ms`);\n\n return {\n toolCallId: toolCall.id,\n name: handler.name,\n content: result,\n success: true,\n durationMs,\n };\n } catch (error) {\n const durationMs = Date.now() - startTime;\n const errorMsg = (error as Error).message;\n logger.error(COMPONENT, `Tool ${handler.name} failed: ${errorMsg}`);\n\n return {\n toolCallId: toolCall.id,\n name: handler.name,\n content: `Error: ${errorMsg}`,\n success: false,\n durationMs,\n };\n }\n}\n\n/** Execute multiple tool calls (in parallel where possible) */\nexport async function executeTools(toolCalls: ToolCall[]): Promise<ToolResult[]> {\n const config = loadConfig();\n const maxConcurrent = config.security.maxConcurrentTasks || 5;\n\n // Execute in batches\n const results: ToolResult[] = [];\n for (let i = 0; i < toolCalls.length; i += maxConcurrent) {\n const batch = toolCalls.slice(i, i + maxConcurrent);\n const batchResults = await Promise.all(batch.map(executeTool));\n results.push(...batchResults);\n }\n\n return results;\n}\n","/**\n * TITAN — Skills Registry\n * Discovers, loads, and manages skills from bundled, workspace, and marketplace sources.\n */\nimport { existsSync, readdirSync, readFileSync } from 'fs';\nimport { join } from 'path';\nimport { TITAN_HOME, TITAN_SKILLS_DIR } from '../utils/constants.js';\nimport { registerTool, type ToolHandler } from '../agent/toolRunner.js';\nimport { ensureDir } from '../utils/helpers.js';\nimport logger from '../utils/logger.js';\n\nconst COMPONENT = 'Skills';\n\nexport interface SkillMeta {\n name: string;\n description: string;\n version: string;\n author?: string;\n source: 'bundled' | 'workspace' | 'marketplace';\n enabled: boolean;\n}\n\nconst registeredSkills: Map<string, SkillMeta> = new Map();\n\n/** Register a built-in skill (tool handler + metadata) */\nexport function registerSkill(meta: SkillMeta, handler: ToolHandler): void {\n registeredSkills.set(meta.name, meta);\n registerTool(handler);\n logger.debug(COMPONENT, `Registered skill: ${meta.name} (${meta.source})`);\n}\n\n/** Get all registered skills */\nexport function getSkills(): SkillMeta[] {\n return Array.from(registeredSkills.values());\n}\n\n/** Get a skill by name */\nexport function getSkill(name: string): SkillMeta | undefined {\n return registeredSkills.get(name);\n}\n\n/** Discover workspace skills from ~/.titan/workspace/skills/ */\nexport function discoverWorkspaceSkills(): SkillMeta[] {\n ensureDir(TITAN_SKILLS_DIR);\n const discovered: SkillMeta[] = [];\n\n if (!existsSync(TITAN_SKILLS_DIR)) return discovered;\n\n const entries = readdirSync(TITAN_SKILLS_DIR, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n\n const skillDir = join(TITAN_SKILLS_DIR, entry.name);\n const skillMdPath = join(skillDir, 'SKILL.md');\n\n if (!existsSync(skillMdPath)) continue;\n\n try {\n const content = readFileSync(skillMdPath, 'utf-8');\n const meta = parseSkillMd(content, entry.name);\n if (meta) {\n discovered.push({ ...meta, source: 'workspace', enabled: true });\n }\n } catch (error) {\n logger.warn(COMPONENT, `Failed to load skill ${entry.name}: ${(error as Error).message}`);\n }\n }\n\n logger.info(COMPONENT, `Discovered ${discovered.length} workspace skills`);\n return discovered;\n}\n\n/** Parse SKILL.md frontmatter to extract metadata */\nfunction parseSkillMd(content: string, fallbackName: string): Omit<SkillMeta, 'source' | 'enabled'> | null {\n const frontmatterMatch = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!frontmatterMatch) {\n return {\n name: fallbackName,\n description: content.split('\\n')[0] || 'No description',\n version: '1.0.0',\n };\n }\n\n const frontmatter = frontmatterMatch[1];\n const name = frontmatter.match(/name:\\s*(.+)/)?.[1]?.trim() || fallbackName;\n const description = frontmatter.match(/description:\\s*(.+)/)?.[1]?.trim() || 'No description';\n const version = frontmatter.match(/version:\\s*(.+)/)?.[1]?.trim() || '1.0.0';\n const author = frontmatter.match(/author:\\s*(.+)/)?.[1]?.trim();\n\n return { name, description, version, author };\n}\n\n/** Initialize all built-in skills */\nexport async function initBuiltinSkills(): Promise<void> {\n logger.info(COMPONENT, 'Loading built-in skills...');\n\n // Import and register built-in skills\n const { registerShellSkill } = await import('./builtin/shell.js');\n const { registerFilesystemSkill } = await import('./builtin/filesystem.js');\n const { registerWebSearchSkill } = await import('./builtin/web_search.js');\n const { registerCronSkill } = await import('./builtin/cron.js');\n const { registerWebhookSkill } = await import('./builtin/webhook.js');\n const { registerMemorySkill } = await import('./builtin/memory_skill.js');\n const { registerBrowserSkill } = await import('./builtin/browser.js');\n const { registerSessionsSkill } = await import('./builtin/sessions.js');\n const { registerProcessSkill } = await import('./builtin/process.js');\n const { registerWebFetchSkill } = await import('./builtin/web_fetch.js');\n const { registerApplyPatchSkill } = await import('./builtin/apply_patch.js');\n const { registerAutoGenerateSkill } = await import('./builtin/auto_generate.js');\n const { registerVisionSkill } = await import('./builtin/vision.js');\n const { registerVoiceSkills } = await import('./builtin/voice.js');\n\n registerShellSkill();\n registerFilesystemSkill();\n registerWebSearchSkill();\n registerCronSkill();\n registerWebhookSkill();\n registerMemorySkill();\n registerBrowserSkill();\n registerSessionsSkill();\n registerProcessSkill();\n registerWebFetchSkill();\n registerApplyPatchSkill();\n registerAutoGenerateSkill();\n registerVisionSkill();\n registerVoiceSkills();\n\n logger.info(COMPONENT, `Loaded ${registeredSkills.size} built-in skills`);\n}\n\n/** \n * Discover and load auto-generated skills from ~/.titan/skills/auto/\n */\nexport async function loadAutoSkills(): Promise<void> {\n const autoDir = join(TITAN_HOME, 'skills', 'auto');\n if (!existsSync(autoDir)) return;\n\n logger.info(COMPONENT, 'Checking for auto-generated skills...');\n const files = readdirSync(autoDir).filter(f => f.endsWith('.js'));\n\n let loadedCount = 0;\n for (const file of files) {\n try {\n const skillPath = join(autoDir, file);\n // Append cache buster to force hot-reload of ES modules\n const modulePath = `file://${skillPath}?t=${Date.now()}`;\n const mod = await import(modulePath);\n\n if (mod.default && mod.default.name && mod.default.execute) {\n const handler = mod.default as ToolHandler;\n\n // Add to our registry metadata\n const meta: SkillMeta = {\n name: handler.name,\n description: handler.description || 'Auto-generated skill',\n version: '1.0.0',\n source: 'workspace', // Consider it part of user workspace\n enabled: true,\n };\n\n registerSkill(meta, handler);\n loadedCount++;\n }\n } catch (e: any) {\n logger.error(COMPONENT, `Failed to load auto skill ${file}: ${e.message}`);\n }\n }\n\n if (loadedCount > 0) {\n logger.info(COMPONENT, `Successfully loaded ${loadedCount} auto-generated skills`);\n }\n}\n","/**\n * TITAN — Encryption Module\n * Provides E2E encryption for sensitive sessions using AES-256-GCM.\n */\nimport { randomBytes, createCipheriv, createDecipheriv } from 'crypto';\nimport logger from '../utils/logger.js';\n\nconst COMPONENT = 'Encryption';\nconst ALGORITHM = 'aes-256-gcm';\n\nexport interface EncryptedPayload {\n iv: string;\n authTag: string;\n data: string;\n}\n\n/**\n * Generates a strong 256-bit encryption key securely.\n */\nexport function generateKey(): Buffer {\n return randomBytes(32);\n}\n\n/**\n * Encrypts a string of text using AES-256-GCM.\n * @param text The plaintext to encrypt\n * @param key The 32-byte encryption key\n */\nexport function encrypt(text: string, key: Buffer | string): EncryptedPayload {\n try {\n const keyBuffer = typeof key === 'string' ? Buffer.from(key, 'hex') : key;\n if (keyBuffer.length !== 32) {\n throw new Error('Encryption key must be exactly 32 bytes (256 bits).');\n }\n\n const iv = randomBytes(16);\n const cipher = createCipheriv(ALGORITHM, keyBuffer, iv);\n\n let encrypted = cipher.update(text, 'utf8', 'hex');\n encrypted += cipher.final('hex');\n\n const authTag = cipher.getAuthTag().toString('hex');\n\n return {\n iv: iv.toString('hex'),\n authTag,\n data: encrypted\n };\n } catch (e: any) {\n logger.error(COMPONENT, `Encryption failed: ${e.message}`);\n throw new Error('Failed to encrypt session data.');\n }\n}\n\n/**\n * Decrypts an EncryptedPayload back into plaintext text using AES-256-GCM.\n * @param payload The encrypted payload object (iv, authTag, data)\n * @param key The 32-byte encryption key\n */\nexport function decrypt(payload: EncryptedPayload, key: Buffer | string): string {\n try {\n const keyBuffer = typeof key === 'string' ? Buffer.from(key, 'hex') : key;\n if (keyBuffer.length !== 32) {\n throw new Error('Decryption key must be exactly 32 bytes (256 bits).');\n }\n\n const decipher = createDecipheriv(ALGORITHM, keyBuffer, Buffer.from(payload.iv, 'hex'));\n decipher.setAuthTag(Buffer.from(payload.authTag, 'hex'));\n\n let decrypted = decipher.update(payload.data, 'hex', 'utf8');\n decrypted += decipher.final('utf8');\n\n return decrypted;\n } catch (e: any) {\n logger.error(COMPONENT, `Decryption failed: ${e.message}`);\n throw new Error('Failed to decrypt session data. Invalid key or corrupted payload.');\n }\n}\n","/**\n * TITAN — Memory / Persistence System\n * JSON-file-backed persistent memory for conversations, facts, preferences, and usage.\n * Uses no native dependencies — pure Node.js for maximum portability.\n */\nimport { existsSync, readFileSync, writeFileSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { TITAN_DB_PATH, TITAN_HOME } from '../utils/constants.js';\nimport { ensureDir } from '../utils/helpers.js';\nimport logger from '../utils/logger.js';\nimport { encrypt, decrypt, type EncryptedPayload } from '../security/encryption.js';\n\nconst COMPONENT = 'Memory';\n\n// ─── Data Store ──────────────────────────────────────────────────\n\ninterface DataStore {\n conversations: ConversationMessage[];\n memories: MemoryEntry[];\n sessions: SessionRecord[];\n usageStats: UsageRecord[];\n cronJobs: CronRecord[];\n skillsInstalled: SkillRecord[];\n}\n\ninterface MemoryEntry {\n id: string;\n category: string;\n key: string;\n value: string;\n metadata?: string;\n createdAt: string;\n updatedAt: string;\n}\n\ninterface SessionRecord {\n id: string;\n channel: string;\n user_id: string;\n agent_id: string;\n status: string;\n message_count: number;\n created_at: string;\n last_active: string;\n}\n\ninterface UsageRecord {\n id: number;\n session_id: string;\n provider: string;\n model: string;\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n created_at: string;\n}\n\ninterface CronRecord {\n id: string;\n name: string;\n schedule: string;\n command: string;\n enabled: boolean;\n last_run?: string;\n next_run?: string;\n created_at: string;\n}\n\ninterface SkillRecord {\n name: string;\n version: string;\n source: string;\n enabled: boolean;\n installed_at: string;\n}\n\nconst DB_FILE = join(TITAN_HOME, 'titan-data.json');\n\nlet store: DataStore | null = null;\n\nfunction getDefaultStore(): DataStore {\n return {\n conversations: [],\n memories: [],\n sessions: [],\n usageStats: [],\n cronJobs: [],\n skillsInstalled: [],\n };\n}\n\nfunction loadStore(): DataStore {\n if (store) return store;\n ensureDir(TITAN_HOME);\n if (existsSync(DB_FILE)) {\n try {\n const raw = readFileSync(DB_FILE, 'utf-8');\n store = JSON.parse(raw) as DataStore;\n // Ensure all fields exist\n store.conversations = store.conversations || [];\n store.memories = store.memories || [];\n store.sessions = store.sessions || [];\n store.usageStats = store.usageStats || [];\n store.cronJobs = store.cronJobs || [];\n store.skillsInstalled = store.skillsInstalled || [];\n } catch {\n logger.warn(COMPONENT, 'Could not load data store, creating fresh one');\n store = getDefaultStore();\n }\n } else {\n store = getDefaultStore();\n }\n return store;\n}\n\nfunction saveStore(): void {\n if (!store) return;\n ensureDir(TITAN_HOME);\n try {\n writeFileSync(DB_FILE, JSON.stringify(store, null, 2), 'utf-8');\n } catch (e) {\n logger.error(COMPONENT, `Failed to save data: ${(e as Error).message}`);\n }\n}\n\n// Auto-save periodically\nlet saveTimeout: ReturnType<typeof setTimeout> | null = null;\nfunction debouncedSave(): void {\n if (saveTimeout) clearTimeout(saveTimeout);\n saveTimeout = setTimeout(saveStore, 1000);\n}\n\n/** Initialize the memory system */\nexport function initMemory(): void {\n loadStore();\n logger.info(COMPONENT, 'Memory system initialized');\n}\n\n/** Close / flush the memory system */\nexport function closeMemory(): void {\n saveStore();\n store = null;\n}\n\n/** Get internal store (for skills like cron that need direct access) */\nexport function getDb(): DataStore {\n return loadStore();\n}\n\n// ─── Conversation History ────────────────────────────────────────\n\nexport interface ConversationMessage {\n id: string;\n sessionId: string;\n role: string;\n content: string;\n toolCalls?: string;\n toolCallId?: string;\n model?: string;\n tokenCount: number;\n createdAt: string;\n isEncrypted?: boolean;\n}\n\n/** Save a message to conversation history */\nexport function saveMessage(message: Omit<ConversationMessage, 'createdAt'>, e2eKey?: string): void {\n const s = loadStore();\n\n let content = message.content;\n let isEncrypted = false;\n\n if (e2eKey) {\n try {\n const payload = encrypt(message.content, Buffer.from(e2eKey, 'base64'));\n content = JSON.stringify(payload);\n isEncrypted = true;\n } catch (e) {\n logger.error(COMPONENT, `Failed to encrypt message for storage`);\n content = \"[ENCRYPTION FAILED] \" + content; // Fallback, though we should probably throw in strict environments\n }\n }\n\n s.conversations.push({\n ...message,\n content,\n isEncrypted,\n createdAt: new Date().toISOString(),\n });\n // Keep only last 5000 messages total to prevent unbounded growth\n if (s.conversations.length > 5000) {\n s.conversations = s.conversations.slice(-5000);\n }\n debouncedSave();\n}\n\n/** Get conversation history for a session */\nexport function getHistory(sessionId: string, limit: number = 50, e2eKey?: string): ConversationMessage[] {\n const s = loadStore();\n const rawHistory = s.conversations\n .filter((m) => m.sessionId === sessionId)\n .slice(-limit);\n\n if (!e2eKey) {\n // If no key is provided, we just return the raw payload. \n // If it's encrypted, it'll just show the JSON string of the EncryptedPayload.\n return rawHistory;\n }\n\n // Decrypt the ones that were encrypted\n return rawHistory.map(m => {\n if (m.isEncrypted) {\n try {\n const payload = JSON.parse(m.content) as EncryptedPayload;\n return {\n ...m,\n content: decrypt(payload, Buffer.from(e2eKey, 'base64'))\n };\n } catch (e) {\n logger.error(COMPONENT, `Failed to decrypt message ${m.id}`);\n return { ...m, content: \"[DECRYPTION FAILED]\" };\n }\n }\n return m;\n });\n}\n\n/** Clear conversation history for a session */\nexport function clearHistory(sessionId: string): void {\n const s = loadStore();\n s.conversations = s.conversations.filter((m) => m.sessionId !== sessionId);\n debouncedSave();\n}\n\n// ─── Persistent Memory (Facts / Preferences) ─────────────────────\n\n/** Store a memory (key-value with category) */\nexport function rememberFact(category: string, key: string, value: string, metadata?: Record<string, unknown>): void {\n const s = loadStore();\n const id = `${category}:${key}`;\n const existingIdx = s.memories.findIndex((m) => m.id === id);\n const now = new Date().toISOString();\n\n if (existingIdx >= 0) {\n s.memories[existingIdx].value = value;\n s.memories[existingIdx].metadata = metadata ? JSON.stringify(metadata) : undefined;\n s.memories[existingIdx].updatedAt = now;\n } else {\n s.memories.push({\n id,\n category,\n key,\n value,\n metadata: metadata ? JSON.stringify(metadata) : undefined,\n createdAt: now,\n updatedAt: now,\n });\n }\n debouncedSave();\n}\n\n/** Recall a specific memory */\nexport function recallFact(category: string, key: string): string | null {\n const s = loadStore();\n const entry = s.memories.find((m) => m.category === category && m.key === key);\n return entry?.value || null;\n}\n\n/** Search memories by category */\nexport function searchMemories(category?: string, query?: string): Array<{ key: string; value: string; category: string }> {\n const s = loadStore();\n let results = s.memories;\n\n if (category) {\n results = results.filter((m) => m.category === category);\n }\n if (query) {\n const q = query.toLowerCase();\n results = results.filter((m) =>\n m.key.toLowerCase().includes(q) || m.value.toLowerCase().includes(q)\n );\n }\n\n return results.slice(-50).map((m) => ({ key: m.key, value: m.value, category: m.category }));\n}\n\n// ─── Usage Tracking ──────────────────────────────────────────────\n\n/** Record usage statistics */\nexport function recordUsage(sessionId: string, provider: string, model: string, promptTokens: number, completionTokens: number): void {\n const s = loadStore();\n s.usageStats.push({\n id: s.usageStats.length + 1,\n session_id: sessionId,\n provider,\n model,\n prompt_tokens: promptTokens,\n completion_tokens: completionTokens,\n total_tokens: promptTokens + completionTokens,\n created_at: new Date().toISOString(),\n });\n // Keep only last 10000 records\n if (s.usageStats.length > 10000) {\n s.usageStats = s.usageStats.slice(-10000);\n }\n debouncedSave();\n}\n\n/** Get total usage statistics */\nexport function getUsageStats(): { totalTokens: number; totalRequests: number; byProvider: Record<string, number> } {\n const s = loadStore();\n let totalTokens = 0;\n const byProvider: Record<string, number> = {};\n\n for (const rec of s.usageStats) {\n totalTokens += rec.total_tokens;\n byProvider[rec.provider] = (byProvider[rec.provider] || 0) + rec.total_tokens;\n }\n\n return {\n totalTokens,\n totalRequests: s.usageStats.length,\n byProvider,\n };\n}\n","/**\n * TITAN — Memory Skill (Built-in)\n * Persistent fact/preference storage for the agent.\n */\nimport { registerSkill } from '../registry.js';\nimport { rememberFact, recallFact, searchMemories } from '../../memory/memory.js';\n\nexport function registerMemorySkill(): void {\n registerSkill(\n { name: 'memory', description: 'Persistent memory management', version: '1.0.0', source: 'bundled', enabled: true },\n {\n name: 'memory',\n description: 'Store and recall persistent memories. Use this to remember user preferences, important facts, project details, and anything that should persist across conversations.',\n parameters: {\n type: 'object',\n properties: {\n action: { type: 'string', enum: ['remember', 'recall', 'search', 'list'], description: 'Action' },\n category: { type: 'string', description: 'Memory category (e.g., \"preference\", \"fact\", \"project\")' },\n key: { type: 'string', description: 'Memory key/name' },\n value: { type: 'string', description: 'Value to remember' },\n query: { type: 'string', description: 'Search query (for search action)' },\n },\n required: ['action'],\n },\n execute: async (args) => {\n const action = args.action as string;\n const category = (args.category as string) || 'general';\n\n switch (action) {\n case 'remember': {\n const key = args.key as string;\n const value = args.value as string;\n if (!key || !value) return 'Error: key and value are required';\n rememberFact(category, key, value);\n return `Remembered: [${category}] ${key} = ${value}`;\n }\n case 'recall': {\n const rKey = args.key as string;\n if (!rKey) return 'Error: key is required';\n const value = recallFact(category, rKey);\n return value ? `[${category}] ${rKey} = ${value}` : `No memory found for [${category}] ${rKey}`;\n }\n case 'search': {\n const query = args.query as string;\n const results = searchMemories(category !== 'general' ? category : undefined, query);\n if (results.length === 0) return 'No matching memories found.';\n return results.map((m) => `• [${m.category}] ${m.key}: ${m.value}`).join('\\n');\n }\n case 'list': {\n const all = searchMemories(category !== 'general' ? category : undefined);\n if (all.length === 0) return 'No memories stored yet.';\n return all.map((m) => `• [${m.category}] ${m.key}: ${m.value}`).join('\\n');\n }\n default:\n return `Unknown action: ${action}`;\n }\n },\n },\n );\n}\n"],"mappings":"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","names":["COMPONENT","existsSync","readFileSync","writeFileSync","join","COMPONENT"]}