@saccolabs/tars 1.0.7
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/README.md +93 -0
- package/context/GEMINI.md +13 -0
- package/context/config/settings.json-template +36 -0
- package/context/skills/create-extension/SKILL.md +90 -0
- package/context/skills/create-skill/SKILL.md +33 -0
- package/context/skills/manage-extensions/SKILL.md +69 -0
- package/context/skills/tars-ops/SKILL.md +89 -0
- package/dist/cli/commands/discord.d.ts +4 -0
- package/dist/cli/commands/discord.js +48 -0
- package/dist/cli/commands/discord.js.map +1 -0
- package/dist/cli/commands/export.d.ts +3 -0
- package/dist/cli/commands/export.js +39 -0
- package/dist/cli/commands/export.js.map +1 -0
- package/dist/cli/commands/import.d.ts +1 -0
- package/dist/cli/commands/import.js +45 -0
- package/dist/cli/commands/import.js.map +1 -0
- package/dist/cli/commands/logs.d.ts +4 -0
- package/dist/cli/commands/logs.js +23 -0
- package/dist/cli/commands/logs.js.map +1 -0
- package/dist/cli/commands/memory.d.ts +1 -0
- package/dist/cli/commands/memory.js +35 -0
- package/dist/cli/commands/memory.js.map +1 -0
- package/dist/cli/commands/secret.d.ts +6 -0
- package/dist/cli/commands/secret.js +46 -0
- package/dist/cli/commands/secret.js.map +1 -0
- package/dist/cli/commands/setup.d.ts +4 -0
- package/dist/cli/commands/setup.js +329 -0
- package/dist/cli/commands/setup.js.map +1 -0
- package/dist/cli/commands/start.d.ts +1 -0
- package/dist/cli/commands/start.js +42 -0
- package/dist/cli/commands/start.js.map +1 -0
- package/dist/cli/commands/status.d.ts +1 -0
- package/dist/cli/commands/status.js +56 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/stop.d.ts +1 -0
- package/dist/cli/commands/stop.js +38 -0
- package/dist/cli/commands/stop.js.map +1 -0
- package/dist/cli/commands/uninstall.d.ts +1 -0
- package/dist/cli/commands/uninstall.js +91 -0
- package/dist/cli/commands/uninstall.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +54 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config/config.d.ts +14 -0
- package/dist/config/config.js +69 -0
- package/dist/config/config.js.map +1 -0
- package/dist/discord/discord-bot.d.ts +32 -0
- package/dist/discord/discord-bot.js +151 -0
- package/dist/discord/discord-bot.js.map +1 -0
- package/dist/discord/message-formatter.d.ts +95 -0
- package/dist/discord/message-formatter.js +448 -0
- package/dist/discord/message-formatter.js.map +1 -0
- package/dist/memory/knowledge-store.d.ts +24 -0
- package/dist/memory/knowledge-store.js +126 -0
- package/dist/memory/knowledge-store.js.map +1 -0
- package/dist/memory/memory-manager.d.ts +24 -0
- package/dist/memory/memory-manager.js +101 -0
- package/dist/memory/memory-manager.js.map +1 -0
- package/dist/scripts/debug-cli.d.ts +1 -0
- package/dist/scripts/debug-cli.js +52 -0
- package/dist/scripts/debug-cli.js.map +1 -0
- package/dist/supervisor/gemini-cli.d.ts +28 -0
- package/dist/supervisor/gemini-cli.js +315 -0
- package/dist/supervisor/gemini-cli.js.map +1 -0
- package/dist/supervisor/heartbeat-service.d.ts +21 -0
- package/dist/supervisor/heartbeat-service.js +143 -0
- package/dist/supervisor/heartbeat-service.js.map +1 -0
- package/dist/supervisor/main.d.ts +1 -0
- package/dist/supervisor/main.js +242 -0
- package/dist/supervisor/main.js.map +1 -0
- package/dist/supervisor/session-manager.d.ts +47 -0
- package/dist/supervisor/session-manager.js +118 -0
- package/dist/supervisor/session-manager.js.map +1 -0
- package/dist/supervisor/supervisor.d.ts +32 -0
- package/dist/supervisor/supervisor.js +98 -0
- package/dist/supervisor/supervisor.js.map +1 -0
- package/dist/types/index.d.ts +42 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/attachment-processor.d.ts +22 -0
- package/dist/utils/attachment-processor.js +79 -0
- package/dist/utils/attachment-processor.js.map +1 -0
- package/dist/utils/logger.d.ts +6 -0
- package/dist/utils/logger.js +15 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/secrets-manager.d.ts +27 -0
- package/dist/utils/secrets-manager.js +79 -0
- package/dist/utils/secrets-manager.js.map +1 -0
- package/dist/utils/version.d.ts +3 -0
- package/dist/utils/version.js +23 -0
- package/dist/utils/version.js.map +1 -0
- package/extensions/tasks/gemini-extension.json +14 -0
- package/extensions/tasks/package-lock.json +1209 -0
- package/extensions/tasks/package.json +19 -0
- package/extensions/tasks/src/server.ts +265 -0
- package/extensions/tasks/src/store.ts +92 -0
- package/extensions/tasks/tsconfig.json +14 -0
- package/package.json +55 -0
- package/src/prompts/system.md +25 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import logger from '../utils/logger.js';
|
|
3
|
+
import { CronExpressionParser } from 'cron-parser';
|
|
4
|
+
import { AttachmentProcessor } from '../utils/attachment-processor.js';
|
|
5
|
+
/**
|
|
6
|
+
* HeartbeatService - Manages background task execution via file polling
|
|
7
|
+
*/
|
|
8
|
+
export class HeartbeatService {
|
|
9
|
+
supervisor;
|
|
10
|
+
config;
|
|
11
|
+
interval = null;
|
|
12
|
+
isExecuting = false;
|
|
13
|
+
processor;
|
|
14
|
+
constructor(supervisor, config) {
|
|
15
|
+
this.supervisor = supervisor;
|
|
16
|
+
this.config = config;
|
|
17
|
+
this.processor = new AttachmentProcessor(config);
|
|
18
|
+
}
|
|
19
|
+
async start() {
|
|
20
|
+
const intervalMs = this.config.heartbeatIntervalMs;
|
|
21
|
+
logger.info(`💓 Heartbeat service started (Interval: ${intervalMs / 1000}s)`);
|
|
22
|
+
// Initial run
|
|
23
|
+
this.tick();
|
|
24
|
+
this.interval = setInterval(() => this.tick(), intervalMs);
|
|
25
|
+
}
|
|
26
|
+
stop() {
|
|
27
|
+
if (this.interval) {
|
|
28
|
+
clearInterval(this.interval);
|
|
29
|
+
this.interval = null;
|
|
30
|
+
}
|
|
31
|
+
logger.info('💓 Heartbeat service stopped');
|
|
32
|
+
}
|
|
33
|
+
async tick() {
|
|
34
|
+
if (this.isExecuting)
|
|
35
|
+
return;
|
|
36
|
+
this.isExecuting = true;
|
|
37
|
+
try {
|
|
38
|
+
// 1. Maintenance & Sync
|
|
39
|
+
this.processor.cleanup();
|
|
40
|
+
await this.supervisor.memory.fullSync();
|
|
41
|
+
// 2. Load Tasks
|
|
42
|
+
const tasks = await this.loadTasks();
|
|
43
|
+
const now = new Date();
|
|
44
|
+
const dueTasks = tasks.filter((t) => t.enabled && new Date(t.nextRun) <= now);
|
|
45
|
+
// 3. Autonomous Check (The OpenClaw style)
|
|
46
|
+
// If no hard-scheduled tasks, we do a semantic "health check"
|
|
47
|
+
if (dueTasks.length === 0) {
|
|
48
|
+
await this.autonomousCheck();
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
logger.info(`💓 Found ${dueTasks.length} due tasks`);
|
|
52
|
+
for (const task of dueTasks) {
|
|
53
|
+
await this.runTask(task);
|
|
54
|
+
}
|
|
55
|
+
await this.saveTasks(tasks);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
logger.error(`❌ Heartbeat tick error: ${error.message}`);
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
this.isExecuting = false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async autonomousCheck() {
|
|
66
|
+
// This is a "quiet" heartbeat. We ask the AI if anything needs attention
|
|
67
|
+
// based on the context it has in memory.
|
|
68
|
+
const prompt = `Self-Correction and Autonomous Heartbeat:\nReview your current objectives in GEMINI.md and any pending tasks.\nIf everything is on track and no immediate action is required, reply exactly with 'SILENT_ACK'.\nIf you detect an issue, a missed deadline, or a high-priority task that needs starting, provide a short internal reasoning and then describe the action you are taking.`;
|
|
69
|
+
try {
|
|
70
|
+
const response = await this.supervisor.executeTask(prompt);
|
|
71
|
+
if (response.includes('SILENT_ACK')) {
|
|
72
|
+
// Heartbeat OK, prune to prevent context bloat
|
|
73
|
+
await this.supervisor.pruneLastTurn();
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
// If the AI didn't say SILENT_ACK, it wants to do something!
|
|
77
|
+
logger.info(`🤖 Tars Heartbeat initiated action: ${response.substring(0, 100)}...`);
|
|
78
|
+
// Here we could route this to Discord or a Log.
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
logger.error(`❌ Autonomous check failed: ${error.message}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
async runTask(task) {
|
|
85
|
+
logger.info(`🚀 Running task: ${task.title} (${task.id})`);
|
|
86
|
+
try {
|
|
87
|
+
const result = await this.supervisor.executeTask(task.prompt);
|
|
88
|
+
logger.info(`✅ Task ${task.id} completed. Result length: ${result.length}`);
|
|
89
|
+
task.lastRun = new Date().toISOString();
|
|
90
|
+
task.failedCount = 0;
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
logger.error(`❌ Task ${task.id} failed: ${error.message}`);
|
|
94
|
+
task.failedCount++;
|
|
95
|
+
}
|
|
96
|
+
finally {
|
|
97
|
+
// Calculate next run
|
|
98
|
+
task.nextRun = this.calculateNextRun(task.schedule);
|
|
99
|
+
task.updatedAt = new Date().toISOString();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
calculateNextRun(schedule) {
|
|
103
|
+
try {
|
|
104
|
+
// 1. Try parsing as a cron expression (using the new 5.x API)
|
|
105
|
+
const interval = CronExpressionParser.parse(schedule);
|
|
106
|
+
const next = interval.next();
|
|
107
|
+
const iso = next.toISOString();
|
|
108
|
+
if (!iso) {
|
|
109
|
+
throw new Error('Could not calculate next run from cron.');
|
|
110
|
+
}
|
|
111
|
+
return iso;
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
// 2. If not cron, try parsing as a specific ISO date
|
|
115
|
+
const date = new Date(schedule);
|
|
116
|
+
if (!isNaN(date.getTime()) && schedule.includes('-')) {
|
|
117
|
+
// We check for '-' to ensure it's likely a date string and not a weird numeric cron fallback
|
|
118
|
+
return date.toISOString();
|
|
119
|
+
}
|
|
120
|
+
// 3. Absolute Fallback: Run in 24 hours if the schedule is totally unparseable
|
|
121
|
+
// This prevents the task from "looping" or getting stuck in the past
|
|
122
|
+
logger.warn(`⚠️ Unrecognized schedule format: "${schedule}". Falling back to 24h.`);
|
|
123
|
+
return new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
async loadTasks() {
|
|
127
|
+
try {
|
|
128
|
+
const data = await fs.readFile(this.config.taskFilePath, 'utf-8');
|
|
129
|
+
return JSON.parse(data);
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
if (error.code === 'ENOENT') {
|
|
133
|
+
return [];
|
|
134
|
+
}
|
|
135
|
+
throw error;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
async saveTasks(tasks) {
|
|
139
|
+
const data = JSON.stringify(tasks, null, 2);
|
|
140
|
+
await fs.writeFile(this.config.taskFilePath, data, 'utf-8');
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=heartbeat-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heartbeat-service.js","sourceRoot":"","sources":["../../src/supervisor/heartbeat-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { Config } from '../config/config.js';
|
|
2
|
+
import { GeminiCli } from './gemini-cli.js';
|
|
3
|
+
import { SessionManager } from './session-manager.js';
|
|
4
|
+
import { Supervisor } from './supervisor.js';
|
|
5
|
+
import { HeartbeatService } from './heartbeat-service.js';
|
|
6
|
+
import { DiscordBot } from '../discord/discord-bot.js';
|
|
7
|
+
import logger from '../utils/logger.js';
|
|
8
|
+
import fs from 'fs';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
12
|
+
const __dirname = path.dirname(__filename);
|
|
13
|
+
/**
|
|
14
|
+
* Install the fixed system prompt into the Tars home directory.
|
|
15
|
+
* This ensures Gemini CLI uses Tars' custom persona instead of the default coding-centric prompt.
|
|
16
|
+
*/
|
|
17
|
+
function installSystemPrompt(config) {
|
|
18
|
+
// Walk up from dist/supervisor/ or src/supervisor/ to find prompts/system.md
|
|
19
|
+
let searchDir = __dirname;
|
|
20
|
+
let srcPrompt = '';
|
|
21
|
+
// Try to find the prompt relative to the package root
|
|
22
|
+
for (let i = 0; i < 5; i++) {
|
|
23
|
+
const candidate = path.join(searchDir, 'prompts', 'system.md');
|
|
24
|
+
const srcCandidate = path.join(searchDir, 'src', 'prompts', 'system.md');
|
|
25
|
+
if (fs.existsSync(candidate)) {
|
|
26
|
+
srcPrompt = candidate;
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
else if (fs.existsSync(srcCandidate)) {
|
|
30
|
+
srcPrompt = srcCandidate;
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
searchDir = path.dirname(searchDir);
|
|
34
|
+
}
|
|
35
|
+
if (!srcPrompt) {
|
|
36
|
+
logger.warn('⚠️ Could not locate system.md prompt file');
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
// Ensure target directory exists
|
|
40
|
+
const targetDir = path.dirname(config.systemPromptPath);
|
|
41
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
42
|
+
// Always overwrite to ensure latest prompt is deployed
|
|
43
|
+
fs.copyFileSync(srcPrompt, config.systemPromptPath);
|
|
44
|
+
logger.info(`📝 System prompt installed: ${config.systemPromptPath}`);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Install built-in skills into the Tars runtime directory.
|
|
48
|
+
*/
|
|
49
|
+
/**
|
|
50
|
+
* Install and sync built-in skills into the Tars runtime directory.
|
|
51
|
+
* Safely updates built-in skills while preserving user-created ones.
|
|
52
|
+
*/
|
|
53
|
+
function installSkills(config) {
|
|
54
|
+
// 1. Locate context/skills/ in the repo
|
|
55
|
+
let searchDir = __dirname;
|
|
56
|
+
let skillsSrc = '';
|
|
57
|
+
for (let i = 0; i < 5; i++) {
|
|
58
|
+
const candidate = path.join(searchDir, 'context', 'skills');
|
|
59
|
+
const srcCandidate = path.join(searchDir, '..', 'context', 'skills'); // If in dist/supervisor/
|
|
60
|
+
if (fs.existsSync(candidate)) {
|
|
61
|
+
skillsSrc = candidate;
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
else if (fs.existsSync(srcCandidate)) {
|
|
65
|
+
skillsSrc = srcCandidate;
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
// Try finding context in root if running from src
|
|
69
|
+
const rootCandidate = path.join(searchDir, '..', '..', 'context', 'skills');
|
|
70
|
+
if (fs.existsSync(rootCandidate)) {
|
|
71
|
+
skillsSrc = rootCandidate;
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
searchDir = path.dirname(searchDir);
|
|
75
|
+
}
|
|
76
|
+
if (!skillsSrc) {
|
|
77
|
+
logger.warn('⚠️ Could not locate built-in skills directory');
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
// 2. Define target directory (~/.tars/.gemini/skills)
|
|
81
|
+
const skillsDest = path.join(config.homeDir, '.gemini', 'skills');
|
|
82
|
+
try {
|
|
83
|
+
if (!fs.existsSync(skillsDest)) {
|
|
84
|
+
fs.mkdirSync(skillsDest, { recursive: true });
|
|
85
|
+
}
|
|
86
|
+
// 3. Selective Sync: Copy each built-in skill individually
|
|
87
|
+
const builtInSkills = fs.readdirSync(skillsSrc);
|
|
88
|
+
for (const skillName of builtInSkills) {
|
|
89
|
+
const srcSkillPath = path.join(skillsSrc, skillName);
|
|
90
|
+
const destSkillPath = path.join(skillsDest, skillName);
|
|
91
|
+
// Only copy directories
|
|
92
|
+
if (!fs.statSync(srcSkillPath).isDirectory())
|
|
93
|
+
continue;
|
|
94
|
+
// Remove existing destination (to ensure clean update - e.g. deleting old files)
|
|
95
|
+
// This assumes built-in skills are managed entirely by the repo
|
|
96
|
+
if (fs.existsSync(destSkillPath)) {
|
|
97
|
+
fs.rmSync(destSkillPath, { recursive: true, force: true });
|
|
98
|
+
}
|
|
99
|
+
// Copy fresh from repo
|
|
100
|
+
fs.cpSync(srcSkillPath, destSkillPath, { recursive: true });
|
|
101
|
+
logger.info(`📚 Skill synced: ${skillName}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
logger.error(`❌ Failed to sync skills: ${error}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Automatically install/link extensions and enable them.
|
|
110
|
+
* Verifies symlinks are valid and re-links if broken.
|
|
111
|
+
*/
|
|
112
|
+
function installExtensions(config) {
|
|
113
|
+
const repoExtensionsDir = path.join(__dirname, '..', '..', 'extensions');
|
|
114
|
+
const targetExtensionsDir = path.join(config.homeDir, '.gemini', 'extensions');
|
|
115
|
+
const enablementFile = path.join(targetExtensionsDir, 'extension-enablement.json');
|
|
116
|
+
if (!fs.existsSync(repoExtensionsDir)) {
|
|
117
|
+
logger.warn('⚠️ Could not locate extensions directory');
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (!fs.existsSync(targetExtensionsDir)) {
|
|
121
|
+
fs.mkdirSync(targetExtensionsDir, { recursive: true });
|
|
122
|
+
}
|
|
123
|
+
// Load Enablement
|
|
124
|
+
let enablement = {};
|
|
125
|
+
if (fs.existsSync(enablementFile)) {
|
|
126
|
+
try {
|
|
127
|
+
enablement = JSON.parse(fs.readFileSync(enablementFile, 'utf-8'));
|
|
128
|
+
}
|
|
129
|
+
catch (e) {
|
|
130
|
+
logger.warn('⚠️ Could not parse extension-enablement.json, starting fresh');
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
const builtInExtensions = fs.readdirSync(repoExtensionsDir);
|
|
134
|
+
for (const extName of builtInExtensions) {
|
|
135
|
+
const srcPath = path.resolve(repoExtensionsDir, extName);
|
|
136
|
+
if (!fs.statSync(srcPath).isDirectory())
|
|
137
|
+
continue;
|
|
138
|
+
const finalExtName = extName === 'tasks' ? 'tars-tasks' : extName;
|
|
139
|
+
const finalDestPath = path.join(targetExtensionsDir, finalExtName);
|
|
140
|
+
// Check if symlink exists and is valid
|
|
141
|
+
let needsLink = true;
|
|
142
|
+
try {
|
|
143
|
+
if (fs.existsSync(finalDestPath)) {
|
|
144
|
+
const stats = fs.lstatSync(finalDestPath);
|
|
145
|
+
if (stats.isSymbolicLink()) {
|
|
146
|
+
const realPath = fs.realpathSync(finalDestPath);
|
|
147
|
+
if (realPath === srcPath) {
|
|
148
|
+
needsLink = false; // Already linked correctly
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
catch (e) {
|
|
154
|
+
// Broken link or other error, proceed to re-link
|
|
155
|
+
}
|
|
156
|
+
if (needsLink) {
|
|
157
|
+
try {
|
|
158
|
+
// Remove existing file/link if present to prevent EEXIST
|
|
159
|
+
if (fs.existsSync(finalDestPath) || fs.lstatSync(finalDestPath).isSymbolicLink()) {
|
|
160
|
+
fs.rmSync(finalDestPath, { recursive: true, force: true });
|
|
161
|
+
}
|
|
162
|
+
fs.symlinkSync(srcPath, finalDestPath, 'dir');
|
|
163
|
+
logger.info(`🔌 Linked extension: ${finalExtName} -> ${srcPath}`);
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
logger.error(`❌ Failed to link extension ${finalExtName}: ${error}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// Ensure enabled
|
|
170
|
+
if (!enablement[finalExtName]) {
|
|
171
|
+
enablement[finalExtName] = {
|
|
172
|
+
overrides: [path.join(config.homeDir, '*')]
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
fs.writeFileSync(enablementFile, JSON.stringify(enablement, null, 2));
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Install default settings if none exist.
|
|
180
|
+
*/
|
|
181
|
+
function installDefaultSettings(config) {
|
|
182
|
+
const settingsTemplate = path.join(__dirname, '..', '..', 'context', 'config', 'settings.json-template');
|
|
183
|
+
const targetSettings = path.join(config.homeDir, '.gemini', 'settings.json');
|
|
184
|
+
if (fs.existsSync(targetSettings))
|
|
185
|
+
return;
|
|
186
|
+
if (fs.existsSync(settingsTemplate)) {
|
|
187
|
+
fs.mkdirSync(path.dirname(targetSettings), { recursive: true });
|
|
188
|
+
fs.copyFileSync(settingsTemplate, targetSettings);
|
|
189
|
+
logger.info(`⚙️ Default settings installed: ${targetSettings}`);
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
logger.warn('⚠️ Could not locate settings.json-template');
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Tars Main Entry Point
|
|
197
|
+
*/
|
|
198
|
+
async function main() {
|
|
199
|
+
try {
|
|
200
|
+
logger.info('🚀 Tars Starting...');
|
|
201
|
+
// 1. Load Configuration
|
|
202
|
+
const config = Config.getInstance();
|
|
203
|
+
// 2. Install system prompt, skills, extensions and settings
|
|
204
|
+
installSystemPrompt(config);
|
|
205
|
+
installSkills(config);
|
|
206
|
+
installExtensions(config);
|
|
207
|
+
installDefaultSettings(config);
|
|
208
|
+
// 3. Initialize Core Services
|
|
209
|
+
const gemini = new GeminiCli(config);
|
|
210
|
+
const sessionManager = new SessionManager(config.sessionFilePath);
|
|
211
|
+
const supervisor = new Supervisor(gemini, sessionManager);
|
|
212
|
+
// 4. Initialize Heartbeat (Background Tasks)
|
|
213
|
+
const heartbeat = new HeartbeatService(supervisor, config);
|
|
214
|
+
// 5. Initialize Interface (Discord)
|
|
215
|
+
const discordBot = new DiscordBot(supervisor, config);
|
|
216
|
+
// Start Services
|
|
217
|
+
await discordBot.start();
|
|
218
|
+
await heartbeat.start();
|
|
219
|
+
logger.info('✨ Tars successfully initialized and running.');
|
|
220
|
+
// Graceful shutdown
|
|
221
|
+
process.on('SIGINT', async () => {
|
|
222
|
+
logger.info('🛑 Shutting down...');
|
|
223
|
+
heartbeat.stop();
|
|
224
|
+
process.exit(0);
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
catch (error) {
|
|
228
|
+
logger.error(`💥 Fatal error during startup: ${error.message}`);
|
|
229
|
+
process.exit(1);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
// 6. Run Main
|
|
233
|
+
// Strict Safety Check: The supervisor must be explicitly activated via environment variable.
|
|
234
|
+
// This prevents accidental execution via "node dist/supervisor/main.js" which can spawn zombie processes.
|
|
235
|
+
if (process.env.TARS_SUPERVISOR_MODE !== 'true') {
|
|
236
|
+
logger.error('❌ TARS_SUPERVISOR_MODE=true is required to start the supervisor.');
|
|
237
|
+
logger.error(' This safety check prevents accidental multiple instances.');
|
|
238
|
+
logger.error('👉 Use "tars start" or "npm run dev" instead.');
|
|
239
|
+
process.exit(1);
|
|
240
|
+
}
|
|
241
|
+
main();
|
|
242
|
+
//# sourceMappingURL=main.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/supervisor/main.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { UsageStats } from '../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Session data stored to disk
|
|
4
|
+
*/
|
|
5
|
+
export interface SessionData {
|
|
6
|
+
sessionId: string;
|
|
7
|
+
createdAt: string;
|
|
8
|
+
totalInputTokens: number;
|
|
9
|
+
totalOutputTokens: number;
|
|
10
|
+
totalCachedTokens: number;
|
|
11
|
+
interactionCount: number;
|
|
12
|
+
lastInteractionAt: string;
|
|
13
|
+
lastInputTokens: number;
|
|
14
|
+
totalNetTokens: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Manages Gemini CLI session persistence with token tracking
|
|
18
|
+
*/
|
|
19
|
+
export declare class SessionManager {
|
|
20
|
+
private readonly sessionFilePath;
|
|
21
|
+
private sessionData;
|
|
22
|
+
constructor(sessionFilePath: string);
|
|
23
|
+
/**
|
|
24
|
+
* Load session data from storage
|
|
25
|
+
*/
|
|
26
|
+
load(): string | null;
|
|
27
|
+
/**
|
|
28
|
+
* Save or initialize session
|
|
29
|
+
*/
|
|
30
|
+
save(sessionId: string): void;
|
|
31
|
+
/**
|
|
32
|
+
* Update session with usage stats from latest interaction
|
|
33
|
+
*/
|
|
34
|
+
updateUsage(usage: UsageStats): void;
|
|
35
|
+
/**
|
|
36
|
+
* Get current session statistics
|
|
37
|
+
*/
|
|
38
|
+
getStats(): SessionData | null;
|
|
39
|
+
/**
|
|
40
|
+
* Clear the stored session
|
|
41
|
+
*/
|
|
42
|
+
clear(): void;
|
|
43
|
+
/**
|
|
44
|
+
* Check if a session exists
|
|
45
|
+
*/
|
|
46
|
+
exists(): boolean;
|
|
47
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import logger from '../utils/logger.js';
|
|
4
|
+
/**
|
|
5
|
+
* Manages Gemini CLI session persistence with token tracking
|
|
6
|
+
*/
|
|
7
|
+
export class SessionManager {
|
|
8
|
+
sessionFilePath;
|
|
9
|
+
sessionData = null;
|
|
10
|
+
constructor(sessionFilePath) {
|
|
11
|
+
this.sessionFilePath = sessionFilePath;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Load session data from storage
|
|
15
|
+
*/
|
|
16
|
+
load() {
|
|
17
|
+
if (!fs.existsSync(this.sessionFilePath)) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
const raw = fs.readFileSync(this.sessionFilePath, 'utf-8');
|
|
22
|
+
const parsed = JSON.parse(raw);
|
|
23
|
+
// Check if sessionId exists
|
|
24
|
+
if (!parsed.sessionId) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
this.sessionData = parsed;
|
|
28
|
+
if (this.sessionData.totalNetTokens === undefined) {
|
|
29
|
+
this.sessionData.totalNetTokens = this.sessionData.totalInputTokens || 0;
|
|
30
|
+
}
|
|
31
|
+
return this.sessionData.sessionId;
|
|
32
|
+
}
|
|
33
|
+
catch (e) {
|
|
34
|
+
logger.warn(`[SessionManager] Failed to load session: ${e}`);
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Save or initialize session
|
|
40
|
+
*/
|
|
41
|
+
save(sessionId) {
|
|
42
|
+
try {
|
|
43
|
+
// Initialize new session data if not exists
|
|
44
|
+
if (!this.sessionData || this.sessionData.sessionId !== sessionId) {
|
|
45
|
+
this.sessionData = {
|
|
46
|
+
sessionId,
|
|
47
|
+
createdAt: new Date().toISOString(),
|
|
48
|
+
totalInputTokens: 0,
|
|
49
|
+
totalOutputTokens: 0,
|
|
50
|
+
totalCachedTokens: 0,
|
|
51
|
+
interactionCount: 0,
|
|
52
|
+
lastInteractionAt: new Date().toISOString(),
|
|
53
|
+
lastInputTokens: 0,
|
|
54
|
+
totalNetTokens: 0
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const dir = path.dirname(this.sessionFilePath);
|
|
58
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
59
|
+
fs.writeFileSync(this.sessionFilePath, JSON.stringify(this.sessionData, null, 2));
|
|
60
|
+
logger.info(`[SessionManager] Session saved: ${sessionId}`);
|
|
61
|
+
}
|
|
62
|
+
catch (e) {
|
|
63
|
+
logger.error(`[SessionManager] Failed to save session: ${e}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Update session with usage stats from latest interaction
|
|
68
|
+
*/
|
|
69
|
+
updateUsage(usage) {
|
|
70
|
+
if (!this.sessionData) {
|
|
71
|
+
logger.warn('[SessionManager] Cannot update usage - no active session');
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const netInput = Math.max(0, usage.inputTokens - (usage.cachedTokens || 0));
|
|
75
|
+
this.sessionData.totalNetTokens += netInput;
|
|
76
|
+
this.sessionData.totalInputTokens = usage.inputTokens; // Current context size
|
|
77
|
+
this.sessionData.totalOutputTokens += usage.outputTokens;
|
|
78
|
+
this.sessionData.totalCachedTokens = usage.cachedTokens || 0; // Current cached state
|
|
79
|
+
this.sessionData.interactionCount++;
|
|
80
|
+
this.sessionData.lastInteractionAt = new Date().toISOString();
|
|
81
|
+
this.sessionData.lastInputTokens = usage.inputTokens;
|
|
82
|
+
// Persist to disk
|
|
83
|
+
try {
|
|
84
|
+
fs.writeFileSync(this.sessionFilePath, JSON.stringify(this.sessionData, null, 2));
|
|
85
|
+
}
|
|
86
|
+
catch (e) {
|
|
87
|
+
logger.error(`[SessionManager] Failed to update usage: ${e}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Get current session statistics
|
|
92
|
+
*/
|
|
93
|
+
getStats() {
|
|
94
|
+
return this.sessionData ? { ...this.sessionData } : null;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Clear the stored session
|
|
98
|
+
*/
|
|
99
|
+
clear() {
|
|
100
|
+
if (fs.existsSync(this.sessionFilePath)) {
|
|
101
|
+
try {
|
|
102
|
+
fs.unlinkSync(this.sessionFilePath);
|
|
103
|
+
this.sessionData = null;
|
|
104
|
+
logger.info('[SessionManager] Session cleared');
|
|
105
|
+
}
|
|
106
|
+
catch (e) {
|
|
107
|
+
logger.error(`[SessionManager] Failed to clear session: ${e}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Check if a session exists
|
|
113
|
+
*/
|
|
114
|
+
exists() {
|
|
115
|
+
return fs.existsSync(this.sessionFilePath);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=session-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-manager.js","sourceRoot":"","sources":["../../src/supervisor/session-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { GeminiCli } from './gemini-cli.js';
|
|
2
|
+
import { SessionManager } from './session-manager.js';
|
|
3
|
+
import { GeminiOutputHandler } from '../types/index.js';
|
|
4
|
+
import { MemoryManager } from '../memory/memory-manager.js';
|
|
5
|
+
/**
|
|
6
|
+
* Tars Supervisor - Core Orchestrator
|
|
7
|
+
* Simplified to handle session management and Gemini CLI execution.
|
|
8
|
+
*/
|
|
9
|
+
export declare class Supervisor {
|
|
10
|
+
private readonly gemini;
|
|
11
|
+
private readonly sessionManager;
|
|
12
|
+
private readonly config;
|
|
13
|
+
readonly memory: MemoryManager;
|
|
14
|
+
private isProcessing;
|
|
15
|
+
constructor(gemini: GeminiCli, sessionManager: SessionManager);
|
|
16
|
+
/**
|
|
17
|
+
* Executes a user prompt through the Gemini CLI
|
|
18
|
+
*/
|
|
19
|
+
run(content: string, onEvent: GeminiOutputHandler, sessionId?: string): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Specialized execution for background tasks
|
|
22
|
+
*/
|
|
23
|
+
executeTask(prompt: string): Promise<string>;
|
|
24
|
+
/**
|
|
25
|
+
* Prunes the last turn from the current session.
|
|
26
|
+
*/
|
|
27
|
+
pruneLastTurn(): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Checks if the supervisor is currently processing a request
|
|
30
|
+
*/
|
|
31
|
+
isBusy(): boolean;
|
|
32
|
+
}
|