titan-agent 2026.4.2 → 2026.4.3
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/dist/cli/index.js +200 -125
- package/dist/cli/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -4629,180 +4629,255 @@ init_config();
|
|
|
4629
4629
|
init_constants();
|
|
4630
4630
|
init_helpers();
|
|
4631
4631
|
init_memory();
|
|
4632
|
-
import { select, input, confirm, password } from "@inquirer/prompts";
|
|
4632
|
+
import { select, input, confirm, password, checkbox } from "@inquirer/prompts";
|
|
4633
4633
|
import chalk3 from "chalk";
|
|
4634
|
-
async function
|
|
4635
|
-
|
|
4636
|
-
|
|
4634
|
+
async function fetchOllamaModels(baseUrl) {
|
|
4635
|
+
try {
|
|
4636
|
+
const res = await fetch(`${baseUrl}/api/tags`, { signal: AbortSignal.timeout(3e3) });
|
|
4637
|
+
if (!res.ok) return [];
|
|
4638
|
+
const json = await res.json();
|
|
4639
|
+
return (json.models || []).map((m) => m.name).filter(Boolean);
|
|
4640
|
+
} catch {
|
|
4641
|
+
return [];
|
|
4642
|
+
}
|
|
4643
|
+
}
|
|
4644
|
+
async function runOnboard(_installDaemon) {
|
|
4645
|
+
console.log(chalk3.cyan("\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
|
|
4646
|
+
console.log(chalk3.cyan("\u2551 \u26A1 Welcome to TITAN Setup Wizard! \u2551"));
|
|
4647
|
+
console.log(chalk3.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\n"));
|
|
4648
|
+
console.log(chalk3.gray("This wizard will configure your personal AI assistant.\n"));
|
|
4649
|
+
console.log(chalk3.gray("Press Ctrl+C at any time to cancel.\n"));
|
|
4637
4650
|
const config = getDefaultConfig();
|
|
4638
|
-
console.log(chalk3.yellow("\u2500\u2500\u2500 Step 1: AI Provider \u2500\u2500\u2500\n"));
|
|
4651
|
+
console.log(chalk3.yellow("\u2500\u2500\u2500 Step 1 of 7: AI Provider \u2500\u2500\u2500\n"));
|
|
4639
4652
|
const provider = await select({
|
|
4640
|
-
message: "Which AI provider would you like to use?",
|
|
4653
|
+
message: "Which AI provider would you like to use as your primary?",
|
|
4641
4654
|
choices: [
|
|
4642
|
-
{ name: "Anthropic (Claude) \u2014
|
|
4643
|
-
{ name: "OpenAI (GPT-
|
|
4644
|
-
{ name: "Google (Gemini)", value: "google" },
|
|
4645
|
-
{ name: "Ollama (Local
|
|
4655
|
+
{ name: "\u{1F7E3} Anthropic (Claude) \u2014 Best reasoning, recommended", value: "anthropic" },
|
|
4656
|
+
{ name: "\u{1F7E2} OpenAI (GPT-4o) \u2014 Great all-rounder", value: "openai" },
|
|
4657
|
+
{ name: "\u{1F535} Google (Gemini) \u2014 Fast & multimodal", value: "google" },
|
|
4658
|
+
{ name: "\u{1F7E0} Ollama (Local) \u2014 Free, private, runs on your machine", value: "ollama" }
|
|
4646
4659
|
]
|
|
4647
4660
|
});
|
|
4661
|
+
console.log(chalk3.yellow("\n\u2500\u2500\u2500 Step 2 of 7: Model \u2500\u2500\u2500\n"));
|
|
4648
4662
|
if (provider === "ollama") {
|
|
4649
4663
|
const ollamaUrl = await input({
|
|
4650
4664
|
message: "Ollama base URL:",
|
|
4651
4665
|
default: "http://localhost:11434"
|
|
4652
4666
|
});
|
|
4653
4667
|
config.providers.ollama.baseUrl = ollamaUrl;
|
|
4654
|
-
|
|
4668
|
+
console.log(chalk3.gray(`
|
|
4669
|
+
\u{1F50D} Detecting models at ${ollamaUrl}...`));
|
|
4670
|
+
const installedModels = await fetchOllamaModels(ollamaUrl);
|
|
4671
|
+
if (installedModels.length > 0) {
|
|
4672
|
+
console.log(chalk3.green(` \u2705 Found ${installedModels.length} installed model(s)
|
|
4673
|
+
`));
|
|
4674
|
+
const chosen = await select({
|
|
4675
|
+
message: "Select a model to use:",
|
|
4676
|
+
choices: installedModels.map((m) => ({ name: m, value: `ollama/${m}` }))
|
|
4677
|
+
});
|
|
4678
|
+
config.agent.model = chosen;
|
|
4679
|
+
} else {
|
|
4680
|
+
console.log(chalk3.yellow(" \u26A0\uFE0F No models detected (Ollama may not be running, or no models pulled yet)."));
|
|
4681
|
+
console.log(chalk3.gray(" Run: ollama pull llama3.1 to install a model\n"));
|
|
4682
|
+
const modelName = await input({
|
|
4683
|
+
message: "Enter the Ollama model name to use:",
|
|
4684
|
+
default: "llama3.1"
|
|
4685
|
+
});
|
|
4686
|
+
config.agent.model = `ollama/${modelName}`;
|
|
4687
|
+
}
|
|
4655
4688
|
} else {
|
|
4656
4689
|
const apiKey = await password({
|
|
4657
|
-
message: `Enter your ${provider} API key
|
|
4690
|
+
message: `Enter your ${provider} API key:`,
|
|
4691
|
+
mask: "*"
|
|
4692
|
+
});
|
|
4693
|
+
const modelChoices = {
|
|
4694
|
+
anthropic: [
|
|
4695
|
+
{ name: "claude-sonnet-4-20250514 (Latest, recommended)", value: "anthropic/claude-sonnet-4-20250514" },
|
|
4696
|
+
{ name: "claude-opus-4-0 (Most capable, slower)", value: "anthropic/claude-opus-4-0" },
|
|
4697
|
+
{ name: "claude-3-5-haiku-20241022 (Fastest, cheapest)", value: "anthropic/claude-3-5-haiku-20241022" }
|
|
4698
|
+
],
|
|
4699
|
+
openai: [
|
|
4700
|
+
{ name: "gpt-4o (Recommended)", value: "openai/gpt-4o" },
|
|
4701
|
+
{ name: "gpt-4o-mini (Fast & cheap)", value: "openai/gpt-4o-mini" },
|
|
4702
|
+
{ name: "o3 (Best reasoning)", value: "openai/o3" },
|
|
4703
|
+
{ name: "o4-mini (Fast reasoning)", value: "openai/o4-mini" }
|
|
4704
|
+
],
|
|
4705
|
+
google: [
|
|
4706
|
+
{ name: "gemini-2.5-flash (Recommended)", value: "google/gemini-2.5-flash" },
|
|
4707
|
+
{ name: "gemini-2.5-pro (Most capable)", value: "google/gemini-2.5-pro" },
|
|
4708
|
+
{ name: "gemini-2.0-flash (Fast)", value: "google/gemini-2.0-flash" }
|
|
4709
|
+
]
|
|
4710
|
+
};
|
|
4711
|
+
const models = modelChoices[provider] || [];
|
|
4712
|
+
const selectedModel = await select({
|
|
4713
|
+
message: "Which model would you like to use?",
|
|
4714
|
+
choices: [...models, { name: "\u270F\uFE0F Enter manually", value: "__manual__" }]
|
|
4658
4715
|
});
|
|
4716
|
+
if (selectedModel === "__manual__") {
|
|
4717
|
+
config.agent.model = await input({ message: "Enter model identifier:" });
|
|
4718
|
+
} else {
|
|
4719
|
+
config.agent.model = selectedModel;
|
|
4720
|
+
}
|
|
4659
4721
|
if (provider === "anthropic") {
|
|
4660
4722
|
config.providers.anthropic.apiKey = apiKey;
|
|
4661
|
-
config.agent.model = "anthropic/claude-sonnet-4-20250514";
|
|
4662
4723
|
} else if (provider === "openai") {
|
|
4663
4724
|
config.providers.openai.apiKey = apiKey;
|
|
4664
|
-
config.agent.model = "openai/gpt-4o";
|
|
4665
4725
|
} else if (provider === "google") {
|
|
4666
4726
|
config.providers.google.apiKey = apiKey;
|
|
4667
|
-
config.agent.model = "google/gemini-2.5-flash";
|
|
4668
4727
|
}
|
|
4669
|
-
|
|
4670
|
-
|
|
4671
|
-
|
|
4672
|
-
message: `Use default model (${config.agent.model})?`,
|
|
4673
|
-
default: true
|
|
4674
|
-
});
|
|
4675
|
-
if (!useDefault) {
|
|
4676
|
-
const model = await input({
|
|
4677
|
-
message: "Enter model identifier (e.g., anthropic/claude-opus-4-0):",
|
|
4678
|
-
default: config.agent.model
|
|
4728
|
+
const addFallback = await confirm({
|
|
4729
|
+
message: "Add a second provider as fallback (for failover if the primary is unavailable)?",
|
|
4730
|
+
default: false
|
|
4679
4731
|
});
|
|
4680
|
-
|
|
4681
|
-
|
|
4682
|
-
|
|
4683
|
-
|
|
4684
|
-
|
|
4685
|
-
default: false
|
|
4686
|
-
});
|
|
4687
|
-
if (enableChannels) {
|
|
4688
|
-
const selectedChannels = await select({
|
|
4689
|
-
message: "Which channel to configure?",
|
|
4690
|
-
choices: [
|
|
4691
|
-
{ name: "Discord", value: "discord" },
|
|
4692
|
-
{ name: "Telegram", value: "telegram" },
|
|
4693
|
-
{ name: "Slack", value: "slack" },
|
|
4694
|
-
{ name: "Skip for now", value: "skip" }
|
|
4695
|
-
]
|
|
4696
|
-
});
|
|
4697
|
-
if (selectedChannels !== "skip") {
|
|
4698
|
-
const token = await password({
|
|
4699
|
-
message: `Enter your ${selectedChannels} bot token:`
|
|
4732
|
+
if (addFallback) {
|
|
4733
|
+
const fallbackProviders = ["anthropic", "openai", "google", "ollama"].filter((p) => p !== provider);
|
|
4734
|
+
const fallback = await select({
|
|
4735
|
+
message: "Select fallback provider:",
|
|
4736
|
+
choices: fallbackProviders.map((p) => ({ name: p.charAt(0).toUpperCase() + p.slice(1), value: p }))
|
|
4700
4737
|
});
|
|
4701
|
-
if (
|
|
4702
|
-
|
|
4703
|
-
config.
|
|
4704
|
-
} else
|
|
4705
|
-
|
|
4706
|
-
config.
|
|
4707
|
-
|
|
4708
|
-
config.
|
|
4709
|
-
config.channels.slack.token = token;
|
|
4738
|
+
if (fallback === "ollama") {
|
|
4739
|
+
const ollamaUrl = await input({ message: "Ollama base URL:", default: "http://localhost:11434" });
|
|
4740
|
+
config.providers.ollama.baseUrl = ollamaUrl;
|
|
4741
|
+
} else {
|
|
4742
|
+
const fallbackKey = await password({ message: `Enter your ${fallback} API key:`, mask: "*" });
|
|
4743
|
+
if (fallback === "anthropic") config.providers.anthropic.apiKey = fallbackKey;
|
|
4744
|
+
else if (fallback === "openai") config.providers.openai.apiKey = fallbackKey;
|
|
4745
|
+
else if (fallback === "google") config.providers.google.apiKey = fallbackKey;
|
|
4710
4746
|
}
|
|
4711
4747
|
}
|
|
4712
4748
|
}
|
|
4713
|
-
console.log(chalk3.yellow("\n\u2500\u2500\u2500 Step
|
|
4714
|
-
|
|
4715
|
-
message: "Sandbox mode for non-main sessions:",
|
|
4716
|
-
choices: [
|
|
4717
|
-
{ name: "Host (full access, single-user)", value: "host" },
|
|
4718
|
-
{ name: "Docker (isolated containers)", value: "docker" },
|
|
4719
|
-
{ name: "None (no restrictions)", value: "none" }
|
|
4720
|
-
]
|
|
4721
|
-
});
|
|
4722
|
-
config.security.sandboxMode = sandboxMode;
|
|
4723
|
-
console.log(chalk3.yellow("\n\u2500\u2500\u2500 Step 5: Autonomy \u2500\u2500\u2500\n"));
|
|
4724
|
-
console.log(chalk3.gray(" This controls how much freedom TITAN has to act on its own.\n"));
|
|
4749
|
+
console.log(chalk3.yellow("\n\u2500\u2500\u2500 Step 3 of 7: Autonomy \u2500\u2500\u2500\n"));
|
|
4750
|
+
console.log(chalk3.gray(" Controls how independently TITAN acts.\n"));
|
|
4725
4751
|
const autonomyMode = await select({
|
|
4726
4752
|
message: "How much autonomy should TITAN have?",
|
|
4727
4753
|
choices: [
|
|
4728
4754
|
{
|
|
4729
|
-
name: "\u{1F7E1} Supervised (Recommended) \u2014
|
|
4755
|
+
name: "\u{1F7E1} Supervised (Recommended) \u2014 safe ops run freely, dangerous ops ask first",
|
|
4730
4756
|
value: "supervised"
|
|
4731
4757
|
},
|
|
4732
4758
|
{
|
|
4733
|
-
name: "\u{1F7E2} Autonomous \u2014
|
|
4759
|
+
name: "\u{1F7E2} Autonomous \u2014 full auto, acts without asking. Best for power users.",
|
|
4734
4760
|
value: "autonomous"
|
|
4735
4761
|
},
|
|
4736
4762
|
{
|
|
4737
|
-
name: "\u{1F534} Locked \u2014
|
|
4763
|
+
name: "\u{1F534} Locked \u2014 every single action requires your approval.",
|
|
4738
4764
|
value: "locked"
|
|
4739
4765
|
}
|
|
4740
4766
|
]
|
|
4741
4767
|
});
|
|
4742
|
-
config.autonomy =
|
|
4743
|
-
console.log(chalk3.yellow("\n\u2500\u2500\u2500 Step
|
|
4744
|
-
const
|
|
4745
|
-
message: "
|
|
4746
|
-
|
|
4768
|
+
config.autonomy.mode = autonomyMode;
|
|
4769
|
+
console.log(chalk3.yellow("\n\u2500\u2500\u2500 Step 4 of 7: Security \u2500\u2500\u2500\n"));
|
|
4770
|
+
const sandboxMode = await select({
|
|
4771
|
+
message: "Sandbox mode for shell commands:",
|
|
4772
|
+
choices: [
|
|
4773
|
+
{ name: "\u{1F5A5}\uFE0F Host (Full access \u2014 single user machines)", value: "host" },
|
|
4774
|
+
{ name: "\u{1F433} Docker (Isolated containers \u2014 recommended for shared machines)", value: "docker" },
|
|
4775
|
+
{ name: "\u{1F6AB} None (No restrictions \u2014 not recommended)", value: "none" }
|
|
4776
|
+
]
|
|
4777
|
+
});
|
|
4778
|
+
config.security.sandboxMode = sandboxMode;
|
|
4779
|
+
const enableShield = await confirm({
|
|
4780
|
+
message: "Enable Prompt Injection Shield? (blocks attempts to hijack TITAN via chat messages)",
|
|
4781
|
+
default: true
|
|
4782
|
+
});
|
|
4783
|
+
config.security.shield.enabled = enableShield;
|
|
4784
|
+
if (enableShield) {
|
|
4785
|
+
const shieldMode = await select({
|
|
4786
|
+
message: "Shield strictness:",
|
|
4787
|
+
choices: [
|
|
4788
|
+
{ name: "Strict (recommended) \u2014 blocks suspicious payloads aggressively", value: "strict" },
|
|
4789
|
+
{ name: "Standard \u2014 blocks only obvious injection attempts", value: "standard" }
|
|
4790
|
+
]
|
|
4791
|
+
});
|
|
4792
|
+
config.security.shield.mode = shieldMode;
|
|
4793
|
+
}
|
|
4794
|
+
console.log(chalk3.yellow("\n\u2500\u2500\u2500 Step 5 of 7: Messaging Channels \u2500\u2500\u2500\n"));
|
|
4795
|
+
console.log(chalk3.gray(" Connect TITAN to Discord, Telegram, Slack, etc. (all optional)\n"));
|
|
4796
|
+
const channelChoices = await checkbox({
|
|
4797
|
+
message: "Which channels would you like to configure? (space to select, enter to continue)",
|
|
4798
|
+
choices: [
|
|
4799
|
+
{ name: "\u{1F3AE} Discord", value: "discord" },
|
|
4800
|
+
{ name: "\u2708\uFE0F Telegram", value: "telegram" },
|
|
4801
|
+
{ name: "\u{1F4BC} Slack", value: "slack" },
|
|
4802
|
+
{ name: "\u23ED\uFE0F Skip \u2014 configure later with `titan config`", value: "skip" }
|
|
4803
|
+
]
|
|
4804
|
+
});
|
|
4805
|
+
if (!channelChoices.includes("skip")) {
|
|
4806
|
+
for (const channel of channelChoices) {
|
|
4807
|
+
const token = await password({ message: ` ${channel} bot token:`, mask: "*" });
|
|
4808
|
+
if (channel === "discord") {
|
|
4809
|
+
config.channels.discord.enabled = true;
|
|
4810
|
+
config.channels.discord.token = token;
|
|
4811
|
+
} else if (channel === "telegram") {
|
|
4812
|
+
config.channels.telegram.enabled = true;
|
|
4813
|
+
config.channels.telegram.token = token;
|
|
4814
|
+
} else if (channel === "slack") {
|
|
4815
|
+
config.channels.slack.enabled = true;
|
|
4816
|
+
config.channels.slack.token = token;
|
|
4817
|
+
}
|
|
4818
|
+
}
|
|
4819
|
+
}
|
|
4820
|
+
console.log(chalk3.yellow("\n\u2500\u2500\u2500 Step 6 of 7: Gateway \u2500\u2500\u2500\n"));
|
|
4821
|
+
console.log(chalk3.gray(" Mission Control is served at http://127.0.0.1:<port>\n"));
|
|
4822
|
+
const useDefaultPort = await confirm({
|
|
4823
|
+
message: "Use default gateway port (18789)?",
|
|
4824
|
+
default: true
|
|
4747
4825
|
});
|
|
4748
|
-
|
|
4826
|
+
if (!useDefaultPort) {
|
|
4827
|
+
const port = await input({ message: "Enter gateway port:", default: "18789" });
|
|
4828
|
+
config.gateway.port = parseInt(port, 10);
|
|
4829
|
+
}
|
|
4830
|
+
const enableGatewayAuth = await confirm({
|
|
4831
|
+
message: "Enable gateway authentication? (recommended if accessible from other devices)",
|
|
4832
|
+
default: false
|
|
4833
|
+
});
|
|
4834
|
+
if (enableGatewayAuth) {
|
|
4835
|
+
const authMode = await select({
|
|
4836
|
+
message: "Authentication mode:",
|
|
4837
|
+
choices: [
|
|
4838
|
+
{ name: "Token (API key in request header)", value: "token" },
|
|
4839
|
+
{ name: "Password (browser prompt)", value: "password" }
|
|
4840
|
+
]
|
|
4841
|
+
});
|
|
4842
|
+
config.gateway.auth.mode = authMode;
|
|
4843
|
+
if (authMode === "token") {
|
|
4844
|
+
config.gateway.auth.token = await password({ message: "Set a gateway token:", mask: "*" });
|
|
4845
|
+
} else {
|
|
4846
|
+
config.gateway.auth.password = await password({ message: "Set a gateway password:", mask: "*" });
|
|
4847
|
+
}
|
|
4848
|
+
}
|
|
4849
|
+
console.log(chalk3.yellow("\n\u2500\u2500\u2500 Step 7 of 7: Logging \u2500\u2500\u2500\n"));
|
|
4850
|
+
const logLevel = await select({
|
|
4851
|
+
message: "Log level:",
|
|
4852
|
+
choices: [
|
|
4853
|
+
{ name: "info (recommended)", value: "info" },
|
|
4854
|
+
{ name: "debug (verbose \u2014 for troubleshooting)", value: "debug" },
|
|
4855
|
+
{ name: "warn (quiet \u2014 warnings and errors only)", value: "warn" },
|
|
4856
|
+
{ name: "silent (no logs)", value: "silent" }
|
|
4857
|
+
]
|
|
4858
|
+
});
|
|
4859
|
+
config.logging.level = logLevel;
|
|
4749
4860
|
console.log(chalk3.yellow("\n\u2500\u2500\u2500 Setting up workspace \u2500\u2500\u2500\n"));
|
|
4750
4861
|
ensureDir(TITAN_HOME);
|
|
4751
4862
|
ensureDir(TITAN_WORKSPACE);
|
|
4752
4863
|
ensureDir(TITAN_SKILLS_DIR);
|
|
4753
4864
|
initMemory();
|
|
4754
4865
|
saveConfig(config);
|
|
4755
|
-
if (installDaemon) {
|
|
4756
|
-
console.log(chalk3.yellow("\n\u2500\u2500\u2500 Installing daemon \u2500\u2500\u2500\n"));
|
|
4757
|
-
await installDaemonService();
|
|
4758
|
-
}
|
|
4759
4866
|
const modeEmoji = autonomyMode === "autonomous" ? "\u{1F7E2}" : autonomyMode === "locked" ? "\u{1F534}" : "\u{1F7E1}";
|
|
4760
|
-
console.log(chalk3.green("\n\
|
|
4761
|
-
console.log(chalk3.
|
|
4762
|
-
console.log(chalk3.
|
|
4763
|
-
console.log(chalk3.
|
|
4764
|
-
console.log(chalk3.gray(`
|
|
4765
|
-
console.log(chalk3.
|
|
4766
|
-
console.log(chalk3.gray(
|
|
4767
|
-
console.log(chalk3.gray(
|
|
4768
|
-
console.log(chalk3.gray(
|
|
4769
|
-
console.log(chalk3.
|
|
4770
|
-
|
|
4771
|
-
console.log(chalk3.gray(
|
|
4772
|
-
|
|
4773
|
-
|
|
4774
|
-
async function installDaemonService() {
|
|
4775
|
-
const platform = process.platform;
|
|
4776
|
-
if (platform === "linux") {
|
|
4777
|
-
console.log(chalk3.gray("Creating systemd user service..."));
|
|
4778
|
-
const serviceContent = `[Unit]
|
|
4779
|
-
Description=TITAN Gateway
|
|
4780
|
-
After=network.target
|
|
4781
|
-
|
|
4782
|
-
[Service]
|
|
4783
|
-
Type=simple
|
|
4784
|
-
ExecStart=${process.execPath} ${process.argv[1]} gateway
|
|
4785
|
-
Restart=on-failure
|
|
4786
|
-
RestartSec=10
|
|
4787
|
-
|
|
4788
|
-
[Install]
|
|
4789
|
-
WantedBy=default.target
|
|
4790
|
-
`;
|
|
4791
|
-
const { writeFileSync: writeFileSync9, mkdirSync: mkdirSync4, existsSync: existsSync14 } = await import("fs");
|
|
4792
|
-
const { join: join8 } = await import("path");
|
|
4793
|
-
const { homedir: homedir2 } = await import("os");
|
|
4794
|
-
const serviceDir = join8(homedir2(), ".config", "systemd", "user");
|
|
4795
|
-
if (!existsSync14(serviceDir)) mkdirSync4(serviceDir, { recursive: true });
|
|
4796
|
-
writeFileSync9(join8(serviceDir, "titan.service"), serviceContent);
|
|
4797
|
-
console.log(chalk3.green(" Service file installed. Enable with:"));
|
|
4798
|
-
console.log(chalk3.gray(" $ systemctl --user enable titan"));
|
|
4799
|
-
console.log(chalk3.gray(" $ systemctl --user start titan"));
|
|
4800
|
-
} else if (platform === "darwin") {
|
|
4801
|
-
console.log(chalk3.gray("Creating launchd plist..."));
|
|
4802
|
-
console.log(chalk3.yellow(" macOS daemon installation - create a LaunchAgent plist manually."));
|
|
4803
|
-
} else {
|
|
4804
|
-
console.log(chalk3.yellow(" Daemon installation not supported on this platform."));
|
|
4805
|
-
}
|
|
4867
|
+
console.log(chalk3.green("\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
|
|
4868
|
+
console.log(chalk3.green("\u2551 \u2705 TITAN is ready! \u2551"));
|
|
4869
|
+
console.log(chalk3.green("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\n"));
|
|
4870
|
+
console.log(chalk3.white(" Your configuration:"));
|
|
4871
|
+
console.log(chalk3.gray(` Model: ${config.agent.model}`));
|
|
4872
|
+
console.log(chalk3.gray(` Autonomy: ${modeEmoji} ${autonomyMode}`));
|
|
4873
|
+
console.log(chalk3.gray(` Sandbox: ${config.security.sandboxMode}`));
|
|
4874
|
+
console.log(chalk3.gray(` Logs: ${config.logging.level}`));
|
|
4875
|
+
console.log(chalk3.gray(` Config: ${TITAN_CONFIG_PATH}`));
|
|
4876
|
+
console.log(chalk3.white("\n Next steps:"));
|
|
4877
|
+
console.log(chalk3.cyan(" titan gateway ") + chalk3.gray(`\u2192 Open Mission Control at http://127.0.0.1:${config.gateway.port}`));
|
|
4878
|
+
console.log(chalk3.cyan(' titan agent -m "Hello" ') + chalk3.gray("\u2192 Send a direct message"));
|
|
4879
|
+
console.log(chalk3.cyan(" titan doctor ") + chalk3.gray("\u2192 Diagnose configuration & connectivity"));
|
|
4880
|
+
console.log();
|
|
4806
4881
|
}
|
|
4807
4882
|
|
|
4808
4883
|
// src/security/pairing.ts
|