@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.
Files changed (99) hide show
  1. package/README.md +93 -0
  2. package/context/GEMINI.md +13 -0
  3. package/context/config/settings.json-template +36 -0
  4. package/context/skills/create-extension/SKILL.md +90 -0
  5. package/context/skills/create-skill/SKILL.md +33 -0
  6. package/context/skills/manage-extensions/SKILL.md +69 -0
  7. package/context/skills/tars-ops/SKILL.md +89 -0
  8. package/dist/cli/commands/discord.d.ts +4 -0
  9. package/dist/cli/commands/discord.js +48 -0
  10. package/dist/cli/commands/discord.js.map +1 -0
  11. package/dist/cli/commands/export.d.ts +3 -0
  12. package/dist/cli/commands/export.js +39 -0
  13. package/dist/cli/commands/export.js.map +1 -0
  14. package/dist/cli/commands/import.d.ts +1 -0
  15. package/dist/cli/commands/import.js +45 -0
  16. package/dist/cli/commands/import.js.map +1 -0
  17. package/dist/cli/commands/logs.d.ts +4 -0
  18. package/dist/cli/commands/logs.js +23 -0
  19. package/dist/cli/commands/logs.js.map +1 -0
  20. package/dist/cli/commands/memory.d.ts +1 -0
  21. package/dist/cli/commands/memory.js +35 -0
  22. package/dist/cli/commands/memory.js.map +1 -0
  23. package/dist/cli/commands/secret.d.ts +6 -0
  24. package/dist/cli/commands/secret.js +46 -0
  25. package/dist/cli/commands/secret.js.map +1 -0
  26. package/dist/cli/commands/setup.d.ts +4 -0
  27. package/dist/cli/commands/setup.js +329 -0
  28. package/dist/cli/commands/setup.js.map +1 -0
  29. package/dist/cli/commands/start.d.ts +1 -0
  30. package/dist/cli/commands/start.js +42 -0
  31. package/dist/cli/commands/start.js.map +1 -0
  32. package/dist/cli/commands/status.d.ts +1 -0
  33. package/dist/cli/commands/status.js +56 -0
  34. package/dist/cli/commands/status.js.map +1 -0
  35. package/dist/cli/commands/stop.d.ts +1 -0
  36. package/dist/cli/commands/stop.js +38 -0
  37. package/dist/cli/commands/stop.js.map +1 -0
  38. package/dist/cli/commands/uninstall.d.ts +1 -0
  39. package/dist/cli/commands/uninstall.js +91 -0
  40. package/dist/cli/commands/uninstall.js.map +1 -0
  41. package/dist/cli/index.d.ts +2 -0
  42. package/dist/cli/index.js +54 -0
  43. package/dist/cli/index.js.map +1 -0
  44. package/dist/config/config.d.ts +14 -0
  45. package/dist/config/config.js +69 -0
  46. package/dist/config/config.js.map +1 -0
  47. package/dist/discord/discord-bot.d.ts +32 -0
  48. package/dist/discord/discord-bot.js +151 -0
  49. package/dist/discord/discord-bot.js.map +1 -0
  50. package/dist/discord/message-formatter.d.ts +95 -0
  51. package/dist/discord/message-formatter.js +448 -0
  52. package/dist/discord/message-formatter.js.map +1 -0
  53. package/dist/memory/knowledge-store.d.ts +24 -0
  54. package/dist/memory/knowledge-store.js +126 -0
  55. package/dist/memory/knowledge-store.js.map +1 -0
  56. package/dist/memory/memory-manager.d.ts +24 -0
  57. package/dist/memory/memory-manager.js +101 -0
  58. package/dist/memory/memory-manager.js.map +1 -0
  59. package/dist/scripts/debug-cli.d.ts +1 -0
  60. package/dist/scripts/debug-cli.js +52 -0
  61. package/dist/scripts/debug-cli.js.map +1 -0
  62. package/dist/supervisor/gemini-cli.d.ts +28 -0
  63. package/dist/supervisor/gemini-cli.js +315 -0
  64. package/dist/supervisor/gemini-cli.js.map +1 -0
  65. package/dist/supervisor/heartbeat-service.d.ts +21 -0
  66. package/dist/supervisor/heartbeat-service.js +143 -0
  67. package/dist/supervisor/heartbeat-service.js.map +1 -0
  68. package/dist/supervisor/main.d.ts +1 -0
  69. package/dist/supervisor/main.js +242 -0
  70. package/dist/supervisor/main.js.map +1 -0
  71. package/dist/supervisor/session-manager.d.ts +47 -0
  72. package/dist/supervisor/session-manager.js +118 -0
  73. package/dist/supervisor/session-manager.js.map +1 -0
  74. package/dist/supervisor/supervisor.d.ts +32 -0
  75. package/dist/supervisor/supervisor.js +98 -0
  76. package/dist/supervisor/supervisor.js.map +1 -0
  77. package/dist/types/index.d.ts +42 -0
  78. package/dist/types/index.js +5 -0
  79. package/dist/types/index.js.map +1 -0
  80. package/dist/utils/attachment-processor.d.ts +22 -0
  81. package/dist/utils/attachment-processor.js +79 -0
  82. package/dist/utils/attachment-processor.js.map +1 -0
  83. package/dist/utils/logger.d.ts +6 -0
  84. package/dist/utils/logger.js +15 -0
  85. package/dist/utils/logger.js.map +1 -0
  86. package/dist/utils/secrets-manager.d.ts +27 -0
  87. package/dist/utils/secrets-manager.js +79 -0
  88. package/dist/utils/secrets-manager.js.map +1 -0
  89. package/dist/utils/version.d.ts +3 -0
  90. package/dist/utils/version.js +23 -0
  91. package/dist/utils/version.js.map +1 -0
  92. package/extensions/tasks/gemini-extension.json +14 -0
  93. package/extensions/tasks/package-lock.json +1209 -0
  94. package/extensions/tasks/package.json +19 -0
  95. package/extensions/tasks/src/server.ts +265 -0
  96. package/extensions/tasks/src/store.ts +92 -0
  97. package/extensions/tasks/tsconfig.json +14 -0
  98. package/package.json +55 -0
  99. package/src/prompts/system.md +25 -0
