@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,98 @@
|
|
|
1
|
+
import logger from '../utils/logger.js';
|
|
2
|
+
import { Config } from '../config/config.js';
|
|
3
|
+
import { MemoryManager } from '../memory/memory-manager.js';
|
|
4
|
+
/**
|
|
5
|
+
* Tars Supervisor - Core Orchestrator
|
|
6
|
+
* Simplified to handle session management and Gemini CLI execution.
|
|
7
|
+
*/
|
|
8
|
+
export class Supervisor {
|
|
9
|
+
gemini;
|
|
10
|
+
sessionManager;
|
|
11
|
+
config;
|
|
12
|
+
memory;
|
|
13
|
+
isProcessing = false;
|
|
14
|
+
constructor(gemini, sessionManager) {
|
|
15
|
+
this.gemini = gemini;
|
|
16
|
+
this.sessionManager = sessionManager;
|
|
17
|
+
this.config = Config.getInstance();
|
|
18
|
+
this.memory = new MemoryManager(this.config);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Executes a user prompt through the Gemini CLI
|
|
22
|
+
*/
|
|
23
|
+
async run(content, onEvent, sessionId) {
|
|
24
|
+
logger.info(`🤖 Supervisor processing request: ${content.substring(0, 50)}${content.length > 50 ? '...' : ''}`);
|
|
25
|
+
try {
|
|
26
|
+
// Get or create session
|
|
27
|
+
let sessionIdToUse = sessionId || this.sessionManager.load();
|
|
28
|
+
// Lock the supervisor
|
|
29
|
+
this.isProcessing = true;
|
|
30
|
+
// Run Gemini CLI
|
|
31
|
+
await this.gemini.run(content, (event) => {
|
|
32
|
+
// Learn session ID from Gemini CLI if it was newly generated
|
|
33
|
+
if (event.sessionId) {
|
|
34
|
+
sessionIdToUse = event.sessionId;
|
|
35
|
+
if (sessionIdToUse) {
|
|
36
|
+
this.sessionManager.save(sessionIdToUse);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// Extract data for session tracking
|
|
40
|
+
if (event.type === 'done') {
|
|
41
|
+
if (event.usageStats) {
|
|
42
|
+
this.sessionManager.updateUsage(event.usageStats);
|
|
43
|
+
}
|
|
44
|
+
if (sessionIdToUse) {
|
|
45
|
+
this.sessionManager.save(sessionIdToUse);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
onEvent(event);
|
|
49
|
+
}, sessionIdToUse || undefined);
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
logger.error(`❌ Supervisor execution error: ${error.message}`);
|
|
53
|
+
onEvent({ type: 'error', error: error.message });
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
this.isProcessing = false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Specialized execution for background tasks
|
|
61
|
+
*/
|
|
62
|
+
async executeTask(prompt) {
|
|
63
|
+
if (this.isProcessing) {
|
|
64
|
+
logger.warn('⚠️ Supervisor is busy, skipping background task');
|
|
65
|
+
throw new Error('Supervisor is busy');
|
|
66
|
+
}
|
|
67
|
+
logger.info(`⚙️ Executing background task...`);
|
|
68
|
+
try {
|
|
69
|
+
this.isProcessing = true;
|
|
70
|
+
const sessionId = this.sessionManager.load();
|
|
71
|
+
const result = await this.gemini.runSync(prompt, sessionId || undefined);
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
logger.error(`❌ Background task failed: ${error.message}`);
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
finally {
|
|
79
|
+
this.isProcessing = false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Prunes the last turn from the current session.
|
|
84
|
+
*/
|
|
85
|
+
async pruneLastTurn() {
|
|
86
|
+
const sessionId = this.sessionManager.load();
|
|
87
|
+
if (sessionId) {
|
|
88
|
+
await this.gemini.pruneLastTurn(sessionId);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Checks if the supervisor is currently processing a request
|
|
93
|
+
*/
|
|
94
|
+
isBusy() {
|
|
95
|
+
return this.isProcessing;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=supervisor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supervisor.js","sourceRoot":"","sources":["../../src/supervisor/supervisor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core types for the Tars system
|
|
3
|
+
*/
|
|
4
|
+
export interface Task {
|
|
5
|
+
id: string;
|
|
6
|
+
title: string;
|
|
7
|
+
prompt: string;
|
|
8
|
+
schedule: string;
|
|
9
|
+
nextRun: string;
|
|
10
|
+
lastRun?: string;
|
|
11
|
+
enabled: boolean;
|
|
12
|
+
mode: 'notify' | 'silent';
|
|
13
|
+
source: 'user' | 'system';
|
|
14
|
+
failedCount: number;
|
|
15
|
+
createdAt: string;
|
|
16
|
+
updatedAt: string;
|
|
17
|
+
}
|
|
18
|
+
export interface SessionMetadata {
|
|
19
|
+
id: string;
|
|
20
|
+
startTime: string;
|
|
21
|
+
lastActive: string;
|
|
22
|
+
tokenCount: number;
|
|
23
|
+
interactionCount: number;
|
|
24
|
+
}
|
|
25
|
+
export interface GeminiEvent {
|
|
26
|
+
type: 'tool_call' | 'tool_response' | 'text' | 'image' | 'error' | 'done' | 'thought' | 'status';
|
|
27
|
+
content?: string;
|
|
28
|
+
toolName?: string;
|
|
29
|
+
toolArgs?: any;
|
|
30
|
+
toolId?: string;
|
|
31
|
+
imagePath?: string;
|
|
32
|
+
error?: string;
|
|
33
|
+
usageStats?: UsageStats;
|
|
34
|
+
sessionId?: string;
|
|
35
|
+
status?: string;
|
|
36
|
+
}
|
|
37
|
+
export interface UsageStats {
|
|
38
|
+
inputTokens: number;
|
|
39
|
+
outputTokens: number;
|
|
40
|
+
cachedTokens?: number;
|
|
41
|
+
}
|
|
42
|
+
export type GeminiOutputHandler = (event: GeminiEvent) => void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Attachment } from 'discord.js';
|
|
2
|
+
import { Config } from '../config/config.js';
|
|
3
|
+
/**
|
|
4
|
+
* Handles downloading incoming Discord attachments and saving outgoing responses as files.
|
|
5
|
+
*/
|
|
6
|
+
export declare class AttachmentProcessor {
|
|
7
|
+
private uploadDir;
|
|
8
|
+
private tmpDir;
|
|
9
|
+
constructor(config: Config);
|
|
10
|
+
/**
|
|
11
|
+
* Download an attachment from Discord to local storage.
|
|
12
|
+
*/
|
|
13
|
+
download(attachment: Attachment): Promise<string>;
|
|
14
|
+
/**
|
|
15
|
+
* Save a long response text to a temporary file for uploading.
|
|
16
|
+
*/
|
|
17
|
+
saveResponse(content: string, extension?: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* Clean up temporary files (1 hour) and uploads (24 hours).
|
|
20
|
+
*/
|
|
21
|
+
cleanup(): void;
|
|
22
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import logger from './logger.js';
|
|
4
|
+
/**
|
|
5
|
+
* Handles downloading incoming Discord attachments and saving outgoing responses as files.
|
|
6
|
+
*/
|
|
7
|
+
export class AttachmentProcessor {
|
|
8
|
+
uploadDir;
|
|
9
|
+
tmpDir;
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.uploadDir = path.join(config.homeDir, 'data', 'uploads');
|
|
12
|
+
this.tmpDir = path.join(config.homeDir, 'data', 'tmp');
|
|
13
|
+
// Ensure directories exist
|
|
14
|
+
if (!fs.existsSync(this.uploadDir)) {
|
|
15
|
+
fs.mkdirSync(this.uploadDir, { recursive: true });
|
|
16
|
+
}
|
|
17
|
+
if (!fs.existsSync(this.tmpDir)) {
|
|
18
|
+
fs.mkdirSync(this.tmpDir, { recursive: true });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Download an attachment from Discord to local storage.
|
|
23
|
+
*/
|
|
24
|
+
async download(attachment) {
|
|
25
|
+
try {
|
|
26
|
+
const fileName = `${attachment.id}-${attachment.name}`;
|
|
27
|
+
const dest = path.join(this.uploadDir, fileName);
|
|
28
|
+
logger.info(`⬇️ Downloading attachment: ${attachment.name} (${attachment.contentType})`);
|
|
29
|
+
const response = await fetch(attachment.url);
|
|
30
|
+
if (!response.ok)
|
|
31
|
+
throw new Error(`Fetch failed: ${response.statusText}`);
|
|
32
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
33
|
+
fs.writeFileSync(dest, Buffer.from(arrayBuffer));
|
|
34
|
+
logger.info(`✅ Saved attachment to: ${dest}`);
|
|
35
|
+
return dest;
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
logger.error(`❌ Failed to download attachment: ${error.message}`);
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Save a long response text to a temporary file for uploading.
|
|
44
|
+
*/
|
|
45
|
+
saveResponse(content, extension = 'md') {
|
|
46
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
47
|
+
const fileName = `response-${timestamp}.${extension}`;
|
|
48
|
+
const dest = path.join(this.tmpDir, fileName);
|
|
49
|
+
fs.writeFileSync(dest, content);
|
|
50
|
+
return dest;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Clean up temporary files (1 hour) and uploads (24 hours).
|
|
54
|
+
*/
|
|
55
|
+
cleanup() {
|
|
56
|
+
const cleanDir = (dir, maxAgeMs) => {
|
|
57
|
+
try {
|
|
58
|
+
if (!fs.existsSync(dir))
|
|
59
|
+
return;
|
|
60
|
+
const now = Date.now();
|
|
61
|
+
const files = fs.readdirSync(dir);
|
|
62
|
+
for (const file of files) {
|
|
63
|
+
const filePath = path.join(dir, file);
|
|
64
|
+
const stats = fs.statSync(filePath);
|
|
65
|
+
if (now - stats.mtimeMs > maxAgeMs) {
|
|
66
|
+
fs.unlinkSync(filePath);
|
|
67
|
+
logger.debug(`🧹 Deleted old file: ${filePath}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch (e) {
|
|
72
|
+
logger.error(`Cleanup failed for ${dir}: ${e.message}`);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
cleanDir(this.tmpDir, 3600000); // 1 hour for tmp responses
|
|
76
|
+
cleanDir(this.uploadDir, 86400000); // 24 hours for uploads
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=attachment-processor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attachment-processor.js","sourceRoot":"","sources":["../../src/utils/attachment-processor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import winston from 'winston';
|
|
2
|
+
/**
|
|
3
|
+
* Centralized logger for the supervisor application
|
|
4
|
+
*/
|
|
5
|
+
export const logger = winston.createLogger({
|
|
6
|
+
level: process.env.LOG_LEVEL || 'info',
|
|
7
|
+
format: winston.format.combine(winston.format.timestamp({
|
|
8
|
+
format: 'YYYY-MM-DD HH:mm:ss'
|
|
9
|
+
}), winston.format.colorize(), winston.format.printf(({ timestamp, level, message }) => {
|
|
10
|
+
return `${timestamp} [${level}]: ${message}`;
|
|
11
|
+
})),
|
|
12
|
+
transports: [new winston.transports.Console()]
|
|
13
|
+
});
|
|
14
|
+
export default logger;
|
|
15
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B;;GAEG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IACvC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,MAAM;IACtC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,CAC1B,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC;QACrB,MAAM,EAAE,qBAAqB;KAChC,CAAC,EACF,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,EACzB,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE;QACpD,OAAO,GAAG,SAAS,KAAK,KAAK,MAAM,OAAO,EAAE,CAAC;IACjD,CAAC,CAAC,CACL;IACD,UAAU,EAAE,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;CACjD,CAAC,CAAC;AAEH,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manages secrets stored in ~/.tars/.env
|
|
3
|
+
*/
|
|
4
|
+
export declare class SecretsManager {
|
|
5
|
+
private readonly secretsPath;
|
|
6
|
+
constructor(homeDir: string);
|
|
7
|
+
/**
|
|
8
|
+
* Load all secrets as an object
|
|
9
|
+
*/
|
|
10
|
+
load(): Record<string, string>;
|
|
11
|
+
/**
|
|
12
|
+
* Set a secret value
|
|
13
|
+
*/
|
|
14
|
+
set(key: string, value: string): void;
|
|
15
|
+
/**
|
|
16
|
+
* Delete a secret
|
|
17
|
+
*/
|
|
18
|
+
remove(key: string): void;
|
|
19
|
+
/**
|
|
20
|
+
* List all secret keys
|
|
21
|
+
*/
|
|
22
|
+
list(): string[];
|
|
23
|
+
/**
|
|
24
|
+
* Internal save helper
|
|
25
|
+
*/
|
|
26
|
+
private saveFilesystem;
|
|
27
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import dotenv from 'dotenv';
|
|
4
|
+
import logger from './logger.js';
|
|
5
|
+
/**
|
|
6
|
+
* Manages secrets stored in ~/.tars/.env
|
|
7
|
+
*/
|
|
8
|
+
export class SecretsManager {
|
|
9
|
+
secretsPath;
|
|
10
|
+
constructor(homeDir) {
|
|
11
|
+
this.secretsPath = path.join(homeDir, '.env');
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Load all secrets as an object
|
|
15
|
+
*/
|
|
16
|
+
load() {
|
|
17
|
+
if (!fs.existsSync(this.secretsPath)) {
|
|
18
|
+
return {};
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
const content = fs.readFileSync(this.secretsPath, 'utf-8');
|
|
22
|
+
return dotenv.parse(content);
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
logger.error(`[SecretsManager] Failed to load secrets: ${error.message}`);
|
|
26
|
+
return {};
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Set a secret value
|
|
31
|
+
*/
|
|
32
|
+
set(key, value) {
|
|
33
|
+
try {
|
|
34
|
+
const secrets = this.load();
|
|
35
|
+
secrets[key] = value;
|
|
36
|
+
this.saveFilesystem(secrets);
|
|
37
|
+
logger.info(`[SecretsManager] Secret set: ${key}`);
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
logger.error(`[SecretsManager] Failed to set secret ${key}: ${error.message}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Delete a secret
|
|
45
|
+
*/
|
|
46
|
+
remove(key) {
|
|
47
|
+
try {
|
|
48
|
+
const secrets = this.load();
|
|
49
|
+
if (key in secrets) {
|
|
50
|
+
delete secrets[key];
|
|
51
|
+
this.saveFilesystem(secrets);
|
|
52
|
+
logger.info(`[SecretsManager] Secret removed: ${key}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
logger.error(`[SecretsManager] Failed to remove secret ${key}: ${error.message}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* List all secret keys
|
|
61
|
+
*/
|
|
62
|
+
list() {
|
|
63
|
+
return Object.keys(this.load());
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Internal save helper
|
|
67
|
+
*/
|
|
68
|
+
saveFilesystem(secrets) {
|
|
69
|
+
const content = Object.entries(secrets)
|
|
70
|
+
.map(([k, v]) => `${k}="${v.replace(/"/g, '\\"')}"`)
|
|
71
|
+
.join('\n');
|
|
72
|
+
const dir = path.dirname(this.secretsPath);
|
|
73
|
+
if (!fs.existsSync(dir)) {
|
|
74
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
75
|
+
}
|
|
76
|
+
fs.writeFileSync(this.secretsPath, content, { mode: 0o600 });
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=secrets-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secrets-manager.js","sourceRoot":"","sources":["../../src/utils/secrets-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { readFileSync } from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
5
|
+
const __dirname = path.dirname(__filename);
|
|
6
|
+
// Find package.json by walking up (handles both src/ and dist/ structures)
|
|
7
|
+
function getPkg() {
|
|
8
|
+
let currentDir = __dirname;
|
|
9
|
+
while (currentDir !== path.parse(currentDir).root) {
|
|
10
|
+
const pkgPath = path.join(currentDir, 'package.json');
|
|
11
|
+
try {
|
|
12
|
+
return JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
currentDir = path.dirname(currentDir);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return { version: '0.0.0' };
|
|
19
|
+
}
|
|
20
|
+
export const pkg = getPkg();
|
|
21
|
+
export const isDev = !__filename.includes('node_modules');
|
|
22
|
+
export const versionString = `${pkg.version}${isDev ? ' (dev)' : ''}`;
|
|
23
|
+
//# sourceMappingURL=version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/utils/version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAE3C,2EAA2E;AAC3E,SAAS,MAAM;IACX,IAAI,UAAU,GAAG,SAAS,CAAC;IAC3B,OAAO,UAAU,KAAK,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC;QAChD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;QACtD,IAAI,CAAC;YACD,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QACtD,CAAC;QAAC,MAAM,CAAC;YACL,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAC1C,CAAC;IACL,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAChC,CAAC;AAED,MAAM,CAAC,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;AAC5B,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;AAC1D,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,GAAG,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC"}
|