@saccolabs/tars 1.0.35 → 1.0.36

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 (38) hide show
  1. package/dist/auth/credential-manager.d.ts +14 -0
  2. package/dist/auth/credential-manager.js +60 -0
  3. package/dist/auth/credential-manager.js.map +1 -0
  4. package/dist/auth/oauth-service.d.ts +23 -0
  5. package/dist/auth/oauth-service.js +84 -0
  6. package/dist/auth/oauth-service.js.map +1 -0
  7. package/dist/cli/commands/setup.js +32 -96
  8. package/dist/cli/commands/setup.js.map +1 -1
  9. package/dist/cli/commands/start.js +3 -2
  10. package/dist/cli/commands/start.js.map +1 -1
  11. package/dist/discord/discord-bot.js +3 -0
  12. package/dist/discord/discord-bot.js.map +1 -1
  13. package/dist/memory/memory-manager.js +10 -5
  14. package/dist/memory/memory-manager.js.map +1 -1
  15. package/dist/scripts/debug-cli.js +7 -34
  16. package/dist/scripts/debug-cli.js.map +1 -1
  17. package/dist/supervisor/cron-service.d.ts +21 -0
  18. package/dist/supervisor/cron-service.js +105 -0
  19. package/dist/supervisor/cron-service.js.map +1 -0
  20. package/dist/supervisor/gemini-engine.d.ts +51 -0
  21. package/dist/supervisor/gemini-engine.js +314 -0
  22. package/dist/supervisor/gemini-engine.js.map +1 -0
  23. package/dist/supervisor/heartbeat-service.d.ts +1 -11
  24. package/dist/supervisor/heartbeat-service.js +8 -84
  25. package/dist/supervisor/heartbeat-service.js.map +1 -1
  26. package/dist/supervisor/main.js +8 -34
  27. package/dist/supervisor/main.js.map +1 -1
  28. package/dist/supervisor/session-manager.js +16 -15
  29. package/dist/supervisor/session-manager.js.map +1 -1
  30. package/dist/supervisor/supervisor.d.ts +3 -4
  31. package/dist/supervisor/supervisor.js +18 -22
  32. package/dist/supervisor/supervisor.js.map +1 -1
  33. package/extensions/memory/tsconfig.json +2 -1
  34. package/extensions/tasks/tsconfig.json +2 -1
  35. package/package.json +7 -3
  36. package/dist/supervisor/gemini-cli.d.ts +0 -17
  37. package/dist/supervisor/gemini-cli.js +0 -193
  38. package/dist/supervisor/gemini-cli.js.map +0 -1