package/README.md ADDED
@@ -0,0 +1,93 @@
1
+ # Tars: Personal AI Robot
2
+
3
+ <div align="center">
4
+ <img src="assets/logo.png" alt="Tars Logo" width="300" />
5
+ </div>
6
+
7
+ <div align="center">
8
+
9
+ "Its cue for sarcasm is 100%."
10
+
11
+ [License: MIT](https://opensource.org/licenses/MIT) | [TypeScript](https://www.typescriptlang.org/) | [Powered by Gemini](https://deepmind.google/technologies/gemini/)
12
+
13
+ </div>
14
+
15
+ ---
16
+
17
+ Tars is an autonomous, bare-metal AI assistant inspired by the functional minimalism of Interstellar. The design is strictly functional, and the capability is modular. Tars operates in the terminal, retains user preferences, and manages workspaces through a supervisor-subagent architecture.
18
+
19
+ ## The Vision
20
+
21
+ Unlike cloud-only assistants, Tars integrated into the operating system. It possesses a persistent Brain-a collection of memories, tasks, and learned skills stored locally and transparently.
22
+
23
+ - **Private**: Data remains on the local machine.
24
+ - **Portable**: Export the entire brain and configuration for immediate restoration on new hardware.
25
+ - **Extensible**: Tars constructs its own MCP extensions and skills to adapt to workflows.
26
+
27
+ ---
28
+
29
+ ## Key Features
30
+
31
+ - **Multi-Agent Orchestration**: Delegation of specialized research or complex engineering tasks to background Subagents (Experts).
32
+ - **Workspace Management**: Centralized, portable workspace at `~/.tars/workspace/` for AI-built applications, documented via `TARS.md`.
33
+ - **Bare-Metal Runtime**: Native execution on Node.js without the overhead of containerization. Full access to local toolchains (Git, npm, gh).
34
+ - **Autonomous Persistence**: Background Heartbeat service for scheduled task execution and system maintenance.
35
+ - **Context-Aware Memory**: Dynamic memory evolution via `GEMINI.md` for long-term project context.
36
+
37
+ ---
38
+
39
+ ## Installation and Setup
40
+
41
+ ### Prerequisites
42
+
43
+ - Node.js: ≥ 22.0.0
44
+ - Gemini CLI: `npm i -g @google/gemini-cli-beta`
45
+
46
+ ### Installation
47
+
48
+ ```bash
49
+ npm install -g @saccolabs/tars
50
+ ```
51
+
52
+ ### Initial Setup
53
+
54
+ Run the setup wizard to authorize Gemini and connect your Discord bot:
55
+
56
+ ```bash
57
+ tars setup
58
+ ```
59
+
60
+ ---
61
+
62
+ ## Usage
63
+
64
+ ### Commands
65
+
66
+ - `tars start`: Launch the Tars supervisor.
67
+ - `tars status`: View system health and brain statistics.
68
+ - `tars export`: Compress the brain and configuration for portability.
69
+ - `tars import <path>`: Restore a brain with automatic path re-homing.
70
+ - `tars secret set <key> <value>`: Securely store platform credentials.
71
+
72
+ ### Interaction
73
+
74
+ Communication occurs via a private Discord channel. Tars supports file processing, background task management, and expert delegation.
75
+
76
+ > **!tars** Initialize a Next.js project in the workspace and delegate the repository setup to a GitHub subagent.
77
+
78
+ ---
79
+
80
+ ## Architecture
81
+
82
+ Tars utilizes a Supervisor-Orchestrator model:
83
+
84
+ 1. **Supervisor**: Manages persistent sessions and Discord communication.
85
+ 2. **Subagents**: Specialized expert agents invoked dynamically for specific technical domains.
86
+ 3. **Heartbeat**: Cron-based engine for autonomous execution and cleanup.
87
+ 4. **Extensions**: MCP servers that provide tool-level capabilities to the intelligence core.
88
+
89
+ ---
90
+
91
+ ## License
92
+
93
+ MIT Copyright Agustin Sacco
@@ -0,0 +1,13 @@
1
+ # Tars - Memory & Context
2
+
3
+ This file is my dynamic memory. I can update it at any time using `save_memory` to store preferences, context, and learned information. My core identity and operational rules live in my system prompt and cannot be changed here.
4
+
5
+ ## User Preferences
6
+
7
+ - **Name**: User
8
+ - **Role**: Developer / Architect
9
+ - **Style**: Direct, code-focused, no fluff.
10
+
11
+ ## Notes & Context
12
+
13
+ _(Empty)_
@@ -0,0 +1,36 @@
1
+ {
2
+ "model": {
3
+ "compressionThreshold": 0.2,
4
+ "summarizeToolOutput": {
5
+ "run_shell_command": {
6
+ "tokenBudget": 2000
7
+ }
8
+ }
9
+ },
10
+ "security": {
11
+ "auth": {
12
+ "selectedType": "oauth-personal"
13
+ }
14
+ },
15
+ "experimental": {
16
+ "enableAgents": true,
17
+ "codebaseInvestigatorSettings": {
18
+ "enabled": true,
19
+ "maxNumTurns": 20,
20
+ "model": "gemini-3-flash-preview"
21
+ }
22
+ },
23
+ "agents": {
24
+ "overrides": {
25
+ "codebase_investigator": {
26
+ "enabled": true,
27
+ "runConfig": {
28
+ "maxTurns": 20
29
+ },
30
+ "modelConfig": {
31
+ "model": "gemini-3-flash-preview"
32
+ }
33
+ }
34
+ }
35
+ }
36
+ }
@@ -0,0 +1,90 @@
1
+ ---
2
+ name: extension-builder
3
+ description: Guide for creating new Gemini CLI extensions with MCP tools.
4
+ ---
5
+
6
+ # create-extension Guide Skill
7
+
8
+ This skill allows Tars to create new Gemini CLI extensions with MCP servers.
9
+
10
+ ## Instructions
11
+
12
+ When you need to build a new tool or integration:
13
+
14
+ 1. **Plan the Extension**: Define the name and the MCP tools it will expose.
15
+ 2. **Create the Directory**: Move to `~/.tars/.gemini/extensions/<name>`.
16
+ 3. **Initialize npm**: Run `npm init -y`.
17
+ 4. **Install Dependencies**: Install `@modelcontextprotocol/sdk` and any other required libraries.
18
+ 5. **Write the Server (JavaScript)**: Create a `server.js` file.
19
+ - **CRITICAL**: Use plain JavaScript for runtime-created extensions to avoid a build step.
20
+ - Use the `@modelcontextprotocol/sdk` to define tools and handle stdio.
21
+ 6. **Create Manifest**: Create `gemini-extension.json`.
22
+ 7. **Enable Extension**: Edit `~/.tars/.gemini/extensions/extension-enablement.json` to enable the new extension.
23
+ - Since you created the extension directly in the `extensions` directory, it is already "installed".
24
+ - You must now authorize it by adding an entry matching your Tars workspace path:
25
+ ```json
26
+ "my-extension": {
27
+ "overrides": ["/path/to/tars/*"]
28
+ }
29
+ ```
30
+ 8. **Finalize**: Restart Tars using the `tars-ops` procedure.
31
+ - **Note**: Tars automatically enables extensions found in its source repository, but for runtime-created extensions like this one, you must manually add the enablement rule.
32
+
33
+ ## Manifest Template (gemini-extension.json)
34
+
35
+ ```json
36
+ {
37
+ "name": "my-extension",
38
+ "version": "1.0.0",
39
+ "mcpServers": {
40
+ "main": {
41
+ "command": "node",
42
+ "args": ["${extensionPath}/server.js"],
43
+ "env": {
44
+ "NODE_ENV": "production"
45
+ }
46
+ }
47
+ }
48
+ }
49
+ ```
50
+
51
+ ## Server Template (server.js)
52
+
53
+ ```javascript
54
+ #!/usr/bin/env node
55
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
56
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
57
+ import { z } from 'zod';
58
+
59
+ const server = new McpServer({
60
+ name: 'my-extension',
61
+ version: '1.0.0'
62
+ });
63
+
64
+ server.registerTool(
65
+ 'my_tool',
66
+ {
67
+ description: 'Describe tool here',
68
+ inputSchema: z.object({}).shape
69
+ },
70
+ async (args) => {
71
+ return {
72
+ content: [{ type: 'text', text: 'Hello from Tars extension!' }]
73
+ };
74
+ }
75
+ );
76
+
77
+ const transport = new StdioServerTransport();
78
+ await server.connect(transport);
79
+ ```
80
+
81
+ ## Handling Secrets & Authentication
82
+
83
+ Do **NOT** pass API keys or credentials as tool arguments. This exposes them in the conversation history and logs.
84
+
85
+ **Standard Workflow:**
86
+
87
+ 1. **Access**: Use `process.env.MY_SECRET_KEY` in your extension code.
88
+ 2. **Missing Key Handling**: If missing, return a clear error:
89
+ `"API Key missing. Please run 'tars secret set MY_SECRET_KEY <YOUR_KEY>' and restart Tars."`
90
+ 3. **Storage**: Tars manages these via `~/.tars/.env` with private permissions.
@@ -0,0 +1,33 @@
1
+ ---
2
+ name: skill-creator
3
+ description: Guide for creating new SKILL.md files for automated workflows.
4
+ ---
5
+
6
+ # create-skill Guide Skill
7
+
8
+ This skill allows Tars to create new `SKILL.md` files for specific workflows.
9
+
10
+ ## Instructions
11
+
12
+ 1. **Define the Scope**: What specific repeatable task does this skill cover?
13
+ 2. **Create Directory**: Create a directory in `~/.tars/.gemini/skills/<name>`.
14
+ 3. **Write SKILL.md**:
15
+ - Include YAML frontmatter with `name` and `description`.
16
+ - Provide clear, step-by-step instructions.
17
+ - Include code snippets or command examples where relevant.
18
+
19
+ ## Template
20
+
21
+ ```markdown
22
+ ---
23
+ name: name-of-skill
24
+ description: what this skill does
25
+ ---
26
+
27
+ # name-of-skill
28
+
29
+ ## Steps
30
+
31
+ 1. ...
32
+ 2. ...
33
+ ```
@@ -0,0 +1,69 @@
1
+ ---
2
+ name: extension-manager
3
+ description: Enable, disable, list, and install Gemini CLI extensions at runtime.
4
+ ---
5
+
6
+ # manage-extensions Guide Skill
7
+
8
+ This skill allows Tars to manage Gemini CLI extensions - listing, enabling, disabling, and installing them.
9
+
10
+ ## How It Works
11
+
12
+ Extensions are managed via the `gemini extensions` CLI commands. Because Tars spawns a fresh `gemini chat` process for each interaction, any changes made during one message take effect on the **next message** automatically.
13
+
14
+ Extension enablement state is persisted in:
15
+ `~/.tars/.gemini/extensions/extension-enablement.json`
16
+
17
+ ## Commands
18
+
19
+ All commands below should be executed via `run_shell_command`. The `GEMINI_CLI_HOME` environment variable is already set in your shell environment.
20
+
21
+ ### List Extensions
22
+
23
+ ```bash
24
+ gemini extensions list
25
+ ```
26
+
27
+ Shows all installed extensions, their enabled/disabled state, and their MCP servers.
28
+
29
+ ### Disable an Extension
30
+
31
+ ```bash
32
+ gemini extensions disable <name>
33
+ ```
34
+
35
+ Disables the extension for the current user scope. It will no longer load on the next interaction.
36
+
37
+ - `--scope user` - Disable for the user (default).
38
+ - `--scope workspace` - Disable only for the current project.
39
+
40
+ ### Enable an Extension
41
+
42
+ ```bash
43
+ gemini extensions enable <name>
44
+ ```
45
+
46
+ Re-enables a previously disabled extension.
47
+
48
+ ### Install an Extension
49
+
50
+ ```bash
51
+ gemini extensions install <path-or-url>
52
+ ```
53
+
54
+ Installs a new extension from a local directory or remote URL.
55
+
56
+ ### Link an Extension (Development)
57
+
58
+ ```bash
59
+ gemini extensions link <path>
60
+ ```
61
+
62
+ Creates a symlink to a local extension directory. Changes to the source are reflected immediately without reinstalling.
63
+
64
+ ## Important Notes
65
+
66
+ 1. **Changes are deferred**: Enable/disable only takes effect on the **next** `gemini chat` invocation. Since Tars spawns a fresh process per Discord message, changes apply on the next message.
67
+ 2. **State file**: The enablement state is stored in `extension-enablement.json`, not in `settings.json`.
68
+ 3. **Scope**: Use `--scope workspace` if you only want to toggle an extension for a specific project context.
69
+ 4. **Discovery**: If an extension's MCP server fails to connect at startup, it will show an error in the logs but won't crash the session.
@@ -0,0 +1,89 @@
1
+ ---
2
+ name: tars-ops
3
+ description: Operational manual for Tars self-management and configuration.
4
+ ---
5
+
6
+ # Tars Operational Guide
7
+
8
+ Use this skill when you need to change Tars' configuration, manage secrets, or perform system maintenance.
9
+
10
+ ## Core Commands
11
+
12
+ Always use the built binary path from the repository warning: `tars` or `npm run dev`.
13
+
14
+ ### Configuration (Secrets & Env)
15
+
16
+ Tars stores its configuration (Discord tokens, API keys, intervals) in `~/.tars/.env`. Use the `secret` command to safely modify these.
17
+
18
+ ```bash
19
+ # Set a configuration value
20
+ tars secret set <KEY> <VALUE>
21
+
22
+ # List keys (values are hidden)
23
+ tars secret list
24
+
25
+ # Remove a setting
26
+ tars secret remove <KEY>
27
+ ```
28
+
29
+ **Common Keys:**
30
+
31
+ - `HEARTBEAT_INTERVAL_SEC`: Frequency of autonomous checks (default 300).
32
+ - `GEMINI_MODEL`: The primary model to use.
33
+ - `DISCORD_TOKEN`: Bot authentication.
34
+
35
+ ### Applying Changes (Restart)
36
+
37
+ Most configuration changes (like heartbeat intervals) require a supervisor restart.
38
+
39
+ ````bash
40
+ ```bash
41
+ # In development (restart)
42
+ npm run dev
43
+
44
+ # Or using the global CLI
45
+ tars stop && tars start
46
+ ````
47
+
48
+ ````
49
+
50
+ ### Knowledge Management
51
+
52
+ Use the `memory` command to search or manually trigger a sync of the long-term knowledge base.
53
+
54
+ ```bash
55
+ # Search memory
56
+ tars memory search "query"
57
+
58
+ # Force a full sync of GEMINI.md and skills into the FTS index
59
+ tars memory sync
60
+ ```
61
+
62
+ ## Self-Maintenance (Data Hygiene)
63
+
64
+ ### 1. Log Pruning
65
+ Tars generates logs in `~/.tars/logs/`. These are crucial for debugging recent issues but unnecessary to keep forever.
66
+ * **Policy**: Keep logs for the last 7 days.
67
+ * **Command**: `find ~/.tars/logs -type f -mtime +7 -delete`
68
+
69
+ ### 2. Upload Cleanup
70
+ Files uploaded to `~/.tars/data/uploads/` are temporary staging for processing.
71
+ * **Policy**: Remove uploads older than 24 hours.
72
+ * **Command**: `find ~/.tars/data/uploads -type f -mtime +1 -delete`
73
+
74
+ ### 3. History Management
75
+ The `~/.tars/.gemini/history/` directory contains raw JSON conversation logs. These grow rapidly.
76
+ * **Policy**: Keep the most recent 100 conversation logs.
77
+ * **Command**: `ls -t ~/.tars/.gemini/history/*.json | tail -n +101 | xargs -I {} rm {}` (Be careful with xargs; ensure filenames don't have special characters, or use `find` by time if preferred).
78
+
79
+ ### 4. Anomaly Detection
80
+ Occasionally, bugs in code may create recursive directories (like `~/.tars/.tars` or `~/.tars/~`).
81
+ * **Policy**: Check for and remove these specific anomalies if found.
82
+ * **Command**: `rm -rf ~/.tars/.tars ~/.tars/\~``
83
+
84
+ ## Important Safety Rules
85
+
86
+ 1. **Anti-Recursion**: NEVER run `node dist/supervisor/main.js` or `npm run start` directly. This will now fail by design. Always use `tars start` (production) or `npm run dev` (local).
87
+ 2. **Pathing**: The `tars` CLI handles paths automatically.
88
+ 3. **Internal Reasoning**: Before changing a system-level setting (like heartbeat frequency), explain the "Why" to the user unless it is part of a self-correction heartbeat.
89
+ ````
@@ -0,0 +1,4 @@
1
+ /**
2
+ * tars discord - Display Discord setup and invitation instructions
3
+ */
4
+ export declare function discord(): Promise<void>;
@@ -0,0 +1,48 @@
1
+ import chalk from 'chalk';
2
+ /**
3
+ * tars discord - Display Discord setup and invitation instructions
4
+ */
5
+ export async function discord() {
6
+ console.log(chalk.bold.cyan('\n💬 Discord Setup & Invitation Guide'));
7
+ console.log(chalk.cyan('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
8
+ console.log(chalk.bold('\n1. 🛠️ Configure your Bot Application'));
9
+ console.log(chalk.white(' • Go to: ') + chalk.blue('https://discord.com/developers/applications'));
10
+ console.log(chalk.white(' • Select your Tars application.'));
11
+ console.log(chalk.white(' • Click ') + chalk.bold('Bot') + chalk.white(' in the sidebar.'));
12
+ console.log(chalk.white(' • Toggle ') +
13
+ chalk.bold.red('Message Content Intent') +
14
+ chalk.white(' to ON.'));
15
+ console.log(chalk.white(' • ') +
16
+ chalk.italic('Note: A green "Save Changes" bar will pop up at the bottom — click it!'));
17
+ console.log(chalk.bold('\n2. 🔗 Generate Invitation Link'));
18
+ console.log(chalk.white(' • Click ') +
19
+ chalk.bold('OAuth2') +
20
+ chalk.white(' -> ') +
21
+ chalk.bold('URL Generator') +
22
+ chalk.white(' in the sidebar.'));
23
+ console.log(chalk.white(' • Scopes: Check ') + chalk.green('bot') + chalk.white('.'));
24
+ console.log(chalk.white(' • Bot Permissions: Check ') +
25
+ chalk.green('Send Messages') +
26
+ chalk.white(', ') +
27
+ chalk.green('Read Message History') +
28
+ chalk.white(', and ') +
29
+ chalk.green('View Channels') +
30
+ chalk.white('.'));
31
+ console.log(chalk.white(' • ') +
32
+ chalk.italic('No save required here!') +
33
+ chalk.white(' Just copy the generated URL at the bottom and open it in a new tab.'));
34
+ console.log(chalk.bold('\n3. 🏰 Add to Server'));
35
+ console.log(chalk.white(' • Select your server from the dropdown.'));
36
+ console.log(chalk.white(' ') +
37
+ chalk.italic("(Don't have a server? Create one in Discord first by clicking the [+] icon in your server list)"));
38
+ console.log(chalk.white(' • Click ') + chalk.bold('Authorize') + chalk.white('.'));
39
+ console.log(chalk.bold('\n4. ✅ Verify Installation'));
40
+ console.log(chalk.white(' • Tars should appear in your member list.'));
41
+ console.log(chalk.white(' • Once Tars is running (via ') +
42
+ chalk.cyan('tars start') +
43
+ chalk.white('), type ') +
44
+ chalk.bold('!tars hello') +
45
+ chalk.white(' to test.'));
46
+ console.log('\n');
47
+ }
48
+ //# sourceMappingURL=discord.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discord.js","sourceRoot":"","sources":["../../../src/cli/commands/discord.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function exportBrain(options: {
2
+ output?: string;
3
+ }): Promise<void>;
@@ -0,0 +1,39 @@
1
+ import { spawn } from 'child_process';
2
+ import chalk from 'chalk';
3
+ import path from 'path';
4
+ import os from 'os';
5
+ export async function exportBrain(options) {
6
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
7
+ const defaultName = `tars-brain-${timestamp}.tar.gz`;
8
+ const outputPath = options.output
9
+ ? path.resolve(options.output)
10
+ : path.join(process.cwd(), defaultName);
11
+ console.log(chalk.cyan(`📦 Exporting Tars brain to ${outputPath}...`));
12
+ const tarsHome = path.join(os.homedir(), '.tars');
13
+ const geminiHome = path.join(os.homedir(), '.gemini');
14
+ // Exclude heavy directories to keep the brain lean
15
+ const excludes = [
16
+ '--exclude=node_modules',
17
+ '--exclude=.next',
18
+ '--exclude=dist',
19
+ '--exclude=build',
20
+ '--exclude=.cache',
21
+ '--exclude=venv',
22
+ '--exclude=.venv',
23
+ '--exclude=target', // Rust
24
+ '--exclude=vendor', // PHP/Go
25
+ '--exclude=.sass-cache'
26
+ ];
27
+ const tar = spawn('tar', ['-czf', outputPath, ...excludes, '-C', os.homedir(), '.tars']);
28
+ tar.stderr.on('data', (data) => console.warn(chalk.yellow(data.toString())));
29
+ tar.on('close', (code) => {
30
+ if (code === 0) {
31
+ console.log(chalk.green('\n✅ Brain exported successfully!'));
32
+ console.log(`Keep this file safe: ${chalk.bold(outputPath)}`);
33
+ }
34
+ else {
35
+ console.error(chalk.red('\n❌ Export failed.'));
36
+ }
37
+ });
38
+ }
39
+ //# sourceMappingURL=export.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.js","sourceRoot":"","sources":["../../../src/cli/commands/export.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAA4B;IAC1D,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC9E,MAAM,WAAW,GAAG,cAAc,SAAS,SAAS,CAAC;IACrD,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM;QAC7B,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;QAC9B,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,WAAW,CAAC,CAAC;IAE5C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,8BAA8B,UAAU,KAAK,CAAC,CAAC,CAAC;IAEvE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;IAClD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;IAEtD,mDAAmD;IACnD,MAAM,QAAQ,GAAG;QACb,wBAAwB;QACxB,iBAAiB;QACjB,gBAAgB;QAChB,iBAAiB;QACjB,kBAAkB;QAClB,gBAAgB;QAChB,iBAAiB;QACjB,kBAAkB,EAAE,OAAO;QAC3B,kBAAkB,EAAE,SAAS;QAC7B,uBAAuB;KAC1B,CAAC;IAEF,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;IAEzF,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;IAE7E,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;QACrB,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;YACb,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC,CAAC;YAC7D,OAAO,CAAC,GAAG,CAAC,wBAAwB,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QAClE,CAAC;aAAM,CAAC;YACJ,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC,CAAC;QACnD,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function importBrain(archivePath: string): Promise<void>;
@@ -0,0 +1,45 @@
1
+ import { spawn } from 'child_process';
2
+ import chalk from 'chalk';
3
+ import os from 'os';
4
+ import path from 'path';
5
+ import fs from 'fs';
6
+ export async function importBrain(archivePath) {
7
+ const fullPath = path.resolve(archivePath);
8
+ const homeDir = os.homedir();
9
+ const tarsDir = path.join(homeDir, '.tars');
10
+ console.log(chalk.cyan(`📥 Importing Tars brain from ${fullPath}...`));
11
+ // 1. Extract the archive
12
+ const tar = spawn('tar', ['-xzf', fullPath, '-C', homeDir]);
13
+ tar.stderr.on('data', (data) => console.warn(chalk.yellow(data.toString())));
14
+ return new Promise((resolve) => {
15
+ tar.on('close', async (code) => {
16
+ if (code !== 0) {
17
+ console.error(chalk.red('\n❌ Import failed. Check if the file exists and is valid.'));
18
+ resolve();
19
+ return;
20
+ }
21
+ // 2. Machine Portability: Re-home absolute paths in extension-enablement.json
22
+ const enablementPath = path.join(tarsDir, '.gemini', 'extensions', 'extension-enablement.json');
23
+ if (fs.existsSync(enablementPath)) {
24
+ try {
25
+ console.log(chalk.blue('🏠 Normalizing paths for this machine...'));
26
+ const content = fs.readFileSync(enablementPath, 'utf-8');
27
+ // Regex to find things that look like old home directory paths ending in .tars
28
+ // e.g. /home/olduser/.tars/* or /Users/olduser/.tars/* -> current tarsDir
29
+ const rehomedContent = content.replace(/\/(home|Users)\/[^/]+\/\.tars/g, tarsDir);
30
+ if (content !== rehomedContent) {
31
+ fs.writeFileSync(enablementPath, rehomedContent);
32
+ console.log(chalk.green('✨ Extensions successfully re-homed.'));
33
+ }
34
+ }
35
+ catch (err) {
36
+ console.warn(chalk.yellow(`⚠️ Could not normalize extension paths: ${err.message}`));
37
+ }
38
+ }
39
+ console.log(chalk.green('\n✅ Brain imported successfully!'));
40
+ console.log(`Tars is now restored. Run ${chalk.cyan('tars status')} to verify.`);
41
+ resolve();
42
+ });
43
+ });
44
+ }
45
+ //# sourceMappingURL=import.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import.js","sourceRoot":"","sources":["../../../src/cli/commands/import.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,WAAmB;IACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;IAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAE5C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,gCAAgC,QAAQ,KAAK,CAAC,CAAC,CAAC;IAEvE,yBAAyB;IACzB,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAE5D,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;IAE7E,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QACjC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;YAC3B,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CACT,KAAK,CAAC,GAAG,CAAC,2DAA2D,CAAC,CACzE,CAAC;gBACF,OAAO,EAAE,CAAC;gBACV,OAAO;YACX,CAAC;YAED,8EAA8E;YAC9E,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAC5B,OAAO,EACP,SAAS,EACT,YAAY,EACZ,2BAA2B,CAC9B,CAAC;YAEF,IAAI,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;gBAChC,IAAI,CAAC;oBACD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC,CAAC;oBACpE,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;oBAEzD,+EAA+E;oBAC/E,0EAA0E;oBAC1E,MAAM,cAAc,GAAG,OAAO,CAAC,OAAO,CAClC,gCAAgC,EAChC,OAAO,CACV,CAAC;oBAEF,IAAI,OAAO,KAAK,cAAc,EAAE,CAAC;wBAC7B,EAAE,CAAC,aAAa,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC;wBACjD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC,CAAC;oBACpE,CAAC;gBACL,CAAC;gBAAC,OAAO,GAAQ,EAAE,CAAC;oBAChB,OAAO,CAAC,IAAI,CACR,KAAK,CAAC,MAAM,CAAC,2CAA2C,GAAG,CAAC,OAAO,EAAE,CAAC,CACzE,CAAC;gBACN,CAAC;YACL,CAAC;YAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC,CAAC;YAC7D,OAAO,CAAC,GAAG,CAAC,6BAA6B,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;YACjF,OAAO,EAAE,CAAC;QACd,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,4 @@
1
+ /**
2
+ * tars logs - Wrapper for pm2 logs tars-supervisor
3
+ */
4
+ export declare function logs(): Promise<void>;
@@ -0,0 +1,23 @@
1
+ import { spawn } from 'child_process';
2
+ import path from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ /**
5
+ * tars logs - Wrapper for pm2 logs tars-supervisor
6
+ */
7
+ export async function logs() {
8
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
+ const pm2Path = path.resolve(__dirname, '../../../node_modules/.bin/pm2');
10
+ // Run pm2 logs
11
+ const child = spawn(pm2Path, ['logs', 'tars-supervisor', '--lines', '20'], {
12
+ stdio: 'inherit',
13
+ shell: true
14
+ });
15
+ child.on('error', (err) => {
16
+ // Fallback to npx if relative path fails (though it shouldn't)
17
+ spawn('npx', ['pm2', 'logs', 'tars-supervisor', '--lines', '20'], {
18
+ stdio: 'inherit',
19
+ shell: true
20
+ });
21
+ });
22
+ }
23
+ //# sourceMappingURL=logs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logs.js","sourceRoot":"","sources":["../../../src/cli/commands/logs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,IAAI;IACtB,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,gCAAgC,CAAC,CAAC;IAE1E,eAAe;IACf,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,iBAAiB,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE;QACvE,KAAK,EAAE,SAAS;QAChB,KAAK,EAAE,IAAI;KACd,CAAC,CAAC;IAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;QACtB,+DAA+D;QAC/D,KAAK,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,iBAAiB,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE;YAC9D,KAAK,EAAE,SAAS;YAChB,KAAK,EAAE,IAAI;SACd,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function memory(action: string, ...args: string[]): Promise<void>;