@@ -1,193 +0,0 @@
1
- import { spawn } from 'node:child_process';
2
- import EventEmitter from 'node:events';
3
- import logger from '../utils/logger.js';
4
- import fs from 'fs';
5
- /**
6
- * Wrapper for the Gemini CLI process
7
- */
8
- export class GeminiCli extends EventEmitter {
9
- config;
10
- constructor(config) {
11
- super();
12
- this.config = config;
13
- }
14
- /**
15
- * Executes a prompt via Gemini CLI with streaming events.
16
- */
17
- run(prompt, onEvent, sessionId, extensions = []) {
18
- return new Promise((resolve, reject) => {
19
- const args = ['--output-format', 'stream-json', '--yolo', '--prompt', prompt];
20
- if (sessionId) {
21
- args.push('--resume', sessionId);
22
- }
23
- if (this.config.geminiModel && this.config.geminiModel !== 'auto') {
24
- args.push('--model', this.config.geminiModel);
25
- }
26
- // Add extensions (MCP servers) if any
27
- for (const ext of extensions) {
28
- args.push('--extensions', ext);
29
- }
30
- const childDescription = `Gemini CLI (Session: ${sessionId || 'new'})`;
31
- // Re-homing environment for subprocess
32
- // Pin CWD to homeDir (~/.tars) so the Gemini CLI doesn't discover
33
- // stray GEMINI.md files in whatever directory the user ran `tars start` from.
34
- const env = {
35
- ...process.env,
36
- HOME: this.config.homeDir,
37
- TARS_HOME: this.config.homeDir,
38
- GEMINI_CLI_HOME: this.config.homeDir,
39
- GEMINI_SYSTEM_MD: this.config.systemPromptPath,
40
- PWD: this.config.homeDir
41
- };
42
- logger.info(`🚀 [GeminiCli] Spawning: gemini ${args.join(' ')}`);
43
- const child = spawn('gemini', args, {
44
- env,
45
- cwd: this.config.homeDir,
46
- stdio: ['ignore', 'pipe', 'pipe']
47
- });
48
- const debugFile = `/tmp/gemini-debug-${Date.now()}.log`;
49
- const debugStream = fs.createWriteStream(debugFile);
50
- let stdoutBuffer = '';
51
- let usageStats = { inputTokens: 0, outputTokens: 0, cachedTokens: 0 };
52
- let hasResolved = false;
53
- // --- Timeout Logic ---
54
- // 1. Total Safety Timeout (10m) - Absolute max for any task
55
- // 2. Idleness Timeout (5m) - Reset every time we get data
56
- let idleTimeout;
57
- const TOTAL_TIMEOUT = 600000;
58
- const IDLE_TIMEOUT = 300000;
59
- const resetIdleTimeout = () => {
60
- clearTimeout(idleTimeout);
61
- idleTimeout = setTimeout(() => {
62
- if (hasResolved)
63
- return;
64
- logger.warn(`🕒 ${childDescription} idle for ${IDLE_TIMEOUT / 1000}s. Killing...`);
65
- cleanup(null, new Error('Idle timeout'));
66
- child.kill('SIGKILL');
67
- }, IDLE_TIMEOUT);
68
- };
69
- const totalTimeout = setTimeout(() => {
70
- if (hasResolved)
71
- return;
72
- logger.warn(`🕒 ${childDescription} reached absolute limit (${TOTAL_TIMEOUT / 1000}s). Killing...`);
73
- cleanup(null, new Error('Absolute timeout'));
74
- child.kill('SIGKILL');
75
- }, TOTAL_TIMEOUT);
76
- resetIdleTimeout();
77
- // ---------------------
78
- const cleanup = (code, error) => {
79
- if (hasResolved)
80
- return;
81
- hasResolved = true;
82
- clearTimeout(totalTimeout);
83
- clearTimeout(idleTimeout);
84
- debugStream.end();
85
- if (error) {
86
- reject(error);
87
- return;
88
- }
89
- logger.info(`âšī¸ ${childDescription} closed with code ${code}`);
90
- if (code === 0 || code === null) {
91
- onEvent({ type: 'done', usageStats });
92
- resolve();
93
- }
94
- else {
95
- reject(new Error(`${childDescription} exited with code ${code}`));
96
- }
97
- };
98
- child.stdout.on('data', (data) => {
99
- resetIdleTimeout(); // Reset timer on any output
100
- const chunk = data.toString();
101
- debugStream.write(chunk);
102
- stdoutBuffer += chunk;
103
- const lines = stdoutBuffer.split('\n');
104
- stdoutBuffer = lines.pop() || '';
105
- for (const line of lines) {
106
- if (!line.trim())
107
- continue;
108
- try {
109
- const event = JSON.parse(line);
110
- // --- Normalize Event ---
111
- // 1. Tool Calls
112
- if (event.type === 'tool_use') {
113
- event.type = 'tool_call';
114
- event.toolName = event.tool_name;
115
- event.toolArgs = event.parameters;
116
- }
117
- // 2. Tool Responses
118
- if (event.type === 'tool_result') {
119
- event.type = 'tool_response';
120
- event.toolId = event.tool_id;
121
- event.content = event.output;
122
- }
123
- // 3. Thoughts
124
- if (event.thoughts && !event.content) {
125
- onEvent({
126
- type: 'thought',
127
- content: Array.isArray(event.thoughts)
128
- ? event.thoughts.join('\n')
129
- : event.thoughts
130
- });
131
- }
132
- if (event.type === 'message' && event.thoughts) {
133
- // If message has thoughts, emit them separately or as a combined event
134
- onEvent({
135
- type: 'thought',
136
- content: Array.isArray(event.thoughts)
137
- ? event.thoughts.join('\n')
138
- : event.thoughts
139
- });
140
- }
141
- // 4. Session & Stats
142
- if (event.stats) {
143
- usageStats = {
144
- inputTokens: event.stats.input_tokens || event.stats.input || 0,
145
- outputTokens: event.stats.output_tokens || event.stats.output || 0,
146
- cachedTokens: event.stats.cached || 0
147
- };
148
- }
149
- if (event.session_id && !event.sessionId) {
150
- event.sessionId = event.session_id;
151
- }
152
- onEvent(event);
153
- // If we see a 'done' event, the CLI is effectively finished
154
- if (event.type === 'done' ||
155
- (event.type === 'result' && event.status === 'success')) {
156
- cleanup(0);
157
- child.kill('SIGTERM');
158
- }
159
- }
160
- catch (e) {
161
- continue;
162
- }
163
- }
164
- });
165
- child.stderr.on('data', (data) => {
166
- const error = data.toString();
167
- logger.warn(`[Gemini CLI Stderr] ${error.trim()}`);
168
- });
169
- child.on('close', (code) => {
170
- cleanup(code);
171
- });
172
- child.on('error', (err) => {
173
- logger.error(`Failed to start ${childDescription}: ${err.message}`);
174
- reject(err);
175
- });
176
- });
177
- }
178
- /**
179
- * Synchronous execution (collects all output)
180
- */
181
- async runSync(prompt, sessionId, extensions = []) {
182
- let fullContent = '';
183
- await this.run(prompt, (event) => {
184
- if ((event.type === 'message' || event.type === 'text') &&
185
- event.role === 'assistant' &&
186
- event.content) {
187
- fullContent += event.content;
188
- }
189
- }, sessionId, extensions);
190
- return fullContent;
191
- }
192
- }
193
- //# sourceMappingURL=gemini-cli.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"gemini-cli.js","sourceRoot":"","sources":["../../src/supervisor/gemini-cli.ts"],"names":[],"mappings":"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"}