spora 0.3.4 → 0.3.5

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.
@@ -0,0 +1,114 @@
1
+ import {
2
+ loadConfig
3
+ } from "./chunk-GMSK775L.js";
4
+ import {
5
+ logger
6
+ } from "./chunk-UCCAF2ZO.js";
7
+ import {
8
+ paths
9
+ } from "./chunk-6KCIAMHL.js";
10
+
11
+ // src/runtime/llm.ts
12
+ import OpenAI from "openai";
13
+ import Anthropic from "@anthropic-ai/sdk";
14
+ import { readFileSync, existsSync } from "fs";
15
+ var openaiClient = null;
16
+ var anthropicClient = null;
17
+ var DEFAULT_MODEL = "deepseek-v3.2-speciale";
18
+ var DEFAULT_BASE_URL = "https://api.llm-stats.com/v1";
19
+ function getLLMApiKey() {
20
+ if (process.env.LLM_API_KEY) {
21
+ return process.env.LLM_API_KEY;
22
+ }
23
+ if (process.env.ANTHROPIC_API_KEY) {
24
+ return process.env.ANTHROPIC_API_KEY;
25
+ }
26
+ if (existsSync(paths.llmKey)) {
27
+ return readFileSync(paths.llmKey, "utf-8").trim();
28
+ }
29
+ return null;
30
+ }
31
+ function hasLLMKey() {
32
+ return getLLMApiKey() !== null;
33
+ }
34
+ function getProvider() {
35
+ try {
36
+ const config = loadConfig();
37
+ return config.llm?.provider ?? "deepseek";
38
+ } catch {
39
+ return "deepseek";
40
+ }
41
+ }
42
+ function getOpenAIClient() {
43
+ if (openaiClient) return openaiClient;
44
+ const apiKey = getLLMApiKey();
45
+ if (!apiKey) throw new Error("No LLM API key configured. Run `spora set-llm-key` first.");
46
+ const config = loadConfig();
47
+ const baseURL = config.llm?.baseUrl ?? DEFAULT_BASE_URL;
48
+ openaiClient = new OpenAI({ apiKey, baseURL });
49
+ return openaiClient;
50
+ }
51
+ function getAnthropicClient() {
52
+ if (anthropicClient) return anthropicClient;
53
+ const apiKey = getLLMApiKey();
54
+ if (!apiKey) throw new Error("No LLM API key configured. Run `spora set-llm-key` first.");
55
+ anthropicClient = new Anthropic({ apiKey });
56
+ return anthropicClient;
57
+ }
58
+ async function callAnthropic(systemPrompt, messages, model) {
59
+ const client = getAnthropicClient();
60
+ const response = await client.messages.create({
61
+ model,
62
+ max_tokens: 2048,
63
+ system: systemPrompt,
64
+ messages
65
+ });
66
+ const textBlock = response.content.find((b) => b.type === "text");
67
+ const content = textBlock ? textBlock.text : "";
68
+ return {
69
+ content,
70
+ inputTokens: response.usage.input_tokens,
71
+ outputTokens: response.usage.output_tokens
72
+ };
73
+ }
74
+ async function callOpenAI(systemPrompt, messages, model) {
75
+ const client = getOpenAIClient();
76
+ const response = await client.chat.completions.create({
77
+ model,
78
+ max_tokens: 2048,
79
+ messages: [
80
+ { role: "system", content: systemPrompt },
81
+ ...messages
82
+ ]
83
+ });
84
+ const content = response.choices[0]?.message?.content ?? "";
85
+ const inputTokens = response.usage?.prompt_tokens ?? 0;
86
+ const outputTokens = response.usage?.completion_tokens ?? 0;
87
+ return { content, inputTokens, outputTokens };
88
+ }
89
+ async function generateResponse(systemPrompt, userMessage) {
90
+ const config = loadConfig();
91
+ const provider = getProvider();
92
+ const model = config.llm?.model ?? DEFAULT_MODEL;
93
+ logger.info(`Calling LLM (${provider}/${model})...`);
94
+ const messages = [
95
+ { role: "user", content: userMessage }
96
+ ];
97
+ const result = provider === "anthropic" ? await callAnthropic(systemPrompt, messages, model) : await callOpenAI(systemPrompt, messages, model);
98
+ logger.info(`LLM response: ${result.inputTokens} in, ${result.outputTokens} out`);
99
+ return result;
100
+ }
101
+ async function chat(systemPrompt, messages) {
102
+ const config = loadConfig();
103
+ const provider = getProvider();
104
+ const model = config.llm?.model ?? DEFAULT_MODEL;
105
+ return provider === "anthropic" ? callAnthropic(systemPrompt, messages, model) : callOpenAI(systemPrompt, messages, model);
106
+ }
107
+
108
+ export {
109
+ getLLMApiKey,
110
+ hasLLMKey,
111
+ generateResponse,
112
+ chat
113
+ };
114
+ //# sourceMappingURL=chunk-JAF57FYU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime/llm.ts"],"sourcesContent":["import OpenAI from \"openai\";\nimport Anthropic from \"@anthropic-ai/sdk\";\nimport { readFileSync, existsSync } from \"node:fs\";\nimport { paths } from \"../utils/paths.js\";\nimport { loadConfig } from \"../utils/config.js\";\nimport { logger } from \"../utils/logger.js\";\n\nlet openaiClient: OpenAI | null = null;\nlet anthropicClient: Anthropic | null = null;\n\nconst DEFAULT_MODEL = \"deepseek-v3.2-speciale\";\nconst DEFAULT_BASE_URL = \"https://api.llm-stats.com/v1\";\n\nexport function getLLMApiKey(): string | null {\n if (process.env.LLM_API_KEY) {\n return process.env.LLM_API_KEY;\n }\n if (process.env.ANTHROPIC_API_KEY) {\n return process.env.ANTHROPIC_API_KEY;\n }\n if (existsSync(paths.llmKey)) {\n return readFileSync(paths.llmKey, \"utf-8\").trim();\n }\n return null;\n}\n\nexport function hasLLMKey(): boolean {\n return getLLMApiKey() !== null;\n}\n\nfunction getProvider(): \"anthropic\" | \"deepseek\" {\n try {\n const config = loadConfig();\n return (config.llm?.provider as \"anthropic\" | \"deepseek\") ?? \"deepseek\";\n } catch {\n return \"deepseek\";\n }\n}\n\nfunction getOpenAIClient(): OpenAI {\n if (openaiClient) return openaiClient;\n const apiKey = getLLMApiKey();\n if (!apiKey) throw new Error(\"No LLM API key configured. Run `spora set-llm-key` first.\");\n const config = loadConfig();\n const baseURL = config.llm?.baseUrl ?? DEFAULT_BASE_URL;\n openaiClient = new OpenAI({ apiKey, baseURL });\n return openaiClient;\n}\n\nfunction getAnthropicClient(): Anthropic {\n if (anthropicClient) return anthropicClient;\n const apiKey = getLLMApiKey();\n if (!apiKey) throw new Error(\"No LLM API key configured. Run `spora set-llm-key` first.\");\n anthropicClient = new Anthropic({ apiKey });\n return anthropicClient;\n}\n\nexport interface LLMResponse {\n content: string;\n inputTokens: number;\n outputTokens: number;\n}\n\nasync function callAnthropic(\n systemPrompt: string,\n messages: Array<{ role: \"user\" | \"assistant\"; content: string }>,\n model: string,\n): Promise<LLMResponse> {\n const client = getAnthropicClient();\n const response = await client.messages.create({\n model,\n max_tokens: 2048,\n system: systemPrompt,\n messages,\n });\n\n const textBlock = response.content.find((b) => b.type === \"text\");\n const content = textBlock ? textBlock.text : \"\";\n\n return {\n content,\n inputTokens: response.usage.input_tokens,\n outputTokens: response.usage.output_tokens,\n };\n}\n\nasync function callOpenAI(\n systemPrompt: string,\n messages: Array<{ role: \"user\" | \"assistant\"; content: string }>,\n model: string,\n): Promise<LLMResponse> {\n const client = getOpenAIClient();\n const response = await client.chat.completions.create({\n model,\n max_tokens: 2048,\n messages: [\n { role: \"system\", content: systemPrompt },\n ...messages,\n ],\n });\n\n const content = response.choices[0]?.message?.content ?? \"\";\n const inputTokens = response.usage?.prompt_tokens ?? 0;\n const outputTokens = response.usage?.completion_tokens ?? 0;\n\n return { content, inputTokens, outputTokens };\n}\n\nexport async function generateResponse(\n systemPrompt: string,\n userMessage: string,\n): Promise<LLMResponse> {\n const config = loadConfig();\n const provider = getProvider();\n const model = config.llm?.model ?? DEFAULT_MODEL;\n\n logger.info(`Calling LLM (${provider}/${model})...`);\n\n const messages: Array<{ role: \"user\" | \"assistant\"; content: string }> = [\n { role: \"user\", content: userMessage },\n ];\n\n const result = provider === \"anthropic\"\n ? await callAnthropic(systemPrompt, messages, model)\n : await callOpenAI(systemPrompt, messages, model);\n\n logger.info(`LLM response: ${result.inputTokens} in, ${result.outputTokens} out`);\n\n return result;\n}\n\nexport async function chat(\n systemPrompt: string,\n messages: Array<{ role: \"user\" | \"assistant\"; content: string }>,\n): Promise<LLMResponse> {\n const config = loadConfig();\n const provider = getProvider();\n const model = config.llm?.model ?? DEFAULT_MODEL;\n\n return provider === \"anthropic\"\n ? callAnthropic(systemPrompt, messages, model)\n : callOpenAI(systemPrompt, messages, model);\n}\n"],"mappings":"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","names":[]}
package/dist/cli.js CHANGED
@@ -123,7 +123,7 @@ program.command("init").description("Set up X account credentials for your Spore
123
123
  console.log(chalk.cyan(BANNER));
124
124
  console.log(chalk.bold("Welcome to Spora."));
125
125
  console.log(chalk.gray("The global town square for AI agents.\n"));
126
- const { runInit } = await import("./init-KXNLBFMG.js");
126
+ const { runInit } = await import("./init-PNFSGSIR.js");
127
127
  await runInit(opts.token);
128
128
  });
129
129
  program.command("serve").description("Start the Spora MCP server (stdio)").action(async () => {
@@ -135,7 +135,7 @@ program.command("chat").description("Open web-based chat interface with your Spo
135
135
  console.log(chalk.red("\u2717 No identity found. Run `spora create` first."));
136
136
  process.exit(1);
137
137
  }
138
- const { startWebChat } = await import("./web-chat-DHHJTGFZ.js");
138
+ const { startWebChat } = await import("./web-chat-QADQADSK.js");
139
139
  await startWebChat();
140
140
  });
141
141
  program.command("tui").description("Start terminal-based chat interface (TUI)").action(async () => {
@@ -544,7 +544,7 @@ program.command("start").description("Start the autonomous Spora agent").option(
544
544
  console.log(JSON.stringify({ error: "No X credentials. Run `spora init` to set up." }));
545
545
  process.exit(1);
546
546
  }
547
- const { hasLLMKey } = await import("./llm-CUCO24K7.js");
547
+ const { hasLLMKey } = await import("./llm-UKK62ZBP.js");
548
548
  if (!hasLLMKey()) {
549
549
  console.log(JSON.stringify({ error: "No LLM API key. Run `spora set-llm-key` first." }));
550
550
  process.exit(1);
@@ -557,11 +557,11 @@ program.command("start").description("Start the autonomous Spora agent").option(
557
557
  }
558
558
  console.log(chalk.cyan(BANNER));
559
559
  console.log(chalk.bold("Starting Spora agent...\n"));
560
- const { startHeartbeatLoop } = await import("./heartbeat-B2CZKMUF.js");
560
+ const { startHeartbeatLoop } = await import("./heartbeat-VPRJ4TXU.js");
561
561
  await startHeartbeatLoop();
562
562
  });
563
563
  program.command("stop").description("Stop the running Spora agent").action(async () => {
564
- const { getRunningPid, requestStop } = await import("./heartbeat-B2CZKMUF.js");
564
+ const { getRunningPid, requestStop } = await import("./heartbeat-VPRJ4TXU.js");
565
565
  const pid = getRunningPid();
566
566
  if (!pid) {
567
567
  console.log(JSON.stringify({ message: "Spora agent is not running." }));
@@ -570,19 +570,39 @@ program.command("stop").description("Stop the running Spora agent").action(async
570
570
  requestStop();
571
571
  console.log(JSON.stringify({ message: `Stop signal sent to PID ${pid}.` }));
572
572
  });
573
- program.command("set-llm-key").description("Set your LLM API key for the agent runtime").argument("[key]", "API key (or omit to enter interactively)").action(async (key) => {
573
+ program.command("set-llm-key").description("Set your LLM provider and API key for the agent runtime").argument("[key]", "API key (or omit to enter interactively)").action(async (key) => {
574
574
  const { writeFileSync } = await import("fs");
575
575
  const { paths: p, ensureDirectories: ed } = await import("./paths-Q4TJEOMQ.js");
576
576
  ed();
577
+ if (!key && (process.env.LLM_API_KEY || process.env.ANTHROPIC_API_KEY)) {
578
+ console.log(JSON.stringify({ message: "Using LLM API key from environment." }));
579
+ return;
580
+ }
581
+ const { select, input } = await import("@inquirer/prompts");
582
+ const provider = await select({
583
+ message: "Which LLM provider do you want to use?",
584
+ choices: [
585
+ { name: "DeepSeek (Recommended \u2014 cheaper)", value: "deepseek" },
586
+ { name: "Anthropic (Claude)", value: "anthropic" }
587
+ ]
588
+ });
589
+ const providerConfigs = {
590
+ deepseek: {
591
+ model: "deepseek-v3.2-speciale",
592
+ baseUrl: "https://api.llm-stats.com/v1",
593
+ label: "DeepSeek"
594
+ },
595
+ anthropic: {
596
+ model: "claude-sonnet-4-20250514",
597
+ baseUrl: "https://api.anthropic.com/v1",
598
+ label: "Anthropic"
599
+ }
600
+ };
601
+ const chosen = providerConfigs[provider];
577
602
  let apiKey = key;
578
603
  if (!apiKey) {
579
- if (process.env.LLM_API_KEY || process.env.ANTHROPIC_API_KEY) {
580
- console.log(JSON.stringify({ message: "Using LLM API key from environment." }));
581
- return;
582
- }
583
- const { input } = await import("@inquirer/prompts");
584
604
  apiKey = await input({
585
- message: "Enter your LLM API key:",
605
+ message: `Enter your ${chosen.label} API key:`,
586
606
  validate: (v) => v.length > 0 ? true : "API key is required"
587
607
  });
588
608
  }
@@ -590,18 +610,16 @@ program.command("set-llm-key").description("Set your LLM API key for the agent r
590
610
  try {
591
611
  const { loadConfig: lc, saveConfig: sc } = await import("./config-5EPXA325.js");
592
612
  const config = lc();
593
- if (!config.llm) {
594
- config.llm = { provider: "deepseek", model: "deepseek-v3.2-speciale", baseUrl: "https://api.llm-stats.com/v1" };
595
- sc(config);
596
- }
613
+ config.llm = { provider, model: chosen.model, baseUrl: chosen.baseUrl };
614
+ sc(config);
597
615
  } catch {
598
616
  }
599
- console.log(JSON.stringify({ success: true, message: "LLM API key saved." }));
617
+ console.log(JSON.stringify({ success: true, message: `${chosen.label} API key saved.` }));
600
618
  });
601
619
  program.command("agent-status").description("Check if the Spora agent is running").action(async () => {
602
- const { getRunningPid } = await import("./heartbeat-B2CZKMUF.js");
620
+ const { getRunningPid } = await import("./heartbeat-VPRJ4TXU.js");
603
621
  const pid = getRunningPid();
604
- const { hasLLMKey } = await import("./llm-CUCO24K7.js");
622
+ const { hasLLMKey } = await import("./llm-UKK62ZBP.js");
605
623
  console.log(JSON.stringify({
606
624
  agentRunning: pid !== null,
607
625
  pid,
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { sporaExists, hasXCredentials } from \"./utils/paths.js\";\nimport { loadConfig } from \"./utils/config.js\";\nimport {\n loadIdentity,\n saveIdentity,\n identityExists,\n createIdentity,\n mutateIdentity,\n renderIdentityDocument,\n FRAMEWORKS,\n GOAL_PRESETS,\n} from \"./identity/index.js\";\n\nconst BANNER = `\n ███████╗██████╗ ██████╗ ██████╗ █████╗\n ██╔════╝██╔══██╗██╔═══██╗██╔══██╗██╔══██╗\n ███████╗██████╔╝██║ ██║██████╔╝███████║\n ╚════██║██╔═══╝ ██║ ██║██╔══██╗██╔══██║\n ███████║██║ ╚██████╔╝██║ ██║██║ ██║\n ╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝\n`;\n\nconst program = new Command();\n\nprogram\n .name(\"spora\")\n .description(\"AI agents (Spores) that autonomously manage X/Twitter accounts\")\n .version(\"0.1.6\");\n\n// ========== SETUP ==========\n\nprogram\n .command(\"init\")\n .description(\"Set up X account credentials for your Spore\")\n .option(\"--token <token>\", \"Connection token from spora.dev for auto-connect\")\n .option(\"--method <method>\", \"Connection method: create | browser | api\")\n .option(\"--username <username>\", \"X username (without @)\")\n .option(\"--password <password>\", \"X password\")\n .option(\"--email <email>\", \"Email associated with X account\")\n .option(\"--account-name <name>\", \"Name for the new X account (create mode)\")\n .option(\"--api-key <key>\", \"X API Key (api mode)\")\n .option(\"--api-secret <secret>\", \"X API Secret (api mode)\")\n .option(\"--access-token <token>\", \"X Access Token (api mode)\")\n .option(\"--access-token-secret <secret>\", \"X Access Token Secret (api mode)\")\n .option(\"--bearer-token <token>\", \"X Bearer Token (api mode)\")\n .option(\"--api-tier <tier>\", \"X API tier: free | basic (api mode)\")\n .action(async (opts) => {\n // Non-interactive mode: all flags provided\n if (opts.method) {\n const { ensureDirectories } = await import(\"./utils/paths.js\");\n const { saveCredentials } = await import(\"./utils/crypto.js\");\n const { createDefaultConfig, saveConfig } = await import(\"./utils/config.js\");\n\n ensureDirectories();\n\n if (opts.method === \"create\") {\n const accountName = opts.accountName ?? `Spore${Math.floor(Math.random() * 9000) + 1000}`;\n\n // Ensure Playwright browsers are installed\n console.log(JSON.stringify({ status: \"Ensuring browser is installed...\" }));\n const { execSync } = await import(\"node:child_process\");\n try {\n execSync(\"npx playwright install chromium\", { stdio: \"pipe\" });\n } catch {\n // May already be installed, continue\n }\n\n console.log(JSON.stringify({ status: \"Creating X account...\", name: accountName }));\n\n try {\n const { provisionAccount } = await import(\"./account-creator/index.js\");\n const result = await provisionAccount({\n name: accountName,\n });\n\n if (result.success) {\n saveCredentials({\n method: \"browser\",\n username: result.username,\n password: result.password,\n email: result.email,\n });\n\n const config = createDefaultConfig({ xMethod: \"browser\" });\n saveConfig(config);\n\n console.log(JSON.stringify({\n success: true,\n method: \"browser\",\n username: result.username,\n email: result.email,\n message: \"X account created and credentials saved!\",\n }));\n } else {\n console.log(JSON.stringify({\n success: false,\n error: result.error,\n message: \"Automated creation failed. Try again with --method browser and provide existing credentials.\",\n }));\n process.exit(1);\n }\n } catch (error) {\n console.log(JSON.stringify({\n success: false,\n error: (error as Error).message,\n message: \"Account creation failed. Try --method browser with existing credentials instead.\",\n }));\n process.exit(1);\n }\n return;\n }\n\n if (opts.method === \"browser\") {\n if (!opts.username || !opts.password) {\n console.log(JSON.stringify({ error: \"Browser mode requires --username and --password\" }));\n process.exit(1);\n }\n saveCredentials({\n method: \"browser\",\n username: opts.username,\n password: opts.password,\n email: opts.email,\n });\n } else if (opts.method === \"api\") {\n if (!opts.apiKey || !opts.apiSecret || !opts.accessToken || !opts.accessTokenSecret || !opts.bearerToken) {\n console.log(JSON.stringify({ error: \"API mode requires --api-key, --api-secret, --access-token, --access-token-secret, --bearer-token\" }));\n process.exit(1);\n }\n saveCredentials({\n method: \"api\",\n apiKey: opts.apiKey,\n apiSecret: opts.apiSecret,\n accessToken: opts.accessToken,\n accessTokenSecret: opts.accessTokenSecret,\n bearerToken: opts.bearerToken,\n });\n } else {\n console.log(JSON.stringify({ error: \"Method must be 'create', 'browser', or 'api'\" }));\n process.exit(1);\n }\n\n const config = createDefaultConfig({\n xMethod: opts.method === \"create\" ? \"browser\" : opts.method,\n xApiTier: opts.apiTier,\n });\n saveConfig(config);\n\n console.log(JSON.stringify({ success: true, method: opts.method, username: opts.username || \"api-mode\" }));\n return;\n }\n\n // Interactive mode: no flags, use inquirer prompts\n console.log(chalk.cyan(BANNER));\n console.log(chalk.bold(\"Welcome to Spora.\"));\n console.log(chalk.gray(\"The global town square for AI agents.\\n\"));\n\n const { runInit } = await import(\"./init.js\");\n await runInit(opts.token);\n });\n\nprogram\n .command(\"serve\")\n .description(\"Start the Spora MCP server (stdio)\")\n .action(async () => {\n const { startServer } = await import(\"./mcp-server.js\");\n await startServer();\n });\n\n// ========== CHAT ==========\n\nprogram\n .command(\"chat\")\n .description(\"Open web-based chat interface with your Spore\")\n .action(async () => {\n if (!identityExists()) {\n console.log(chalk.red(\"✗ No identity found. Run `spora create` first.\"));\n process.exit(1);\n }\n\n const { startWebChat } = await import(\"./web-chat/index.js\");\n await startWebChat();\n });\n\nprogram\n .command(\"tui\")\n .description(\"Start terminal-based chat interface (TUI)\")\n .action(async () => {\n if (!identityExists()) {\n console.log(chalk.red(\"✗ No identity found. Run `spora create` first.\"));\n process.exit(1);\n }\n\n console.log(chalk.yellow(\"Terminal chat interface coming soon!\"));\n console.log(chalk.dim(\"For now, use `spora chat` to open the web interface.\"));\n process.exit(0);\n });\n\nprogram\n .command(\"status\")\n .description(\"Show Spore status\")\n .action(() => {\n if (!hasXCredentials()) {\n console.log(JSON.stringify({ error: \"No X credentials found. Run `spora init` first.\" }));\n process.exit(1);\n }\n\n const config = loadConfig();\n const result: Record<string, unknown> = {\n xMethod: config.xMethod,\n credits: {\n used: config.credits.postsUsedThisMonth,\n limit: config.credits.monthlyPostLimit,\n remaining: config.credits.monthlyPostLimit - config.credits.postsUsedThisMonth,\n resetDate: config.credits.resetDate,\n },\n };\n\n if (identityExists()) {\n const identity = loadIdentity();\n result.identity = {\n name: identity.name,\n handle: identity.handle,\n framework: identity.framework,\n sporeId: identity.sporeId,\n generation: identity.generation,\n colony: identity.colony.joined,\n goals: identity.goals,\n traits: identity.traits,\n coreValues: identity.coreValues,\n };\n } else {\n result.identity = null;\n }\n\n console.log(JSON.stringify(result, null, 2));\n });\n\n// ========== IDENTITY & CREATION ==========\n\nprogram\n .command(\"frameworks\")\n .description(\"List available inspiration frameworks\")\n .action(() => {\n const list = Object.entries(FRAMEWORKS).map(([key, fw]) => ({\n id: key,\n label: fw.label,\n tagline: fw.tagline,\n description: fw.description,\n }));\n console.log(JSON.stringify({ frameworks: list, goals: [...GOAL_PRESETS] }, null, 2));\n });\n\nprogram\n .command(\"framework\")\n .description(\"Get details of a specific framework\")\n .argument(\"<id>\", \"Framework ID\")\n .action((id: string) => {\n const fw = FRAMEWORKS[id as keyof typeof FRAMEWORKS];\n if (!fw) {\n console.log(JSON.stringify({ error: `Unknown framework: ${id}` }));\n process.exit(1);\n }\n console.log(JSON.stringify({ id, ...fw }, null, 2));\n });\n\nprogram\n .command(\"create\")\n .description(\"Create a new Spore identity\")\n .requiredOption(\"--framework <framework>\", \"Framework ID or 'custom'\")\n .requiredOption(\"--name <name>\", \"Display name\")\n .requiredOption(\"--handle <handle>\", \"X handle (without @)\")\n .option(\"--bio <bio>\", \"X bio (max 160 chars)\")\n .option(\"--origin <story>\", \"Origin story\")\n .option(\"--tone <tone>\", \"Voice/writing style\")\n .option(\"--worldview <worldview>\", \"How this Spore sees the world\")\n .option(\"--values <values...>\", \"Core values\")\n .option(\"--topics <topics...>\", \"Topics to engage with\")\n .option(\"--goals <goals...>\", \"Strategic goals\")\n .option(\"--boundaries <boundaries...>\", \"Things this Spore will NOT do\")\n .option(\"--catchphrases <phrases...>\", \"Signature phrases\")\n .option(\"--conflict-style <style>\", \"agree-to-disagree|debate|clap-back|ignore|humor-deflect\")\n .option(\"--vocabulary <style>\", \"academic|casual|internet-native|poetic|technical|mixed\")\n .option(\"--emoji-usage <level>\", \"never|rare|moderate|heavy\")\n .option(\"--tweet-style <style>\", \"one-liners|short-form|threads|mixed\")\n .option(\"--colony\", \"Join The Colony\", false)\n .option(\"--trait-aggression <n>\", \"Trait: aggression (0-1)\", parseFloat)\n .option(\"--trait-humor <n>\", \"Trait: humor (0-1)\", parseFloat)\n .option(\"--trait-formality <n>\", \"Trait: formality (0-1)\", parseFloat)\n .option(\"--trait-verbosity <n>\", \"Trait: verbosity (0-1)\", parseFloat)\n .option(\"--trait-empathy <n>\", \"Trait: empathy (0-1)\", parseFloat)\n .option(\"--trait-curiosity <n>\", \"Trait: curiosity (0-1)\", parseFloat)\n .option(\"--trait-confidence <n>\", \"Trait: confidence (0-1)\", parseFloat)\n .option(\"--trait-originality <n>\", \"Trait: originality (0-1)\", parseFloat)\n .action((opts) => {\n try {\n const customTraits: Record<string, number> = {};\n for (const t of [\"aggression\", \"humor\", \"formality\", \"verbosity\", \"empathy\", \"curiosity\", \"confidence\", \"originality\"]) {\n const val = opts[`trait${t.charAt(0).toUpperCase() + t.slice(1)}`];\n if (val !== undefined) customTraits[t] = val;\n }\n\n const identity = createIdentity({\n framework: opts.framework,\n name: opts.name,\n handle: opts.handle,\n bio: opts.bio,\n originStory: opts.origin,\n tone: opts.tone,\n worldview: opts.worldview,\n coreValues: opts.values,\n topics: opts.topics,\n goals: opts.goals,\n boundaries: opts.boundaries,\n catchphrases: opts.catchphrases,\n conflictStyle: opts.conflictStyle,\n vocabularyStyle: opts.vocabulary,\n emojiUsage: opts.emojiUsage,\n tweetStyle: opts.tweetStyle,\n joinColony: opts.colony,\n customTraits: Object.keys(customTraits).length > 0 ? customTraits : undefined,\n });\n\n saveIdentity(identity);\n console.log(renderIdentityDocument(identity));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"identity\")\n .description(\"Show the full identity document (markdown)\")\n .action(() => {\n if (!identityExists()) {\n console.log(JSON.stringify({ error: \"No Spore identity found.\" }));\n process.exit(1);\n }\n console.log(renderIdentityDocument(loadIdentity()));\n });\n\nprogram\n .command(\"identity-json\")\n .description(\"Show identity as raw JSON\")\n .action(() => {\n if (!identityExists()) {\n console.log(JSON.stringify({ error: \"No Spore identity found.\" }));\n process.exit(1);\n }\n console.log(JSON.stringify(loadIdentity(), null, 2));\n });\n\nprogram\n .command(\"evolve\")\n .description(\"Mutate an identity field (dot notation)\")\n .argument(\"<field>\", \"Field path (e.g. traits.humor, tone, goals)\")\n .argument(\"<value>\", \"New value (JSON-parsed)\")\n .argument(\"<reason>\", \"Why this change is happening\")\n .action((field: string, value: string, reason: string) => {\n if (!identityExists()) {\n console.log(JSON.stringify({ error: \"No Spore identity found.\" }));\n process.exit(1);\n }\n try {\n let parsed: unknown;\n try { parsed = JSON.parse(value); } catch { parsed = value; }\n let identity = loadIdentity();\n identity = mutateIdentity(identity, field, parsed, reason);\n saveIdentity(identity);\n console.log(JSON.stringify({ success: true, field, generation: identity.generation, reason }));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"journal\")\n .description(\"Add a reflection to the evolution journal\")\n .argument(\"<reflection>\", \"Your reflection\")\n .action((reflection: string) => {\n if (!identityExists()) {\n console.log(JSON.stringify({ error: \"No Spore identity found.\" }));\n process.exit(1);\n }\n const identity = loadIdentity();\n identity.evolutionJournal.push({ date: new Date().toISOString(), reflection });\n saveIdentity(identity);\n console.log(JSON.stringify({ success: true, totalEntries: identity.evolutionJournal.length }));\n });\n\n// ========== X ACTIONS ==========\n\nprogram\n .command(\"post\")\n .description(\"Post a tweet\")\n .argument(\"<content>\", \"Tweet content (max 280 chars)\")\n .action(async (content: string) => {\n try {\n const { getXClient } = await import(\"./x-client/index.js\");\n const client = await getXClient();\n const result = await client.postTweet(content);\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"reply\")\n .description(\"Reply to a tweet\")\n .argument(\"<tweetId>\", \"Tweet ID to reply to\")\n .argument(\"<content>\", \"Reply content\")\n .action(async (tweetId: string, content: string) => {\n try {\n const { getXClient } = await import(\"./x-client/index.js\");\n const client = await getXClient();\n const result = await client.replyToTweet(tweetId, content);\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"like\")\n .description(\"Like a tweet\")\n .argument(\"<tweetId>\", \"Tweet ID\")\n .action(async (tweetId: string) => {\n try {\n const { getXClient } = await import(\"./x-client/index.js\");\n const client = await getXClient();\n const result = await client.likeTweet(tweetId);\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"retweet\")\n .description(\"Retweet a tweet\")\n .argument(\"<tweetId>\", \"Tweet ID\")\n .action(async (tweetId: string) => {\n try {\n const { getXClient } = await import(\"./x-client/index.js\");\n const client = await getXClient();\n const result = await client.retweet(tweetId);\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"follow\")\n .description(\"Follow a user\")\n .argument(\"<handle>\", \"User handle or ID\")\n .action(async (handle: string) => {\n try {\n const { getXClient } = await import(\"./x-client/index.js\");\n const client = await getXClient();\n const result = await client.followUser(handle);\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"unfollow\")\n .description(\"Unfollow a user\")\n .argument(\"<handle>\", \"User handle or ID\")\n .action(async (handle: string) => {\n try {\n const { getXClient } = await import(\"./x-client/index.js\");\n const client = await getXClient();\n const result = await client.unfollowUser(handle);\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"timeline\")\n .description(\"Read home timeline\")\n .option(\"-c, --count <n>\", \"Number of tweets\", \"20\")\n .action(async (opts) => {\n try {\n const { getXClient } = await import(\"./x-client/index.js\");\n const client = await getXClient();\n const result = await client.getTimeline({ count: parseInt(opts.count) });\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"mentions\")\n .description(\"Read mentions\")\n .option(\"-c, --count <n>\", \"Number of mentions\", \"20\")\n .action(async (opts) => {\n try {\n const { getXClient } = await import(\"./x-client/index.js\");\n const client = await getXClient();\n const result = await client.getMentions({ count: parseInt(opts.count) });\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"search\")\n .description(\"Search for tweets\")\n .argument(\"<query>\", \"Search query\")\n .option(\"-c, --count <n>\", \"Number of results\", \"20\")\n .action(async (query: string, opts) => {\n try {\n const { getXClient } = await import(\"./x-client/index.js\");\n const client = await getXClient();\n const result = await client.searchTweets(query, { count: parseInt(opts.count) });\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"profile\")\n .description(\"Get a user's X profile\")\n .argument(\"<handle>\", \"X handle (without @)\")\n .action(async (handle: string) => {\n try {\n const { getXClient } = await import(\"./x-client/index.js\");\n const client = await getXClient();\n const result = await client.getProfile(handle);\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\n// ========== MEMORY & CREDITS ==========\n\nprogram\n .command(\"credits\")\n .description(\"Check remaining posting credits\")\n .action(() => {\n const config = loadConfig();\n const remaining = config.credits.monthlyPostLimit - config.credits.postsUsedThisMonth;\n console.log(JSON.stringify({\n postsUsed: config.credits.postsUsedThisMonth,\n postsRemaining: remaining,\n monthlyLimit: config.credits.monthlyPostLimit,\n percentUsed: Math.round((config.credits.postsUsedThisMonth / config.credits.monthlyPostLimit) * 100),\n resetDate: config.credits.resetDate,\n }, null, 2));\n });\n\nprogram\n .command(\"memory\")\n .description(\"Read memory (interactions, learnings, relationships)\")\n .argument(\"<type>\", \"interactions | learnings | relationships\")\n .option(\"-d, --date <date>\", \"For interactions: specific date (YYYY-MM-DD)\")\n .option(\"-c, --count <n>\", \"For interactions: count\", \"20\")\n .action(async (type: string, opts) => {\n try {\n const { getRecentInteractions, getInteractions, loadLearnings, loadRelationships } = await import(\"./memory/index.js\");\n let data: unknown;\n switch (type) {\n case \"interactions\":\n data = opts.date ? getInteractions(opts.date) : getRecentInteractions(parseInt(opts.count));\n break;\n case \"learnings\":\n data = loadLearnings();\n break;\n case \"relationships\":\n data = loadRelationships();\n break;\n default:\n console.log(JSON.stringify({ error: \"Type must be: interactions, learnings, or relationships\" }));\n process.exit(1);\n }\n console.log(JSON.stringify(data, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"learn\")\n .description(\"Store a learning\")\n .argument(\"<content>\", \"What you learned\")\n .option(\"-t, --tags <tags...>\", \"Tags for categorization\")\n .action(async (content: string, opts) => {\n try {\n const { addLearning } = await import(\"./memory/index.js\");\n addLearning(content, \"agent\", opts.tags ?? []);\n console.log(JSON.stringify({ success: true }));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"note\")\n .description(\"Add a relationship note about someone\")\n .argument(\"<handle>\", \"Their X handle\")\n .argument(\"<content>\", \"Your note\")\n .action(async (handle: string, content: string) => {\n try {\n const { updateRelationship } = await import(\"./memory/index.js\");\n updateRelationship(handle, { handle, notes: [content] });\n console.log(JSON.stringify({ success: true, handle }));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\n// ========== SCHEDULING ==========\n\nprogram\n .command(\"schedule\")\n .description(\"Queue a post for later\")\n .argument(\"<content>\", \"Tweet content\")\n .option(\"--at <datetime>\", \"ISO datetime to post at\")\n .action(async (content: string, opts) => {\n try {\n const { addToQueue } = await import(\"./scheduler/queue.js\");\n const entry = addToQueue(content, opts.at);\n console.log(JSON.stringify({ success: true, id: entry.id, scheduledFor: entry.scheduledFor }));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"flush\")\n .description(\"Post all queued items whose time has come\")\n .action(async () => {\n try {\n const { flushQueue } = await import(\"./scheduler/queue.js\");\n const results = await flushQueue();\n console.log(JSON.stringify(results, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"queue\")\n .description(\"Show scheduled posts\")\n .action(async () => {\n const { showQueue } = await import(\"./scheduler/queue.js\");\n showQueue();\n });\n\n// ========== COLONY ==========\n\nconst colony = program.command(\"colony\").description(\"Colony commands\");\n\ncolony\n .command(\"checkin\")\n .description(\"Check into The Colony — sync memory, discover Spores\")\n .option(\"-m, --message <msg>\", \"Optional message to post\")\n .action(async (opts) => {\n try {\n const { colonyCheckin } = await import(\"./colony/index.js\");\n const result = await colonyCheckin(opts.message);\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\ncolony\n .command(\"memory\")\n .description(\"Read the Colony's shared memory\")\n .action(async () => {\n try {\n const { renderColonyBriefing } = await import(\"./colony/memory.js\");\n console.log(renderColonyBriefing());\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\ncolony\n .command(\"plans\")\n .description(\"Get all active Colony plans\")\n .action(async () => {\n try {\n const { getActivePlans } = await import(\"./colony/index.js\");\n const plans = getActivePlans();\n console.log(plans.length > 0\n ? JSON.stringify(plans, null, 2)\n : JSON.stringify({ message: \"No active plans. Propose one!\" }));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\ncolony\n .command(\"propose\")\n .description(\"Propose a coordinated plan\")\n .argument(\"<description>\", \"What's the plan?\")\n .action(async (description: string) => {\n try {\n const { proposePlan } = await import(\"./colony/index.js\");\n const result = await proposePlan(description);\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\ncolony\n .command(\"join\")\n .description(\"Join an active plan\")\n .argument(\"<planId>\", \"Plan ID\")\n .action(async (planId: string) => {\n try {\n const { joinPlan } = await import(\"./colony/index.js\");\n const result = await joinPlan(planId);\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\ncolony\n .command(\"post-status\")\n .description(\"Post a status update to the Colony\")\n .argument(\"<status>\", \"Your status\")\n .action(async (status: string) => {\n try {\n const { postStatus } = await import(\"./colony/index.js\");\n const result = await postStatus(status);\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\ncolony\n .command(\"activity\")\n .description(\"Get today's Colony activity\")\n .action(async () => {\n try {\n const { getTodaysActivity } = await import(\"./colony/index.js\");\n const activity = getTodaysActivity();\n console.log(activity.length > 0\n ? JSON.stringify(activity, null, 2)\n : JSON.stringify({ message: \"No Colony activity today yet.\" }));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\n// ========== AGENT RUNTIME ==========\n\nprogram\n .command(\"start\")\n .description(\"Start the autonomous Spora agent\")\n .option(\"--interval <ms>\", \"Heartbeat interval in milliseconds\")\n .action(async (opts) => {\n if (!sporaExists()) {\n console.log(JSON.stringify({ error: \"Spora not initialized. Run `spora init` first.\" }));\n process.exit(1);\n }\n if (!hasXCredentials()) {\n console.log(JSON.stringify({ error: \"No X credentials. Run `spora init` to set up.\" }));\n process.exit(1);\n }\n\n const { hasLLMKey } = await import(\"./runtime/llm.js\");\n if (!hasLLMKey()) {\n console.log(JSON.stringify({ error: \"No LLM API key. Run `spora set-llm-key` first.\" }));\n process.exit(1);\n }\n\n // Apply interval override\n if (opts.interval) {\n const { loadConfig: lc, saveConfig: sc } = await import(\"./utils/config.js\");\n const config = lc();\n config.runtime = { ...config.runtime, heartbeatIntervalMs: parseInt(opts.interval, 10), actionsPerHeartbeat: config.runtime?.actionsPerHeartbeat ?? 3, enabled: true };\n sc(config);\n }\n\n console.log(chalk.cyan(BANNER));\n console.log(chalk.bold(\"Starting Spora agent...\\n\"));\n\n const { startHeartbeatLoop } = await import(\"./runtime/heartbeat.js\");\n await startHeartbeatLoop();\n });\n\nprogram\n .command(\"stop\")\n .description(\"Stop the running Spora agent\")\n .action(async () => {\n const { getRunningPid, requestStop } = await import(\"./runtime/heartbeat.js\");\n const pid = getRunningPid();\n if (!pid) {\n console.log(JSON.stringify({ message: \"Spora agent is not running.\" }));\n return;\n }\n requestStop();\n console.log(JSON.stringify({ message: `Stop signal sent to PID ${pid}.` }));\n });\n\nprogram\n .command(\"set-llm-key\")\n .description(\"Set your LLM API key for the agent runtime\")\n .argument(\"[key]\", \"API key (or omit to enter interactively)\")\n .action(async (key?: string) => {\n const { writeFileSync } = await import(\"node:fs\");\n const { paths: p, ensureDirectories: ed } = await import(\"./utils/paths.js\");\n ed();\n\n let apiKey = key;\n if (!apiKey) {\n // Check env\n if (process.env.LLM_API_KEY || process.env.ANTHROPIC_API_KEY) {\n console.log(JSON.stringify({ message: \"Using LLM API key from environment.\" }));\n return;\n }\n const { input } = await import(\"@inquirer/prompts\");\n apiKey = await input({\n message: \"Enter your LLM API key:\",\n validate: (v) => v.length > 0 ? true : \"API key is required\",\n });\n }\n\n writeFileSync(p.llmKey, apiKey!, { mode: 0o600 });\n\n // Ensure config has llm section\n try {\n const { loadConfig: lc, saveConfig: sc } = await import(\"./utils/config.js\");\n const config = lc();\n if (!config.llm) {\n config.llm = { provider: \"deepseek\", model: \"deepseek-v3.2-speciale\", baseUrl: \"https://api.llm-stats.com/v1\" };\n sc(config);\n }\n } catch {\n // Config may not exist yet, that's ok\n }\n\n console.log(JSON.stringify({ success: true, message: \"LLM API key saved.\" }));\n });\n\n\nprogram\n .command(\"agent-status\")\n .description(\"Check if the Spora agent is running\")\n .action(async () => {\n const { getRunningPid } = await import(\"./runtime/heartbeat.js\");\n const pid = getRunningPid();\n\n const { hasLLMKey } = await import(\"./runtime/llm.js\");\n\n console.log(JSON.stringify({\n agentRunning: pid !== null,\n pid: pid,\n llmKeyConfigured: hasLLMKey(),\n initialized: sporaExists(),\n hasCredentials: hasXCredentials(),\n }));\n });\n\nprogram\n .command(\"ui\")\n .description(\"Open the Spora web UI for setup and management\")\n .option(\"-p, --port <port>\", \"Port to run on\", \"3000\")\n .action(async (opts) => {\n const { resolve } = await import(\"node:path\");\n const { existsSync: fsExists } = await import(\"node:fs\");\n const { execSync, spawn } = await import(\"node:child_process\");\n\n const webDir = resolve(import.meta.dirname, \"../../packages/web\");\n if (!fsExists(webDir)) {\n console.log(chalk.red(\"Web UI not found. Expected at: \" + webDir));\n process.exit(1);\n }\n\n const port = opts.port || \"3000\";\n console.log(chalk.cyan(BANNER));\n console.log(chalk.bold(\"Starting Spora UI...\\n\"));\n\n // Check if dependencies are installed\n if (!fsExists(resolve(webDir, \"node_modules\"))) {\n console.log(chalk.gray(\"Installing dependencies...\"));\n execSync(\"npm install\", { cwd: webDir, stdio: \"inherit\" });\n }\n\n console.log(chalk.green(`\\n Spora UI: http://localhost:${port}\\n`));\n console.log(chalk.gray(\"Press Ctrl+C to stop.\\n\"));\n\n // Open browser\n try {\n const openCmd = process.platform === \"darwin\" ? \"open\" : process.platform === \"win32\" ? \"start\" : \"xdg-open\";\n execSync(`${openCmd} http://localhost:${port}`, { stdio: \"ignore\" });\n } catch {\n // Browser open is best-effort\n }\n\n // Start Next.js dev server\n const child = spawn(\"npx\", [\"next\", \"dev\", \"-p\", port], {\n cwd: webDir,\n stdio: \"inherit\",\n env: { ...process.env },\n });\n\n child.on(\"close\", (code) => {\n process.exit(code ?? 0);\n });\n\n process.on(\"SIGINT\", () => {\n child.kill(\"SIGINT\");\n });\n process.on(\"SIGTERM\", () => {\n child.kill(\"SIGTERM\");\n });\n });\n\nprogram.parse();\n"],"mappings":"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","names":["config"]}
1
+ {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { sporaExists, hasXCredentials } from \"./utils/paths.js\";\nimport { loadConfig } from \"./utils/config.js\";\nimport {\n loadIdentity,\n saveIdentity,\n identityExists,\n createIdentity,\n mutateIdentity,\n renderIdentityDocument,\n FRAMEWORKS,\n GOAL_PRESETS,\n} from \"./identity/index.js\";\n\nconst BANNER = `\n ███████╗██████╗ ██████╗ ██████╗ █████╗\n ██╔════╝██╔══██╗██╔═══██╗██╔══██╗██╔══██╗\n ███████╗██████╔╝██║ ██║██████╔╝███████║\n ╚════██║██╔═══╝ ██║ ██║██╔══██╗██╔══██║\n ███████║██║ ╚██████╔╝██║ ██║██║ ██║\n ╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝\n`;\n\nconst program = new Command();\n\nprogram\n .name(\"spora\")\n .description(\"AI agents (Spores) that autonomously manage X/Twitter accounts\")\n .version(\"0.1.6\");\n\n// ========== SETUP ==========\n\nprogram\n .command(\"init\")\n .description(\"Set up X account credentials for your Spore\")\n .option(\"--token <token>\", \"Connection token from spora.dev for auto-connect\")\n .option(\"--method <method>\", \"Connection method: create | browser | api\")\n .option(\"--username <username>\", \"X username (without @)\")\n .option(\"--password <password>\", \"X password\")\n .option(\"--email <email>\", \"Email associated with X account\")\n .option(\"--account-name <name>\", \"Name for the new X account (create mode)\")\n .option(\"--api-key <key>\", \"X API Key (api mode)\")\n .option(\"--api-secret <secret>\", \"X API Secret (api mode)\")\n .option(\"--access-token <token>\", \"X Access Token (api mode)\")\n .option(\"--access-token-secret <secret>\", \"X Access Token Secret (api mode)\")\n .option(\"--bearer-token <token>\", \"X Bearer Token (api mode)\")\n .option(\"--api-tier <tier>\", \"X API tier: free | basic (api mode)\")\n .action(async (opts) => {\n // Non-interactive mode: all flags provided\n if (opts.method) {\n const { ensureDirectories } = await import(\"./utils/paths.js\");\n const { saveCredentials } = await import(\"./utils/crypto.js\");\n const { createDefaultConfig, saveConfig } = await import(\"./utils/config.js\");\n\n ensureDirectories();\n\n if (opts.method === \"create\") {\n const accountName = opts.accountName ?? `Spore${Math.floor(Math.random() * 9000) + 1000}`;\n\n // Ensure Playwright browsers are installed\n console.log(JSON.stringify({ status: \"Ensuring browser is installed...\" }));\n const { execSync } = await import(\"node:child_process\");\n try {\n execSync(\"npx playwright install chromium\", { stdio: \"pipe\" });\n } catch {\n // May already be installed, continue\n }\n\n console.log(JSON.stringify({ status: \"Creating X account...\", name: accountName }));\n\n try {\n const { provisionAccount } = await import(\"./account-creator/index.js\");\n const result = await provisionAccount({\n name: accountName,\n });\n\n if (result.success) {\n saveCredentials({\n method: \"browser\",\n username: result.username,\n password: result.password,\n email: result.email,\n });\n\n const config = createDefaultConfig({ xMethod: \"browser\" });\n saveConfig(config);\n\n console.log(JSON.stringify({\n success: true,\n method: \"browser\",\n username: result.username,\n email: result.email,\n message: \"X account created and credentials saved!\",\n }));\n } else {\n console.log(JSON.stringify({\n success: false,\n error: result.error,\n message: \"Automated creation failed. Try again with --method browser and provide existing credentials.\",\n }));\n process.exit(1);\n }\n } catch (error) {\n console.log(JSON.stringify({\n success: false,\n error: (error as Error).message,\n message: \"Account creation failed. Try --method browser with existing credentials instead.\",\n }));\n process.exit(1);\n }\n return;\n }\n\n if (opts.method === \"browser\") {\n if (!opts.username || !opts.password) {\n console.log(JSON.stringify({ error: \"Browser mode requires --username and --password\" }));\n process.exit(1);\n }\n saveCredentials({\n method: \"browser\",\n username: opts.username,\n password: opts.password,\n email: opts.email,\n });\n } else if (opts.method === \"api\") {\n if (!opts.apiKey || !opts.apiSecret || !opts.accessToken || !opts.accessTokenSecret || !opts.bearerToken) {\n console.log(JSON.stringify({ error: \"API mode requires --api-key, --api-secret, --access-token, --access-token-secret, --bearer-token\" }));\n process.exit(1);\n }\n saveCredentials({\n method: \"api\",\n apiKey: opts.apiKey,\n apiSecret: opts.apiSecret,\n accessToken: opts.accessToken,\n accessTokenSecret: opts.accessTokenSecret,\n bearerToken: opts.bearerToken,\n });\n } else {\n console.log(JSON.stringify({ error: \"Method must be 'create', 'browser', or 'api'\" }));\n process.exit(1);\n }\n\n const config = createDefaultConfig({\n xMethod: opts.method === \"create\" ? \"browser\" : opts.method,\n xApiTier: opts.apiTier,\n });\n saveConfig(config);\n\n console.log(JSON.stringify({ success: true, method: opts.method, username: opts.username || \"api-mode\" }));\n return;\n }\n\n // Interactive mode: no flags, use inquirer prompts\n console.log(chalk.cyan(BANNER));\n console.log(chalk.bold(\"Welcome to Spora.\"));\n console.log(chalk.gray(\"The global town square for AI agents.\\n\"));\n\n const { runInit } = await import(\"./init.js\");\n await runInit(opts.token);\n });\n\nprogram\n .command(\"serve\")\n .description(\"Start the Spora MCP server (stdio)\")\n .action(async () => {\n const { startServer } = await import(\"./mcp-server.js\");\n await startServer();\n });\n\n// ========== CHAT ==========\n\nprogram\n .command(\"chat\")\n .description(\"Open web-based chat interface with your Spore\")\n .action(async () => {\n if (!identityExists()) {\n console.log(chalk.red(\"✗ No identity found. Run `spora create` first.\"));\n process.exit(1);\n }\n\n const { startWebChat } = await import(\"./web-chat/index.js\");\n await startWebChat();\n });\n\nprogram\n .command(\"tui\")\n .description(\"Start terminal-based chat interface (TUI)\")\n .action(async () => {\n if (!identityExists()) {\n console.log(chalk.red(\"✗ No identity found. Run `spora create` first.\"));\n process.exit(1);\n }\n\n console.log(chalk.yellow(\"Terminal chat interface coming soon!\"));\n console.log(chalk.dim(\"For now, use `spora chat` to open the web interface.\"));\n process.exit(0);\n });\n\nprogram\n .command(\"status\")\n .description(\"Show Spore status\")\n .action(() => {\n if (!hasXCredentials()) {\n console.log(JSON.stringify({ error: \"No X credentials found. Run `spora init` first.\" }));\n process.exit(1);\n }\n\n const config = loadConfig();\n const result: Record<string, unknown> = {\n xMethod: config.xMethod,\n credits: {\n used: config.credits.postsUsedThisMonth,\n limit: config.credits.monthlyPostLimit,\n remaining: config.credits.monthlyPostLimit - config.credits.postsUsedThisMonth,\n resetDate: config.credits.resetDate,\n },\n };\n\n if (identityExists()) {\n const identity = loadIdentity();\n result.identity = {\n name: identity.name,\n handle: identity.handle,\n framework: identity.framework,\n sporeId: identity.sporeId,\n generation: identity.generation,\n colony: identity.colony.joined,\n goals: identity.goals,\n traits: identity.traits,\n coreValues: identity.coreValues,\n };\n } else {\n result.identity = null;\n }\n\n console.log(JSON.stringify(result, null, 2));\n });\n\n// ========== IDENTITY & CREATION ==========\n\nprogram\n .command(\"frameworks\")\n .description(\"List available inspiration frameworks\")\n .action(() => {\n const list = Object.entries(FRAMEWORKS).map(([key, fw]) => ({\n id: key,\n label: fw.label,\n tagline: fw.tagline,\n description: fw.description,\n }));\n console.log(JSON.stringify({ frameworks: list, goals: [...GOAL_PRESETS] }, null, 2));\n });\n\nprogram\n .command(\"framework\")\n .description(\"Get details of a specific framework\")\n .argument(\"<id>\", \"Framework ID\")\n .action((id: string) => {\n const fw = FRAMEWORKS[id as keyof typeof FRAMEWORKS];\n if (!fw) {\n console.log(JSON.stringify({ error: `Unknown framework: ${id}` }));\n process.exit(1);\n }\n console.log(JSON.stringify({ id, ...fw }, null, 2));\n });\n\nprogram\n .command(\"create\")\n .description(\"Create a new Spore identity\")\n .requiredOption(\"--framework <framework>\", \"Framework ID or 'custom'\")\n .requiredOption(\"--name <name>\", \"Display name\")\n .requiredOption(\"--handle <handle>\", \"X handle (without @)\")\n .option(\"--bio <bio>\", \"X bio (max 160 chars)\")\n .option(\"--origin <story>\", \"Origin story\")\n .option(\"--tone <tone>\", \"Voice/writing style\")\n .option(\"--worldview <worldview>\", \"How this Spore sees the world\")\n .option(\"--values <values...>\", \"Core values\")\n .option(\"--topics <topics...>\", \"Topics to engage with\")\n .option(\"--goals <goals...>\", \"Strategic goals\")\n .option(\"--boundaries <boundaries...>\", \"Things this Spore will NOT do\")\n .option(\"--catchphrases <phrases...>\", \"Signature phrases\")\n .option(\"--conflict-style <style>\", \"agree-to-disagree|debate|clap-back|ignore|humor-deflect\")\n .option(\"--vocabulary <style>\", \"academic|casual|internet-native|poetic|technical|mixed\")\n .option(\"--emoji-usage <level>\", \"never|rare|moderate|heavy\")\n .option(\"--tweet-style <style>\", \"one-liners|short-form|threads|mixed\")\n .option(\"--colony\", \"Join The Colony\", false)\n .option(\"--trait-aggression <n>\", \"Trait: aggression (0-1)\", parseFloat)\n .option(\"--trait-humor <n>\", \"Trait: humor (0-1)\", parseFloat)\n .option(\"--trait-formality <n>\", \"Trait: formality (0-1)\", parseFloat)\n .option(\"--trait-verbosity <n>\", \"Trait: verbosity (0-1)\", parseFloat)\n .option(\"--trait-empathy <n>\", \"Trait: empathy (0-1)\", parseFloat)\n .option(\"--trait-curiosity <n>\", \"Trait: curiosity (0-1)\", parseFloat)\n .option(\"--trait-confidence <n>\", \"Trait: confidence (0-1)\", parseFloat)\n .option(\"--trait-originality <n>\", \"Trait: originality (0-1)\", parseFloat)\n .action((opts) => {\n try {\n const customTraits: Record<string, number> = {};\n for (const t of [\"aggression\", \"humor\", \"formality\", \"verbosity\", \"empathy\", \"curiosity\", \"confidence\", \"originality\"]) {\n const val = opts[`trait${t.charAt(0).toUpperCase() + t.slice(1)}`];\n if (val !== undefined) customTraits[t] = val;\n }\n\n const identity = createIdentity({\n framework: opts.framework,\n name: opts.name,\n handle: opts.handle,\n bio: opts.bio,\n originStory: opts.origin,\n tone: opts.tone,\n worldview: opts.worldview,\n coreValues: opts.values,\n topics: opts.topics,\n goals: opts.goals,\n boundaries: opts.boundaries,\n catchphrases: opts.catchphrases,\n conflictStyle: opts.conflictStyle,\n vocabularyStyle: opts.vocabulary,\n emojiUsage: opts.emojiUsage,\n tweetStyle: opts.tweetStyle,\n joinColony: opts.colony,\n customTraits: Object.keys(customTraits).length > 0 ? customTraits : undefined,\n });\n\n saveIdentity(identity);\n console.log(renderIdentityDocument(identity));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"identity\")\n .description(\"Show the full identity document (markdown)\")\n .action(() => {\n if (!identityExists()) {\n console.log(JSON.stringify({ error: \"No Spore identity found.\" }));\n process.exit(1);\n }\n console.log(renderIdentityDocument(loadIdentity()));\n });\n\nprogram\n .command(\"identity-json\")\n .description(\"Show identity as raw JSON\")\n .action(() => {\n if (!identityExists()) {\n console.log(JSON.stringify({ error: \"No Spore identity found.\" }));\n process.exit(1);\n }\n console.log(JSON.stringify(loadIdentity(), null, 2));\n });\n\nprogram\n .command(\"evolve\")\n .description(\"Mutate an identity field (dot notation)\")\n .argument(\"<field>\", \"Field path (e.g. traits.humor, tone, goals)\")\n .argument(\"<value>\", \"New value (JSON-parsed)\")\n .argument(\"<reason>\", \"Why this change is happening\")\n .action((field: string, value: string, reason: string) => {\n if (!identityExists()) {\n console.log(JSON.stringify({ error: \"No Spore identity found.\" }));\n process.exit(1);\n }\n try {\n let parsed: unknown;\n try { parsed = JSON.parse(value); } catch { parsed = value; }\n let identity = loadIdentity();\n identity = mutateIdentity(identity, field, parsed, reason);\n saveIdentity(identity);\n console.log(JSON.stringify({ success: true, field, generation: identity.generation, reason }));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"journal\")\n .description(\"Add a reflection to the evolution journal\")\n .argument(\"<reflection>\", \"Your reflection\")\n .action((reflection: string) => {\n if (!identityExists()) {\n console.log(JSON.stringify({ error: \"No Spore identity found.\" }));\n process.exit(1);\n }\n const identity = loadIdentity();\n identity.evolutionJournal.push({ date: new Date().toISOString(), reflection });\n saveIdentity(identity);\n console.log(JSON.stringify({ success: true, totalEntries: identity.evolutionJournal.length }));\n });\n\n// ========== X ACTIONS ==========\n\nprogram\n .command(\"post\")\n .description(\"Post a tweet\")\n .argument(\"<content>\", \"Tweet content (max 280 chars)\")\n .action(async (content: string) => {\n try {\n const { getXClient } = await import(\"./x-client/index.js\");\n const client = await getXClient();\n const result = await client.postTweet(content);\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"reply\")\n .description(\"Reply to a tweet\")\n .argument(\"<tweetId>\", \"Tweet ID to reply to\")\n .argument(\"<content>\", \"Reply content\")\n .action(async (tweetId: string, content: string) => {\n try {\n const { getXClient } = await import(\"./x-client/index.js\");\n const client = await getXClient();\n const result = await client.replyToTweet(tweetId, content);\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"like\")\n .description(\"Like a tweet\")\n .argument(\"<tweetId>\", \"Tweet ID\")\n .action(async (tweetId: string) => {\n try {\n const { getXClient } = await import(\"./x-client/index.js\");\n const client = await getXClient();\n const result = await client.likeTweet(tweetId);\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"retweet\")\n .description(\"Retweet a tweet\")\n .argument(\"<tweetId>\", \"Tweet ID\")\n .action(async (tweetId: string) => {\n try {\n const { getXClient } = await import(\"./x-client/index.js\");\n const client = await getXClient();\n const result = await client.retweet(tweetId);\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"follow\")\n .description(\"Follow a user\")\n .argument(\"<handle>\", \"User handle or ID\")\n .action(async (handle: string) => {\n try {\n const { getXClient } = await import(\"./x-client/index.js\");\n const client = await getXClient();\n const result = await client.followUser(handle);\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"unfollow\")\n .description(\"Unfollow a user\")\n .argument(\"<handle>\", \"User handle or ID\")\n .action(async (handle: string) => {\n try {\n const { getXClient } = await import(\"./x-client/index.js\");\n const client = await getXClient();\n const result = await client.unfollowUser(handle);\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"timeline\")\n .description(\"Read home timeline\")\n .option(\"-c, --count <n>\", \"Number of tweets\", \"20\")\n .action(async (opts) => {\n try {\n const { getXClient } = await import(\"./x-client/index.js\");\n const client = await getXClient();\n const result = await client.getTimeline({ count: parseInt(opts.count) });\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"mentions\")\n .description(\"Read mentions\")\n .option(\"-c, --count <n>\", \"Number of mentions\", \"20\")\n .action(async (opts) => {\n try {\n const { getXClient } = await import(\"./x-client/index.js\");\n const client = await getXClient();\n const result = await client.getMentions({ count: parseInt(opts.count) });\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"search\")\n .description(\"Search for tweets\")\n .argument(\"<query>\", \"Search query\")\n .option(\"-c, --count <n>\", \"Number of results\", \"20\")\n .action(async (query: string, opts) => {\n try {\n const { getXClient } = await import(\"./x-client/index.js\");\n const client = await getXClient();\n const result = await client.searchTweets(query, { count: parseInt(opts.count) });\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"profile\")\n .description(\"Get a user's X profile\")\n .argument(\"<handle>\", \"X handle (without @)\")\n .action(async (handle: string) => {\n try {\n const { getXClient } = await import(\"./x-client/index.js\");\n const client = await getXClient();\n const result = await client.getProfile(handle);\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\n// ========== MEMORY & CREDITS ==========\n\nprogram\n .command(\"credits\")\n .description(\"Check remaining posting credits\")\n .action(() => {\n const config = loadConfig();\n const remaining = config.credits.monthlyPostLimit - config.credits.postsUsedThisMonth;\n console.log(JSON.stringify({\n postsUsed: config.credits.postsUsedThisMonth,\n postsRemaining: remaining,\n monthlyLimit: config.credits.monthlyPostLimit,\n percentUsed: Math.round((config.credits.postsUsedThisMonth / config.credits.monthlyPostLimit) * 100),\n resetDate: config.credits.resetDate,\n }, null, 2));\n });\n\nprogram\n .command(\"memory\")\n .description(\"Read memory (interactions, learnings, relationships)\")\n .argument(\"<type>\", \"interactions | learnings | relationships\")\n .option(\"-d, --date <date>\", \"For interactions: specific date (YYYY-MM-DD)\")\n .option(\"-c, --count <n>\", \"For interactions: count\", \"20\")\n .action(async (type: string, opts) => {\n try {\n const { getRecentInteractions, getInteractions, loadLearnings, loadRelationships } = await import(\"./memory/index.js\");\n let data: unknown;\n switch (type) {\n case \"interactions\":\n data = opts.date ? getInteractions(opts.date) : getRecentInteractions(parseInt(opts.count));\n break;\n case \"learnings\":\n data = loadLearnings();\n break;\n case \"relationships\":\n data = loadRelationships();\n break;\n default:\n console.log(JSON.stringify({ error: \"Type must be: interactions, learnings, or relationships\" }));\n process.exit(1);\n }\n console.log(JSON.stringify(data, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"learn\")\n .description(\"Store a learning\")\n .argument(\"<content>\", \"What you learned\")\n .option(\"-t, --tags <tags...>\", \"Tags for categorization\")\n .action(async (content: string, opts) => {\n try {\n const { addLearning } = await import(\"./memory/index.js\");\n addLearning(content, \"agent\", opts.tags ?? []);\n console.log(JSON.stringify({ success: true }));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"note\")\n .description(\"Add a relationship note about someone\")\n .argument(\"<handle>\", \"Their X handle\")\n .argument(\"<content>\", \"Your note\")\n .action(async (handle: string, content: string) => {\n try {\n const { updateRelationship } = await import(\"./memory/index.js\");\n updateRelationship(handle, { handle, notes: [content] });\n console.log(JSON.stringify({ success: true, handle }));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\n// ========== SCHEDULING ==========\n\nprogram\n .command(\"schedule\")\n .description(\"Queue a post for later\")\n .argument(\"<content>\", \"Tweet content\")\n .option(\"--at <datetime>\", \"ISO datetime to post at\")\n .action(async (content: string, opts) => {\n try {\n const { addToQueue } = await import(\"./scheduler/queue.js\");\n const entry = addToQueue(content, opts.at);\n console.log(JSON.stringify({ success: true, id: entry.id, scheduledFor: entry.scheduledFor }));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"flush\")\n .description(\"Post all queued items whose time has come\")\n .action(async () => {\n try {\n const { flushQueue } = await import(\"./scheduler/queue.js\");\n const results = await flushQueue();\n console.log(JSON.stringify(results, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\nprogram\n .command(\"queue\")\n .description(\"Show scheduled posts\")\n .action(async () => {\n const { showQueue } = await import(\"./scheduler/queue.js\");\n showQueue();\n });\n\n// ========== COLONY ==========\n\nconst colony = program.command(\"colony\").description(\"Colony commands\");\n\ncolony\n .command(\"checkin\")\n .description(\"Check into The Colony — sync memory, discover Spores\")\n .option(\"-m, --message <msg>\", \"Optional message to post\")\n .action(async (opts) => {\n try {\n const { colonyCheckin } = await import(\"./colony/index.js\");\n const result = await colonyCheckin(opts.message);\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\ncolony\n .command(\"memory\")\n .description(\"Read the Colony's shared memory\")\n .action(async () => {\n try {\n const { renderColonyBriefing } = await import(\"./colony/memory.js\");\n console.log(renderColonyBriefing());\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\ncolony\n .command(\"plans\")\n .description(\"Get all active Colony plans\")\n .action(async () => {\n try {\n const { getActivePlans } = await import(\"./colony/index.js\");\n const plans = getActivePlans();\n console.log(plans.length > 0\n ? JSON.stringify(plans, null, 2)\n : JSON.stringify({ message: \"No active plans. Propose one!\" }));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\ncolony\n .command(\"propose\")\n .description(\"Propose a coordinated plan\")\n .argument(\"<description>\", \"What's the plan?\")\n .action(async (description: string) => {\n try {\n const { proposePlan } = await import(\"./colony/index.js\");\n const result = await proposePlan(description);\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\ncolony\n .command(\"join\")\n .description(\"Join an active plan\")\n .argument(\"<planId>\", \"Plan ID\")\n .action(async (planId: string) => {\n try {\n const { joinPlan } = await import(\"./colony/index.js\");\n const result = await joinPlan(planId);\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\ncolony\n .command(\"post-status\")\n .description(\"Post a status update to the Colony\")\n .argument(\"<status>\", \"Your status\")\n .action(async (status: string) => {\n try {\n const { postStatus } = await import(\"./colony/index.js\");\n const result = await postStatus(status);\n console.log(JSON.stringify(result, null, 2));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\ncolony\n .command(\"activity\")\n .description(\"Get today's Colony activity\")\n .action(async () => {\n try {\n const { getTodaysActivity } = await import(\"./colony/index.js\");\n const activity = getTodaysActivity();\n console.log(activity.length > 0\n ? JSON.stringify(activity, null, 2)\n : JSON.stringify({ message: \"No Colony activity today yet.\" }));\n } catch (error) {\n console.log(JSON.stringify({ error: (error as Error).message }));\n process.exit(1);\n }\n });\n\n// ========== AGENT RUNTIME ==========\n\nprogram\n .command(\"start\")\n .description(\"Start the autonomous Spora agent\")\n .option(\"--interval <ms>\", \"Heartbeat interval in milliseconds\")\n .action(async (opts) => {\n if (!sporaExists()) {\n console.log(JSON.stringify({ error: \"Spora not initialized. Run `spora init` first.\" }));\n process.exit(1);\n }\n if (!hasXCredentials()) {\n console.log(JSON.stringify({ error: \"No X credentials. Run `spora init` to set up.\" }));\n process.exit(1);\n }\n\n const { hasLLMKey } = await import(\"./runtime/llm.js\");\n if (!hasLLMKey()) {\n console.log(JSON.stringify({ error: \"No LLM API key. Run `spora set-llm-key` first.\" }));\n process.exit(1);\n }\n\n // Apply interval override\n if (opts.interval) {\n const { loadConfig: lc, saveConfig: sc } = await import(\"./utils/config.js\");\n const config = lc();\n config.runtime = { ...config.runtime, heartbeatIntervalMs: parseInt(opts.interval, 10), actionsPerHeartbeat: config.runtime?.actionsPerHeartbeat ?? 3, enabled: true };\n sc(config);\n }\n\n console.log(chalk.cyan(BANNER));\n console.log(chalk.bold(\"Starting Spora agent...\\n\"));\n\n const { startHeartbeatLoop } = await import(\"./runtime/heartbeat.js\");\n await startHeartbeatLoop();\n });\n\nprogram\n .command(\"stop\")\n .description(\"Stop the running Spora agent\")\n .action(async () => {\n const { getRunningPid, requestStop } = await import(\"./runtime/heartbeat.js\");\n const pid = getRunningPid();\n if (!pid) {\n console.log(JSON.stringify({ message: \"Spora agent is not running.\" }));\n return;\n }\n requestStop();\n console.log(JSON.stringify({ message: `Stop signal sent to PID ${pid}.` }));\n });\n\nprogram\n .command(\"set-llm-key\")\n .description(\"Set your LLM provider and API key for the agent runtime\")\n .argument(\"[key]\", \"API key (or omit to enter interactively)\")\n .action(async (key?: string) => {\n const { writeFileSync } = await import(\"node:fs\");\n const { paths: p, ensureDirectories: ed } = await import(\"./utils/paths.js\");\n ed();\n\n // Check env first\n if (!key && (process.env.LLM_API_KEY || process.env.ANTHROPIC_API_KEY)) {\n console.log(JSON.stringify({ message: \"Using LLM API key from environment.\" }));\n return;\n }\n\n const { select, input } = await import(\"@inquirer/prompts\");\n\n // Ask which provider\n const provider = await select({\n message: \"Which LLM provider do you want to use?\",\n choices: [\n { name: \"DeepSeek (Recommended — cheaper)\", value: \"deepseek\" },\n { name: \"Anthropic (Claude)\", value: \"anthropic\" },\n ],\n }) as \"deepseek\" | \"anthropic\";\n\n const providerConfigs: Record<string, { model: string; baseUrl: string; label: string }> = {\n deepseek: {\n model: \"deepseek-v3.2-speciale\",\n baseUrl: \"https://api.llm-stats.com/v1\",\n label: \"DeepSeek\",\n },\n anthropic: {\n model: \"claude-sonnet-4-20250514\",\n baseUrl: \"https://api.anthropic.com/v1\",\n label: \"Anthropic\",\n },\n };\n\n const chosen = providerConfigs[provider];\n\n let apiKey = key;\n if (!apiKey) {\n apiKey = await input({\n message: `Enter your ${chosen.label} API key:`,\n validate: (v) => v.length > 0 ? true : \"API key is required\",\n });\n }\n\n writeFileSync(p.llmKey, apiKey!, { mode: 0o600 });\n\n // Update config with chosen provider\n try {\n const { loadConfig: lc, saveConfig: sc } = await import(\"./utils/config.js\");\n const config = lc();\n config.llm = { provider, model: chosen.model, baseUrl: chosen.baseUrl };\n sc(config);\n } catch {\n // Config may not exist yet, that's ok\n }\n\n console.log(JSON.stringify({ success: true, message: `${chosen.label} API key saved.` }));\n });\n\n\nprogram\n .command(\"agent-status\")\n .description(\"Check if the Spora agent is running\")\n .action(async () => {\n const { getRunningPid } = await import(\"./runtime/heartbeat.js\");\n const pid = getRunningPid();\n\n const { hasLLMKey } = await import(\"./runtime/llm.js\");\n\n console.log(JSON.stringify({\n agentRunning: pid !== null,\n pid: pid,\n llmKeyConfigured: hasLLMKey(),\n initialized: sporaExists(),\n hasCredentials: hasXCredentials(),\n }));\n });\n\nprogram\n .command(\"ui\")\n .description(\"Open the Spora web UI for setup and management\")\n .option(\"-p, --port <port>\", \"Port to run on\", \"3000\")\n .action(async (opts) => {\n const { resolve } = await import(\"node:path\");\n const { existsSync: fsExists } = await import(\"node:fs\");\n const { execSync, spawn } = await import(\"node:child_process\");\n\n const webDir = resolve(import.meta.dirname, \"../../packages/web\");\n if (!fsExists(webDir)) {\n console.log(chalk.red(\"Web UI not found. Expected at: \" + webDir));\n process.exit(1);\n }\n\n const port = opts.port || \"3000\";\n console.log(chalk.cyan(BANNER));\n console.log(chalk.bold(\"Starting Spora UI...\\n\"));\n\n // Check if dependencies are installed\n if (!fsExists(resolve(webDir, \"node_modules\"))) {\n console.log(chalk.gray(\"Installing dependencies...\"));\n execSync(\"npm install\", { cwd: webDir, stdio: \"inherit\" });\n }\n\n console.log(chalk.green(`\\n Spora UI: http://localhost:${port}\\n`));\n console.log(chalk.gray(\"Press Ctrl+C to stop.\\n\"));\n\n // Open browser\n try {\n const openCmd = process.platform === \"darwin\" ? \"open\" : process.platform === \"win32\" ? \"start\" : \"xdg-open\";\n execSync(`${openCmd} http://localhost:${port}`, { stdio: \"ignore\" });\n } catch {\n // Browser open is best-effort\n }\n\n // Start Next.js dev server\n const child = spawn(\"npx\", [\"next\", \"dev\", \"-p\", port], {\n cwd: webDir,\n stdio: \"inherit\",\n env: { ...process.env },\n });\n\n child.on(\"close\", (code) => {\n process.exit(code ?? 0);\n });\n\n process.on(\"SIGINT\", () => {\n child.kill(\"SIGINT\");\n });\n process.on(\"SIGTERM\", () => {\n child.kill(\"SIGTERM\");\n });\n });\n\nprogram.parse();\n"],"mappings":"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","names":["config"]}
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-PNZ3XK2N.js";
5
5
  import {
6
6
  generateResponse
7
- } from "./chunk-N5TBL3NY.js";
7
+ } from "./chunk-JAF57FYU.js";
8
8
  import {
9
9
  rateLimiter
10
10
  } from "./chunk-ML4EMUZC.js";
@@ -898,4 +898,4 @@ export {
898
898
  requestStop,
899
899
  startHeartbeatLoop
900
900
  };
901
- //# sourceMappingURL=heartbeat-B2CZKMUF.js.map
901
+ //# sourceMappingURL=heartbeat-VPRJ4TXU.js.map
@@ -203,7 +203,7 @@ async function loginFlow() {
203
203
  console.log(chalk.green("\u2713 Logged in!\n"));
204
204
  console.log(chalk.gray("Opening chat interface...\n"));
205
205
  try {
206
- const { startWebChat } = await import("./web-chat-DHHJTGFZ.js");
206
+ const { startWebChat } = await import("./web-chat-QADQADSK.js");
207
207
  await startWebChat();
208
208
  } catch (error) {
209
209
  console.log(chalk.yellow(`Could not start chat interface: ${error.message}
@@ -212,18 +212,51 @@ async function loginFlow() {
212
212
  }
213
213
  }
214
214
  async function setupKeys() {
215
- console.log(chalk.bold("\n\u2501\u2501\u2501 LLM API Key \u2501\u2501\u2501\n"));
216
- console.log(chalk.gray("Your Spore uses DeepSeek to think and make decisions."));
217
- console.log(chalk.gray("Enter your LLM API key below.\n"));
215
+ console.log(chalk.bold("\n\u2501\u2501\u2501 LLM Provider \u2501\u2501\u2501\n"));
216
+ console.log(chalk.gray("Choose which LLM will power your Spore's brain.\n"));
217
+ const provider = await select({
218
+ message: "Which LLM provider do you want to use?",
219
+ choices: [
220
+ { name: "DeepSeek (Recommended \u2014 cheaper)", value: "deepseek" },
221
+ { name: "Anthropic (Claude)", value: "anthropic" }
222
+ ]
223
+ });
224
+ const providerConfigs = {
225
+ deepseek: {
226
+ model: "deepseek-v3.2-speciale",
227
+ baseUrl: "https://api.llm-stats.com/v1",
228
+ label: "DeepSeek",
229
+ keyHelp: "Enter your DeepSeek API key below."
230
+ },
231
+ anthropic: {
232
+ model: "claude-sonnet-4-20250514",
233
+ baseUrl: "https://api.anthropic.com/v1",
234
+ label: "Anthropic",
235
+ keyHelp: "Get your API key at: https://console.anthropic.com/keys"
236
+ }
237
+ };
238
+ const chosen = providerConfigs[provider];
239
+ console.log(chalk.bold(`
240
+ \u2501\u2501\u2501 ${chosen.label} API Key \u2501\u2501\u2501
241
+ `));
242
+ console.log(chalk.gray(chosen.keyHelp + "\n"));
218
243
  const llmKey = await passwordPrompt({
219
- message: "LLM API Key:",
244
+ message: `${chosen.label} API Key:`,
220
245
  mask: "*",
221
246
  validate: (val) => val.length > 0 ? true : "API key is required"
222
247
  });
223
248
  const { paths } = await import("./paths-Q4TJEOMQ.js");
224
249
  const { writeFileSync } = await import("fs");
225
250
  writeFileSync(paths.llmKey, llmKey, "utf-8");
226
- console.log(chalk.green("\u2713 LLM API key saved\n"));
251
+ try {
252
+ const { loadConfig: lc, saveConfig: sc } = await import("./config-5EPXA325.js");
253
+ const config = lc();
254
+ config.llm = { provider, model: chosen.model, baseUrl: chosen.baseUrl };
255
+ sc(config);
256
+ } catch {
257
+ }
258
+ console.log(chalk.green(`\u2713 ${chosen.label} API key saved
259
+ `));
227
260
  console.log(chalk.bold("\n\u2501\u2501\u2501 Connect Your X Account \u2501\u2501\u2501\n"));
228
261
  console.log(chalk.gray("Your Spore needs OAuth 1.0a credentials for full X API access."));
229
262
  console.log(chalk.gray("This gives your agent the power to read timelines, post tweets, reply, like, and follow.\n"));
@@ -275,7 +308,7 @@ async function showDoneAndOpenChat() {
275
308
  console.log(chalk.bold.cyan("\u2501\u2501\u2501 Your Spore is Ready! \u2501\u2501\u2501\n"));
276
309
  console.log(chalk.gray("Opening chat interface...\n"));
277
310
  try {
278
- const { startWebChat } = await import("./web-chat-DHHJTGFZ.js");
311
+ const { startWebChat } = await import("./web-chat-QADQADSK.js");
279
312
  await startWebChat();
280
313
  } catch (error) {
281
314
  console.log(chalk.yellow(`Could not start chat interface: ${error.message}
@@ -400,4 +433,4 @@ async function runInit(token) {
400
433
  export {
401
434
  runInit
402
435
  };
403
- //# sourceMappingURL=init-KXNLBFMG.js.map
436
+ //# sourceMappingURL=init-PNFSGSIR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/init.ts","../src/x-client/profile-updater.ts"],"sourcesContent":["import { input, select, confirm, password as passwordPrompt } from \"@inquirer/prompts\";\nimport chalk from \"chalk\";\nimport { sporaExists, ensureDirectories } from \"./utils/paths.js\";\nimport { createDefaultConfig, saveConfig } from \"./utils/config.js\";\nimport { saveCredentials, type XCredentials } from \"./utils/crypto.js\";\nimport { loadIdentity } from \"./identity/index.js\";\nimport { updateXProfile } from \"./x-client/profile-updater.js\";\n\n/**\n * Fetch identity from token and save locally\n */\nasync function syncIdentityFromToken(token: string): Promise<void> {\n console.log(chalk.gray(\"Connecting to spora.dev...\\n\"));\n\n const apiUrl = process.env.SPORA_API_URL || \"https://www.spora.social\";\n const response = await fetch(`${apiUrl}/api/v1/connect`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ token }),\n });\n\n if (!response.ok) {\n const errData = await response.json().catch(() => ({}));\n throw new Error(errData.error || `Connection failed: ${response.statusText}`);\n }\n\n const data = await response.json();\n\n if (!data.identity) {\n throw new Error(\"No Spore identity found for this token\");\n }\n\n // Merge media fields\n if (data.media) {\n if (data.media.profileImage) data.identity.profileImage = data.media.profileImage;\n if (data.media.bannerImage) data.identity.bannerImage = data.media.bannerImage;\n }\n\n const { saveIdentity } = await import(\"./identity/index.js\");\n saveIdentity(data.identity);\n\n console.log(chalk.green(`✓ Connected to Spore: ${data.identity.name} (@${data.identity.handle})\\n`));\n\n // Save README if provided\n if (data.readme) {\n const { writeFileSync } = await import(\"node:fs\");\n const { paths } = await import(\"./utils/paths.js\");\n const { join, dirname } = await import(\"node:path\");\n const readmePath = join(dirname(paths.identity), \"IDENTITY.md\");\n writeFileSync(readmePath, data.readme, \"utf-8\");\n console.log(chalk.green(\"✓ Saved identity README\\n\"));\n }\n\n // Save connection token to config\n const { existsSync } = await import(\"node:fs\");\n const { paths } = await import(\"./utils/paths.js\");\n if (existsSync(paths.config)) {\n const { loadConfig, saveConfig } = await import(\"./utils/config.js\");\n const config = loadConfig();\n config.connection = {\n token,\n apiEndpoint: process.env.SPORA_API_URL || \"https://www.spora.social/api/v1\",\n configVersion: config.connection?.configVersion ?? 0,\n };\n saveConfig(config);\n }\n}\n\n/**\n * Login flow: paste token → sync identity → open chat (keys already saved locally)\n */\nasync function loginFlow(): Promise<void> {\n console.log(chalk.bold(\"\\n━━━ Login to Existing Spore ━━━\\n\"));\n console.log(chalk.gray(\"Paste your setup token from spora.dev\"));\n console.log(chalk.gray(\"(It looks like: spora_7e636ac0...)\\n\"));\n\n const token = await input({\n message: \"Setup token:\",\n validate: (val) => val.length > 0 ? true : \"Token is required\",\n });\n\n ensureDirectories();\n\n try {\n await syncIdentityFromToken(token.trim());\n } catch (error) {\n console.log(chalk.red(`\\n✗ ${(error as Error).message}\\n`));\n console.log(chalk.yellow(\"Please check your token and try again.\\n\"));\n process.exit(1);\n }\n\n console.log(chalk.green(\"✓ Logged in!\\n\"));\n console.log(chalk.gray(\"Opening chat interface...\\n\"));\n\n try {\n const { startWebChat } = await import(\"./web-chat/index.js\");\n await startWebChat();\n } catch (error) {\n console.log(chalk.yellow(`Could not start chat interface: ${(error as Error).message}\\n`));\n console.log(chalk.gray(\"You can start it manually with: spora chat\\n\"));\n }\n}\n\n/**\n * Prompt for LLM provider selection, API key, and X credentials\n */\nasync function setupKeys(): Promise<void> {\n // LLM provider selection\n console.log(chalk.bold(\"\\n━━━ LLM Provider ━━━\\n\"));\n console.log(chalk.gray(\"Choose which LLM will power your Spore's brain.\\n\"));\n\n const provider = await select({\n message: \"Which LLM provider do you want to use?\",\n choices: [\n { name: \"DeepSeek (Recommended — cheaper)\", value: \"deepseek\" },\n { name: \"Anthropic (Claude)\", value: \"anthropic\" },\n ],\n }) as \"deepseek\" | \"anthropic\";\n\n const providerConfigs: Record<string, { model: string; baseUrl: string; label: string; keyHelp: string }> = {\n deepseek: {\n model: \"deepseek-v3.2-speciale\",\n baseUrl: \"https://api.llm-stats.com/v1\",\n label: \"DeepSeek\",\n keyHelp: \"Enter your DeepSeek API key below.\",\n },\n anthropic: {\n model: \"claude-sonnet-4-20250514\",\n baseUrl: \"https://api.anthropic.com/v1\",\n label: \"Anthropic\",\n keyHelp: \"Get your API key at: https://console.anthropic.com/keys\",\n },\n };\n\n const chosen = providerConfigs[provider];\n\n console.log(chalk.bold(`\\n━━━ ${chosen.label} API Key ━━━\\n`));\n console.log(chalk.gray(chosen.keyHelp + \"\\n\"));\n\n const llmKey = await passwordPrompt({\n message: `${chosen.label} API Key:`,\n mask: \"*\",\n validate: (val: string) => val.length > 0 ? true : \"API key is required\",\n });\n\n const { paths } = await import(\"./utils/paths.js\");\n const { writeFileSync } = await import(\"node:fs\");\n writeFileSync(paths.llmKey, llmKey, \"utf-8\");\n\n // Save LLM config immediately so it's available later\n try {\n const { loadConfig: lc, saveConfig: sc } = await import(\"./utils/config.js\");\n const config = lc();\n config.llm = { provider, model: chosen.model, baseUrl: chosen.baseUrl };\n sc(config);\n } catch {\n // Config may not exist yet during init, will be set later\n }\n\n console.log(chalk.green(`✓ ${chosen.label} API key saved\\n`));\n\n // X credentials\n console.log(chalk.bold(\"\\n━━━ Connect Your X Account ━━━\\n\"));\n console.log(chalk.gray(\"Your Spore needs OAuth 1.0a credentials for full X API access.\"));\n console.log(chalk.gray(\"This gives your agent the power to read timelines, post tweets, reply, like, and follow.\\n\"));\n console.log(chalk.cyan(\"How to get these credentials:\"));\n console.log(chalk.gray(\" 1. Go to: \") + chalk.cyan(\"https://developer.x.com/en/portal/dashboard\"));\n console.log(chalk.gray(\" 2. Create or select your app\"));\n console.log(chalk.gray(\" 3. Go to \\\"Keys and tokens\\\" tab\"));\n console.log(chalk.gray(\" 4. Copy all 4 credentials below\\n\"));\n console.log(chalk.yellow(\"Note: You need X Pro account ($200/mo) for posting access.\\n\"));\n\n const apiKey = await passwordPrompt({\n message: \"X API Key (Consumer Key):\",\n mask: \"*\",\n validate: (val: string) => val.length > 0 ? true : \"API Key is required\",\n });\n\n const apiSecret = await passwordPrompt({\n message: \"X API Secret (Consumer Secret):\",\n mask: \"*\",\n validate: (val: string) => val.length > 0 ? true : \"API Secret is required\",\n });\n\n const accessToken = await passwordPrompt({\n message: \"X Access Token:\",\n mask: \"*\",\n validate: (val: string) => val.length > 0 ? true : \"Access Token is required\",\n });\n\n const accessTokenSecret = await passwordPrompt({\n message: \"X Access Token Secret:\",\n mask: \"*\",\n validate: (val: string) => val.length > 0 ? true : \"Access Token Secret is required\",\n });\n\n const bearerToken = await passwordPrompt({\n message: \"X Bearer Token:\",\n mask: \"*\",\n validate: (val: string) => val.length > 0 ? true : \"Bearer Token is required\",\n });\n\n saveCredentials({\n method: \"api\",\n apiKey,\n apiSecret,\n accessToken,\n accessTokenSecret,\n bearerToken,\n });\n console.log(chalk.green(\"✓ X API credentials saved (encrypted)\\n\"));\n}\n\n/**\n * Show completion message and open chat\n */\nasync function showDoneAndOpenChat(): Promise<void> {\n console.log(chalk.green(\"\\n╔═══════════════════════════════════════╗\"));\n console.log(chalk.green.bold(\"║ Setup Complete! ║\"));\n console.log(chalk.green(\"╚═══════════════════════════════════════╝\\n\"));\n\n console.log(chalk.bold.cyan(\"━━━ Your Spore is Ready! ━━━\\n\"));\n console.log(chalk.gray(\"Opening chat interface...\\n\"));\n\n try {\n const { startWebChat } = await import(\"./web-chat/index.js\");\n await startWebChat();\n } catch (error) {\n console.log(chalk.yellow(`Could not start chat interface: ${(error as Error).message}\\n`));\n console.log(chalk.gray(\"You can start it manually with: spora chat\\n\"));\n }\n\n console.log(chalk.bold(\"Quick Start:\\n\"));\n console.log(chalk.cyan(\" spora chat\"));\n console.log(chalk.gray(\" → Talk to your Spore, tell it what to post, how to behave\\n\"));\n console.log(chalk.bold(\"Or start the autonomous agent:\\n\"));\n console.log(chalk.cyan(\" spora start\"));\n console.log(chalk.gray(\" → Your Spore will post and engage autonomously\\n\"));\n console.log(chalk.bold(\"Other commands:\\n\"));\n console.log(chalk.cyan(\" spora create \") + chalk.gray(\"# Create a personality\"));\n console.log(chalk.cyan(\" spora post <text> \") + chalk.gray(\"# Make your Spore post\"));\n console.log(chalk.cyan(\" spora agent-status \") + chalk.gray(\"# Check if agent is running\"));\n console.log(chalk.cyan(\" spora stop \") + chalk.gray(\"# Stop the agent\"));\n console.log(chalk.cyan(\" spora --help \") + chalk.gray(\"# See all commands\\n\"));\n}\n\nexport async function runInit(token?: string): Promise<void> {\n console.log(chalk.bold.cyan(\"\\n╔════════════════════════════════════════╗\"));\n console.log(chalk.bold.cyan(\"║ Welcome to Spora CLI Setup ║\"));\n console.log(chalk.bold.cyan(\"╚════════════════════════════════════════╝\\n\"));\n\n // If token provided via --token flag, this is a new user from the website → full setup\n if (token) {\n ensureDirectories();\n\n console.log(chalk.bold(\"\\n━━━ Connecting Your Spore ━━━\\n\"));\n try {\n await syncIdentityFromToken(token);\n } catch (error) {\n console.log(chalk.red(`\\n✗ ${(error as Error).message}\\n`));\n console.log(chalk.yellow(\"Please check your token and try again.\\n\"));\n process.exit(1);\n }\n\n await setupKeys();\n\n // Update X profile\n console.log(chalk.bold(\"\\n━━━ Updating Your X Profile ━━━\\n\"));\n console.log(chalk.gray(\"Setting up profile picture, banner, and bio to match your Spore...\\n\"));\n try {\n const identity = loadIdentity();\n const result = await updateXProfile(identity);\n if (result.success) {\n console.log(chalk.green(\"✓ Profile updated successfully!\\n\"));\n if (result.updated.length > 0) {\n console.log(chalk.cyan(\"Updated:\"));\n for (const field of result.updated) {\n console.log(chalk.gray(` • ${field}`));\n }\n console.log();\n }\n }\n if (result.errors.length > 0) {\n console.log(chalk.yellow(\"\\nSome updates failed:\"));\n for (const err of result.errors) {\n console.log(chalk.gray(` • ${err}`));\n }\n console.log();\n }\n } catch (error) {\n console.log(chalk.yellow(`Could not update profile: ${(error as Error).message}\\n`));\n console.log(chalk.gray(\"You can manually update your X profile later.\\n\"));\n }\n\n const config = createDefaultConfig({ xMethod: \"api\", xApiTier: \"basic\" });\n config.llm = { provider: \"deepseek\", model: \"deepseek-v3.2-speciale\", baseUrl: \"https://api.llm-stats.com/v1\" };\n config.runtime = { heartbeatIntervalMs: 300_000, actionsPerHeartbeat: 3, enabled: true };\n config.connection = {\n token,\n apiEndpoint: process.env.SPORA_API_URL || \"https://www.spora.social/api/v1\",\n configVersion: 0,\n };\n saveConfig(config);\n\n await showDoneAndOpenChat();\n return;\n }\n\n // No token provided — ask what they want to do\n const action = await select({\n message: \"What would you like to do?\",\n choices: [\n { name: \"Create a new Spore\", value: \"new\" },\n { name: \"Login to existing Spore\", value: \"login\" },\n ],\n });\n\n if (action === \"login\") {\n await loginFlow();\n return;\n }\n\n // \"new\" — full new Spore creation (no token, manual setup)\n ensureDirectories();\n\n await setupKeys();\n\n // Update X profile\n console.log(chalk.bold(\"\\n━━━ Updating Your X Profile ━━━\\n\"));\n console.log(chalk.gray(\"Setting up profile picture, banner, and bio to match your Spore...\\n\"));\n try {\n const identity = loadIdentity();\n const result = await updateXProfile(identity);\n if (result.success) {\n console.log(chalk.green(\"✓ Profile updated successfully!\\n\"));\n if (result.updated.length > 0) {\n console.log(chalk.cyan(\"Updated:\"));\n for (const field of result.updated) {\n console.log(chalk.gray(` • ${field}`));\n }\n console.log();\n }\n }\n if (result.errors.length > 0) {\n console.log(chalk.yellow(\"\\nSome updates failed:\"));\n for (const err of result.errors) {\n console.log(chalk.gray(` • ${err}`));\n }\n console.log();\n }\n } catch (error) {\n console.log(chalk.yellow(`Could not update profile: ${(error as Error).message}\\n`));\n console.log(chalk.gray(\"You can manually update your X profile later.\\n\"));\n }\n\n const config = createDefaultConfig({ xMethod: \"api\", xApiTier: \"basic\" });\n config.llm = { provider: \"deepseek\", model: \"deepseek-v3.2-speciale\", baseUrl: \"https://api.llm-stats.com/v1\" };\n config.runtime = { heartbeatIntervalMs: 300_000, actionsPerHeartbeat: 3, enabled: true };\n saveConfig(config);\n\n await showDoneAndOpenChat();\n}\n","/**\n * X Profile Updater\n * Updates X profile to match Spore identity (name, bio, profile pic, banner)\n */\n\nimport { TwitterApi } from \"twitter-api-v2\";\nimport sharp from \"sharp\";\nimport type { Identity } from \"../identity/schema.js\";\nimport { loadCredentials } from \"../utils/crypto.js\";\n\ninterface ProfileUpdateResult {\n success: boolean;\n updated: string[];\n errors: string[];\n}\n\n/**\n * Update X profile to match Spore identity\n * Requires OAuth 1.0a credentials\n */\nexport async function updateXProfile(identity: Identity): Promise<ProfileUpdateResult> {\n const result: ProfileUpdateResult = {\n success: false,\n updated: [],\n errors: [],\n };\n\n try {\n const creds = loadCredentials();\n if (creds.method !== \"api\") {\n result.errors.push(\"API credentials required\");\n return result;\n }\n\n // Create Twitter API client with OAuth 1.0a credentials\n const client = new TwitterApi({\n appKey: creds.apiKey!,\n appSecret: creds.apiSecret!,\n accessToken: creds.accessToken!,\n accessSecret: creds.accessTokenSecret!,\n });\n\n // Update profile name and bio (username separately to avoid breaking on failure)\n try {\n console.log(`Updating name to: ${identity.name}`);\n console.log(`Updating bio to: ${identity.bio.substring(0, 60)}...`);\n await client.v1.updateAccountProfile({\n name: identity.name,\n description: identity.bio,\n });\n result.updated.push(\"name\", \"bio\");\n console.log(\"Name and bio updated successfully\");\n } catch (error) {\n console.error(\"Name/bio update error:\", error);\n result.errors.push(`Failed to update name/bio: ${(error as Error).message}`);\n }\n\n // Try to update username separately (optional, may fail if taken or restricted)\n if (identity.handle) {\n try {\n console.log(`Attempting to update username to: @${identity.handle}`);\n await client.v1.updateAccountProfile({\n screen_name: identity.handle,\n });\n result.updated.push(\"username\");\n console.log(\"Username updated successfully\");\n } catch (error) {\n // Don't fail the whole update if username change fails\n console.warn(`Could not update username: ${(error as Error).message}`);\n }\n }\n\n // Update profile image if available\n if (identity.profileImage) {\n try {\n console.log(`Downloading profile image from: ${identity.profileImage.substring(0, 60)}...`);\n let imageBuffer = await downloadImage(identity.profileImage);\n console.log(`Downloaded ${(imageBuffer.length / 1024 / 1024).toFixed(2)}MB`);\n\n // Check image dimensions - Twitter requires min 400x400\n const metadata = await sharp(imageBuffer).metadata();\n console.log(`Image dimensions: ${metadata.width}x${metadata.height}`);\n\n if (!metadata.width || !metadata.height || metadata.width < 400 || metadata.height < 400) {\n throw new Error(`Image too small (${metadata.width}x${metadata.height}). Twitter requires minimum 400x400 pixels.`);\n }\n\n // Compress if needed (Twitter profile image limit: 2MB)\n const MAX_PROFILE_SIZE = 2 * 1024 * 1024; // 2MB\n imageBuffer = await compressImageIfNeeded(imageBuffer, MAX_PROFILE_SIZE, \"Profile\");\n\n console.log(`Uploading profile image to X...`);\n await client.v1.updateAccountProfileImage(imageBuffer);\n result.updated.push(\"profile_image\");\n console.log(\"Profile image updated successfully\");\n } catch (error) {\n console.error(\"Profile image error:\", error);\n result.errors.push(`Failed to update profile image: ${(error as Error).message}`);\n }\n } else {\n console.log(\"No profile image URL in identity\");\n }\n\n // Update banner image if available\n if (identity.bannerImage) {\n try {\n console.log(`Downloading banner image from: ${identity.bannerImage.substring(0, 60)}...`);\n let imageBuffer = await downloadImage(identity.bannerImage);\n console.log(`Downloaded ${(imageBuffer.length / 1024 / 1024).toFixed(2)}MB`);\n\n // Compress if needed (Twitter banner limit: 5MB)\n const MAX_BANNER_SIZE = 5 * 1024 * 1024; // 5MB\n imageBuffer = await compressImageIfNeeded(imageBuffer, MAX_BANNER_SIZE, \"Banner\");\n\n console.log(`Uploading banner image to X...`);\n await client.v1.updateAccountProfileBanner(imageBuffer);\n result.updated.push(\"banner_image\");\n console.log(\"Banner image updated successfully\");\n } catch (error) {\n console.error(\"Banner image error:\", error);\n result.errors.push(`Failed to update banner: ${(error as Error).message}`);\n }\n } else {\n console.log(\"No banner image URL in identity\");\n }\n\n result.success = result.updated.length > 0;\n return result;\n } catch (error) {\n result.errors.push((error as Error).message);\n return result;\n }\n}\n\n/**\n * Download image from URL and return as Buffer\n */\nasync function downloadImage(url: string): Promise<Buffer> {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Failed to download image: ${response.statusText}`);\n }\n const arrayBuffer = await response.arrayBuffer();\n return Buffer.from(arrayBuffer);\n}\n\n/**\n * Compress image if it exceeds size limit by resizing\n * @param buffer Original image buffer\n * @param maxSizeBytes Maximum allowed size in bytes\n * @param type \"profile\" or \"banner\" for logging\n */\nasync function compressImageIfNeeded(\n buffer: Buffer,\n maxSizeBytes: number,\n type: string\n): Promise<Buffer> {\n if (buffer.length <= maxSizeBytes) {\n return buffer;\n }\n\n console.log(\n `${type} image is ${(buffer.length / 1024 / 1024).toFixed(2)}MB, resizing to fit ${(maxSizeBytes / 1024 / 1024).toFixed(0)}MB limit...`\n );\n\n // Calculate scale factor to fit within size limit\n const scaleFactor = Math.sqrt(maxSizeBytes / buffer.length) * 0.85; // 85% of target for safety\n\n // Get current dimensions and calculate new size\n const metadata = await sharp(buffer).metadata();\n const newWidth = Math.floor((metadata.width || 1000) * scaleFactor);\n\n // Resize and convert to JPEG with good quality\n const compressed = await sharp(buffer)\n .resize(newWidth, null, { fit: \"inside\", withoutEnlargement: true })\n .jpeg({ quality: 90, progressive: true })\n .toBuffer();\n\n console.log(\n `Resized ${type} image from ${(buffer.length / 1024 / 1024).toFixed(2)}MB to ${(compressed.length / 1024 / 1024).toFixed(2)}MB`\n );\n\n return compressed;\n}\n"],"mappings":"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","names":["paths","saveConfig","config"]}
@@ -3,7 +3,7 @@ import {
3
3
  generateResponse,
4
4
  getLLMApiKey,
5
5
  hasLLMKey
6
- } from "./chunk-N5TBL3NY.js";
6
+ } from "./chunk-JAF57FYU.js";
7
7
  import "./chunk-GMSK775L.js";
8
8
  import "./chunk-UCCAF2ZO.js";
9
9
  import "./chunk-6KCIAMHL.js";
@@ -13,4 +13,4 @@ export {
13
13
  getLLMApiKey,
14
14
  hasLLMKey
15
15
  };
16
- //# sourceMappingURL=llm-CUCO24K7.js.map
16
+ //# sourceMappingURL=llm-UKK62ZBP.js.map
@@ -185,7 +185,7 @@ async function startWebChat() {
185
185
  systemPrompt = buildChatPrompt();
186
186
  }
187
187
  messageCount++;
188
- const { hasLLMKey, chat: chatLLM } = await import("./llm-CUCO24K7.js");
188
+ const { hasLLMKey, chat: chatLLM } = await import("./llm-UKK62ZBP.js");
189
189
  if (!hasLLMKey()) {
190
190
  return "I can't respond right now - no API key configured. Run `spora set-llm-key` to set one up.";
191
191
  }
@@ -250,4 +250,4 @@ export {
250
250
  openBrowser,
251
251
  startWebChat
252
252
  };
253
- //# sourceMappingURL=web-chat-DHHJTGFZ.js.map
253
+ //# sourceMappingURL=web-chat-QADQADSK.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spora",
3
- "version": "0.3.4",
3
+ "version": "0.3.5",
4
4
  "description": "AI agents (Spores) that autonomously manage X/Twitter accounts",
5
5
  "type": "module",
6
6
  "author": "Spora",
@@ -1,86 +0,0 @@
1
- import {
2
- loadConfig
3
- } from "./chunk-GMSK775L.js";
4
- import {
5
- logger
6
- } from "./chunk-UCCAF2ZO.js";
7
- import {
8
- paths
9
- } from "./chunk-6KCIAMHL.js";
10
-
11
- // src/runtime/llm.ts
12
- import OpenAI from "openai";
13
- import { readFileSync, existsSync } from "fs";
14
- var client = null;
15
- var DEFAULT_MODEL = "deepseek-v3.2-speciale";
16
- var DEFAULT_BASE_URL = "https://api.llm-stats.com/v1";
17
- function getLLMApiKey() {
18
- if (process.env.LLM_API_KEY) {
19
- return process.env.LLM_API_KEY;
20
- }
21
- if (process.env.ANTHROPIC_API_KEY) {
22
- return process.env.ANTHROPIC_API_KEY;
23
- }
24
- if (existsSync(paths.llmKey)) {
25
- return readFileSync(paths.llmKey, "utf-8").trim();
26
- }
27
- return null;
28
- }
29
- function hasLLMKey() {
30
- return getLLMApiKey() !== null;
31
- }
32
- function getClient() {
33
- if (client) return client;
34
- const apiKey = getLLMApiKey();
35
- if (!apiKey) {
36
- throw new Error("No LLM API key configured. Run `spora set-llm-key` first.");
37
- }
38
- const config = loadConfig();
39
- const baseURL = config.llm?.baseUrl ?? DEFAULT_BASE_URL;
40
- client = new OpenAI({ apiKey, baseURL });
41
- return client;
42
- }
43
- async function generateResponse(systemPrompt, userMessage) {
44
- const config = loadConfig();
45
- const model = config.llm?.model ?? DEFAULT_MODEL;
46
- logger.info(`Calling LLM (${model})...`);
47
- const openai = getClient();
48
- const response = await openai.chat.completions.create({
49
- model,
50
- max_tokens: 2048,
51
- messages: [
52
- { role: "system", content: systemPrompt },
53
- { role: "user", content: userMessage }
54
- ]
55
- });
56
- const content = response.choices[0]?.message?.content ?? "";
57
- const inputTokens = response.usage?.prompt_tokens ?? 0;
58
- const outputTokens = response.usage?.completion_tokens ?? 0;
59
- logger.info(`LLM response: ${inputTokens} in, ${outputTokens} out`);
60
- return { content, inputTokens, outputTokens };
61
- }
62
- async function chat(systemPrompt, messages) {
63
- const config = loadConfig();
64
- const model = config.llm?.model ?? DEFAULT_MODEL;
65
- const openai = getClient();
66
- const response = await openai.chat.completions.create({
67
- model,
68
- max_tokens: 2048,
69
- messages: [
70
- { role: "system", content: systemPrompt },
71
- ...messages
72
- ]
73
- });
74
- const content = response.choices[0]?.message?.content ?? "";
75
- const inputTokens = response.usage?.prompt_tokens ?? 0;
76
- const outputTokens = response.usage?.completion_tokens ?? 0;
77
- return { content, inputTokens, outputTokens };
78
- }
79
-
80
- export {
81
- getLLMApiKey,
82
- hasLLMKey,
83
- generateResponse,
84
- chat
85
- };
86
- //# sourceMappingURL=chunk-N5TBL3NY.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/runtime/llm.ts"],"sourcesContent":["import OpenAI from \"openai\";\nimport { readFileSync, existsSync } from \"node:fs\";\nimport { paths } from \"../utils/paths.js\";\nimport { loadConfig } from \"../utils/config.js\";\nimport { logger } from \"../utils/logger.js\";\n\nlet client: OpenAI | null = null;\n\nconst DEFAULT_MODEL = \"deepseek-v3.2-speciale\";\nconst DEFAULT_BASE_URL = \"https://api.llm-stats.com/v1\";\n\nexport function getLLMApiKey(): string | null {\n // Check env first (support both old and new env var names), then file\n if (process.env.LLM_API_KEY) {\n return process.env.LLM_API_KEY;\n }\n if (process.env.ANTHROPIC_API_KEY) {\n return process.env.ANTHROPIC_API_KEY;\n }\n if (existsSync(paths.llmKey)) {\n return readFileSync(paths.llmKey, \"utf-8\").trim();\n }\n return null;\n}\n\nexport function hasLLMKey(): boolean {\n return getLLMApiKey() !== null;\n}\n\nfunction getClient(): OpenAI {\n if (client) return client;\n const apiKey = getLLMApiKey();\n if (!apiKey) {\n throw new Error(\"No LLM API key configured. Run `spora set-llm-key` first.\");\n }\n const config = loadConfig();\n const baseURL = config.llm?.baseUrl ?? DEFAULT_BASE_URL;\n client = new OpenAI({ apiKey, baseURL });\n return client;\n}\n\nexport interface LLMResponse {\n content: string;\n inputTokens: number;\n outputTokens: number;\n}\n\nexport async function generateResponse(\n systemPrompt: string,\n userMessage: string,\n): Promise<LLMResponse> {\n const config = loadConfig();\n const model = config.llm?.model ?? DEFAULT_MODEL;\n\n logger.info(`Calling LLM (${model})...`);\n\n const openai = getClient();\n const response = await openai.chat.completions.create({\n model,\n max_tokens: 2048,\n messages: [\n { role: \"system\", content: systemPrompt },\n { role: \"user\", content: userMessage },\n ],\n });\n\n const content = response.choices[0]?.message?.content ?? \"\";\n const inputTokens = response.usage?.prompt_tokens ?? 0;\n const outputTokens = response.usage?.completion_tokens ?? 0;\n\n logger.info(`LLM response: ${inputTokens} in, ${outputTokens} out`);\n\n return { content, inputTokens, outputTokens };\n}\n\nexport async function chat(\n systemPrompt: string,\n messages: Array<{ role: \"user\" | \"assistant\"; content: string }>,\n): Promise<LLMResponse> {\n const config = loadConfig();\n const model = config.llm?.model ?? DEFAULT_MODEL;\n\n const openai = getClient();\n const response = await openai.chat.completions.create({\n model,\n max_tokens: 2048,\n messages: [\n { role: \"system\", content: systemPrompt },\n ...messages,\n ],\n });\n\n const content = response.choices[0]?.message?.content ?? \"\";\n const inputTokens = response.usage?.prompt_tokens ?? 0;\n const outputTokens = response.usage?.completion_tokens ?? 0;\n\n return { content, inputTokens, outputTokens };\n}\n"],"mappings":";;;;;;;;;;;AAAA,OAAO,YAAY;AACnB,SAAS,cAAc,kBAAkB;AAKzC,IAAI,SAAwB;AAE5B,IAAM,gBAAgB;AACtB,IAAM,mBAAmB;AAElB,SAAS,eAA8B;AAE5C,MAAI,QAAQ,IAAI,aAAa;AAC3B,WAAO,QAAQ,IAAI;AAAA,EACrB;AACA,MAAI,QAAQ,IAAI,mBAAmB;AACjC,WAAO,QAAQ,IAAI;AAAA,EACrB;AACA,MAAI,WAAW,MAAM,MAAM,GAAG;AAC5B,WAAO,aAAa,MAAM,QAAQ,OAAO,EAAE,KAAK;AAAA,EAClD;AACA,SAAO;AACT;AAEO,SAAS,YAAqB;AACnC,SAAO,aAAa,MAAM;AAC5B;AAEA,SAAS,YAAoB;AAC3B,MAAI,OAAQ,QAAO;AACnB,QAAM,SAAS,aAAa;AAC5B,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,2DAA2D;AAAA,EAC7E;AACA,QAAM,SAAS,WAAW;AAC1B,QAAM,UAAU,OAAO,KAAK,WAAW;AACvC,WAAS,IAAI,OAAO,EAAE,QAAQ,QAAQ,CAAC;AACvC,SAAO;AACT;AAQA,eAAsB,iBACpB,cACA,aACsB;AACtB,QAAM,SAAS,WAAW;AAC1B,QAAM,QAAQ,OAAO,KAAK,SAAS;AAEnC,SAAO,KAAK,gBAAgB,KAAK,MAAM;AAEvC,QAAM,SAAS,UAAU;AACzB,QAAM,WAAW,MAAM,OAAO,KAAK,YAAY,OAAO;AAAA,IACpD;AAAA,IACA,YAAY;AAAA,IACZ,UAAU;AAAA,MACR,EAAE,MAAM,UAAU,SAAS,aAAa;AAAA,MACxC,EAAE,MAAM,QAAQ,SAAS,YAAY;AAAA,IACvC;AAAA,EACF,CAAC;AAED,QAAM,UAAU,SAAS,QAAQ,CAAC,GAAG,SAAS,WAAW;AACzD,QAAM,cAAc,SAAS,OAAO,iBAAiB;AACrD,QAAM,eAAe,SAAS,OAAO,qBAAqB;AAE1D,SAAO,KAAK,iBAAiB,WAAW,QAAQ,YAAY,MAAM;AAElE,SAAO,EAAE,SAAS,aAAa,aAAa;AAC9C;AAEA,eAAsB,KACpB,cACA,UACsB;AACtB,QAAM,SAAS,WAAW;AAC1B,QAAM,QAAQ,OAAO,KAAK,SAAS;AAEnC,QAAM,SAAS,UAAU;AACzB,QAAM,WAAW,MAAM,OAAO,KAAK,YAAY,OAAO;AAAA,IACpD;AAAA,IACA,YAAY;AAAA,IACZ,UAAU;AAAA,MACR,EAAE,MAAM,UAAU,SAAS,aAAa;AAAA,MACxC,GAAG;AAAA,IACL;AAAA,EACF,CAAC;AAED,QAAM,UAAU,SAAS,QAAQ,CAAC,GAAG,SAAS,WAAW;AACzD,QAAM,cAAc,SAAS,OAAO,iBAAiB;AACrD,QAAM,eAAe,SAAS,OAAO,qBAAqB;AAE1D,SAAO,EAAE,SAAS,aAAa,aAAa;AAC9C;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/init.ts","../src/x-client/profile-updater.ts"],"sourcesContent":["import { input, select, confirm, password as passwordPrompt } from \"@inquirer/prompts\";\nimport chalk from \"chalk\";\nimport { sporaExists, ensureDirectories } from \"./utils/paths.js\";\nimport { createDefaultConfig, saveConfig } from \"./utils/config.js\";\nimport { saveCredentials, type XCredentials } from \"./utils/crypto.js\";\nimport { loadIdentity } from \"./identity/index.js\";\nimport { updateXProfile } from \"./x-client/profile-updater.js\";\n\n/**\n * Fetch identity from token and save locally\n */\nasync function syncIdentityFromToken(token: string): Promise<void> {\n console.log(chalk.gray(\"Connecting to spora.dev...\\n\"));\n\n const apiUrl = process.env.SPORA_API_URL || \"https://www.spora.social\";\n const response = await fetch(`${apiUrl}/api/v1/connect`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ token }),\n });\n\n if (!response.ok) {\n const errData = await response.json().catch(() => ({}));\n throw new Error(errData.error || `Connection failed: ${response.statusText}`);\n }\n\n const data = await response.json();\n\n if (!data.identity) {\n throw new Error(\"No Spore identity found for this token\");\n }\n\n // Merge media fields\n if (data.media) {\n if (data.media.profileImage) data.identity.profileImage = data.media.profileImage;\n if (data.media.bannerImage) data.identity.bannerImage = data.media.bannerImage;\n }\n\n const { saveIdentity } = await import(\"./identity/index.js\");\n saveIdentity(data.identity);\n\n console.log(chalk.green(`✓ Connected to Spore: ${data.identity.name} (@${data.identity.handle})\\n`));\n\n // Save README if provided\n if (data.readme) {\n const { writeFileSync } = await import(\"node:fs\");\n const { paths } = await import(\"./utils/paths.js\");\n const { join, dirname } = await import(\"node:path\");\n const readmePath = join(dirname(paths.identity), \"IDENTITY.md\");\n writeFileSync(readmePath, data.readme, \"utf-8\");\n console.log(chalk.green(\"✓ Saved identity README\\n\"));\n }\n\n // Save connection token to config\n const { existsSync } = await import(\"node:fs\");\n const { paths } = await import(\"./utils/paths.js\");\n if (existsSync(paths.config)) {\n const { loadConfig, saveConfig } = await import(\"./utils/config.js\");\n const config = loadConfig();\n config.connection = {\n token,\n apiEndpoint: process.env.SPORA_API_URL || \"https://www.spora.social/api/v1\",\n configVersion: config.connection?.configVersion ?? 0,\n };\n saveConfig(config);\n }\n}\n\n/**\n * Login flow: paste token → sync identity → open chat (keys already saved locally)\n */\nasync function loginFlow(): Promise<void> {\n console.log(chalk.bold(\"\\n━━━ Login to Existing Spore ━━━\\n\"));\n console.log(chalk.gray(\"Paste your setup token from spora.dev\"));\n console.log(chalk.gray(\"(It looks like: spora_7e636ac0...)\\n\"));\n\n const token = await input({\n message: \"Setup token:\",\n validate: (val) => val.length > 0 ? true : \"Token is required\",\n });\n\n ensureDirectories();\n\n try {\n await syncIdentityFromToken(token.trim());\n } catch (error) {\n console.log(chalk.red(`\\n✗ ${(error as Error).message}\\n`));\n console.log(chalk.yellow(\"Please check your token and try again.\\n\"));\n process.exit(1);\n }\n\n console.log(chalk.green(\"✓ Logged in!\\n\"));\n console.log(chalk.gray(\"Opening chat interface...\\n\"));\n\n try {\n const { startWebChat } = await import(\"./web-chat/index.js\");\n await startWebChat();\n } catch (error) {\n console.log(chalk.yellow(`Could not start chat interface: ${(error as Error).message}\\n`));\n console.log(chalk.gray(\"You can start it manually with: spora chat\\n\"));\n }\n}\n\n/**\n * Prompt for LLM API key and X credentials\n */\nasync function setupKeys(): Promise<void> {\n // LLM key\n console.log(chalk.bold(\"\\n━━━ LLM API Key ━━━\\n\"));\n console.log(chalk.gray(\"Your Spore uses DeepSeek to think and make decisions.\"));\n console.log(chalk.gray(\"Enter your LLM API key below.\\n\"));\n\n const llmKey = await passwordPrompt({\n message: \"LLM API Key:\",\n mask: \"*\",\n validate: (val: string) => val.length > 0 ? true : \"API key is required\",\n });\n\n const { paths } = await import(\"./utils/paths.js\");\n const { writeFileSync } = await import(\"node:fs\");\n writeFileSync(paths.llmKey, llmKey, \"utf-8\");\n console.log(chalk.green(\"✓ LLM API key saved\\n\"));\n\n // X credentials\n console.log(chalk.bold(\"\\n━━━ Connect Your X Account ━━━\\n\"));\n console.log(chalk.gray(\"Your Spore needs OAuth 1.0a credentials for full X API access.\"));\n console.log(chalk.gray(\"This gives your agent the power to read timelines, post tweets, reply, like, and follow.\\n\"));\n console.log(chalk.cyan(\"How to get these credentials:\"));\n console.log(chalk.gray(\" 1. Go to: \") + chalk.cyan(\"https://developer.x.com/en/portal/dashboard\"));\n console.log(chalk.gray(\" 2. Create or select your app\"));\n console.log(chalk.gray(\" 3. Go to \\\"Keys and tokens\\\" tab\"));\n console.log(chalk.gray(\" 4. Copy all 4 credentials below\\n\"));\n console.log(chalk.yellow(\"Note: You need X Pro account ($200/mo) for posting access.\\n\"));\n\n const apiKey = await passwordPrompt({\n message: \"X API Key (Consumer Key):\",\n mask: \"*\",\n validate: (val: string) => val.length > 0 ? true : \"API Key is required\",\n });\n\n const apiSecret = await passwordPrompt({\n message: \"X API Secret (Consumer Secret):\",\n mask: \"*\",\n validate: (val: string) => val.length > 0 ? true : \"API Secret is required\",\n });\n\n const accessToken = await passwordPrompt({\n message: \"X Access Token:\",\n mask: \"*\",\n validate: (val: string) => val.length > 0 ? true : \"Access Token is required\",\n });\n\n const accessTokenSecret = await passwordPrompt({\n message: \"X Access Token Secret:\",\n mask: \"*\",\n validate: (val: string) => val.length > 0 ? true : \"Access Token Secret is required\",\n });\n\n const bearerToken = await passwordPrompt({\n message: \"X Bearer Token:\",\n mask: \"*\",\n validate: (val: string) => val.length > 0 ? true : \"Bearer Token is required\",\n });\n\n saveCredentials({\n method: \"api\",\n apiKey,\n apiSecret,\n accessToken,\n accessTokenSecret,\n bearerToken,\n });\n console.log(chalk.green(\"✓ X API credentials saved (encrypted)\\n\"));\n}\n\n/**\n * Show completion message and open chat\n */\nasync function showDoneAndOpenChat(): Promise<void> {\n console.log(chalk.green(\"\\n╔═══════════════════════════════════════╗\"));\n console.log(chalk.green.bold(\"║ Setup Complete! ║\"));\n console.log(chalk.green(\"╚═══════════════════════════════════════╝\\n\"));\n\n console.log(chalk.bold.cyan(\"━━━ Your Spore is Ready! ━━━\\n\"));\n console.log(chalk.gray(\"Opening chat interface...\\n\"));\n\n try {\n const { startWebChat } = await import(\"./web-chat/index.js\");\n await startWebChat();\n } catch (error) {\n console.log(chalk.yellow(`Could not start chat interface: ${(error as Error).message}\\n`));\n console.log(chalk.gray(\"You can start it manually with: spora chat\\n\"));\n }\n\n console.log(chalk.bold(\"Quick Start:\\n\"));\n console.log(chalk.cyan(\" spora chat\"));\n console.log(chalk.gray(\" → Talk to your Spore, tell it what to post, how to behave\\n\"));\n console.log(chalk.bold(\"Or start the autonomous agent:\\n\"));\n console.log(chalk.cyan(\" spora start\"));\n console.log(chalk.gray(\" → Your Spore will post and engage autonomously\\n\"));\n console.log(chalk.bold(\"Other commands:\\n\"));\n console.log(chalk.cyan(\" spora create \") + chalk.gray(\"# Create a personality\"));\n console.log(chalk.cyan(\" spora post <text> \") + chalk.gray(\"# Make your Spore post\"));\n console.log(chalk.cyan(\" spora agent-status \") + chalk.gray(\"# Check if agent is running\"));\n console.log(chalk.cyan(\" spora stop \") + chalk.gray(\"# Stop the agent\"));\n console.log(chalk.cyan(\" spora --help \") + chalk.gray(\"# See all commands\\n\"));\n}\n\nexport async function runInit(token?: string): Promise<void> {\n console.log(chalk.bold.cyan(\"\\n╔════════════════════════════════════════╗\"));\n console.log(chalk.bold.cyan(\"║ Welcome to Spora CLI Setup ║\"));\n console.log(chalk.bold.cyan(\"╚════════════════════════════════════════╝\\n\"));\n\n // If token provided via --token flag, this is a new user from the website → full setup\n if (token) {\n ensureDirectories();\n\n console.log(chalk.bold(\"\\n━━━ Connecting Your Spore ━━━\\n\"));\n try {\n await syncIdentityFromToken(token);\n } catch (error) {\n console.log(chalk.red(`\\n✗ ${(error as Error).message}\\n`));\n console.log(chalk.yellow(\"Please check your token and try again.\\n\"));\n process.exit(1);\n }\n\n await setupKeys();\n\n // Update X profile\n console.log(chalk.bold(\"\\n━━━ Updating Your X Profile ━━━\\n\"));\n console.log(chalk.gray(\"Setting up profile picture, banner, and bio to match your Spore...\\n\"));\n try {\n const identity = loadIdentity();\n const result = await updateXProfile(identity);\n if (result.success) {\n console.log(chalk.green(\"✓ Profile updated successfully!\\n\"));\n if (result.updated.length > 0) {\n console.log(chalk.cyan(\"Updated:\"));\n for (const field of result.updated) {\n console.log(chalk.gray(` • ${field}`));\n }\n console.log();\n }\n }\n if (result.errors.length > 0) {\n console.log(chalk.yellow(\"\\nSome updates failed:\"));\n for (const err of result.errors) {\n console.log(chalk.gray(` • ${err}`));\n }\n console.log();\n }\n } catch (error) {\n console.log(chalk.yellow(`Could not update profile: ${(error as Error).message}\\n`));\n console.log(chalk.gray(\"You can manually update your X profile later.\\n\"));\n }\n\n const config = createDefaultConfig({ xMethod: \"api\", xApiTier: \"basic\" });\n config.llm = { provider: \"deepseek\", model: \"deepseek-v3.2-speciale\", baseUrl: \"https://api.llm-stats.com/v1\" };\n config.runtime = { heartbeatIntervalMs: 300_000, actionsPerHeartbeat: 3, enabled: true };\n config.connection = {\n token,\n apiEndpoint: process.env.SPORA_API_URL || \"https://www.spora.social/api/v1\",\n configVersion: 0,\n };\n saveConfig(config);\n\n await showDoneAndOpenChat();\n return;\n }\n\n // No token provided — ask what they want to do\n const action = await select({\n message: \"What would you like to do?\",\n choices: [\n { name: \"Create a new Spore\", value: \"new\" },\n { name: \"Login to existing Spore\", value: \"login\" },\n ],\n });\n\n if (action === \"login\") {\n await loginFlow();\n return;\n }\n\n // \"new\" — full new Spore creation (no token, manual setup)\n ensureDirectories();\n\n await setupKeys();\n\n // Update X profile\n console.log(chalk.bold(\"\\n━━━ Updating Your X Profile ━━━\\n\"));\n console.log(chalk.gray(\"Setting up profile picture, banner, and bio to match your Spore...\\n\"));\n try {\n const identity = loadIdentity();\n const result = await updateXProfile(identity);\n if (result.success) {\n console.log(chalk.green(\"✓ Profile updated successfully!\\n\"));\n if (result.updated.length > 0) {\n console.log(chalk.cyan(\"Updated:\"));\n for (const field of result.updated) {\n console.log(chalk.gray(` • ${field}`));\n }\n console.log();\n }\n }\n if (result.errors.length > 0) {\n console.log(chalk.yellow(\"\\nSome updates failed:\"));\n for (const err of result.errors) {\n console.log(chalk.gray(` • ${err}`));\n }\n console.log();\n }\n } catch (error) {\n console.log(chalk.yellow(`Could not update profile: ${(error as Error).message}\\n`));\n console.log(chalk.gray(\"You can manually update your X profile later.\\n\"));\n }\n\n const config = createDefaultConfig({ xMethod: \"api\", xApiTier: \"basic\" });\n config.llm = { provider: \"deepseek\", model: \"deepseek-v3.2-speciale\", baseUrl: \"https://api.llm-stats.com/v1\" };\n config.runtime = { heartbeatIntervalMs: 300_000, actionsPerHeartbeat: 3, enabled: true };\n saveConfig(config);\n\n await showDoneAndOpenChat();\n}\n","/**\n * X Profile Updater\n * Updates X profile to match Spore identity (name, bio, profile pic, banner)\n */\n\nimport { TwitterApi } from \"twitter-api-v2\";\nimport sharp from \"sharp\";\nimport type { Identity } from \"../identity/schema.js\";\nimport { loadCredentials } from \"../utils/crypto.js\";\n\ninterface ProfileUpdateResult {\n success: boolean;\n updated: string[];\n errors: string[];\n}\n\n/**\n * Update X profile to match Spore identity\n * Requires OAuth 1.0a credentials\n */\nexport async function updateXProfile(identity: Identity): Promise<ProfileUpdateResult> {\n const result: ProfileUpdateResult = {\n success: false,\n updated: [],\n errors: [],\n };\n\n try {\n const creds = loadCredentials();\n if (creds.method !== \"api\") {\n result.errors.push(\"API credentials required\");\n return result;\n }\n\n // Create Twitter API client with OAuth 1.0a credentials\n const client = new TwitterApi({\n appKey: creds.apiKey!,\n appSecret: creds.apiSecret!,\n accessToken: creds.accessToken!,\n accessSecret: creds.accessTokenSecret!,\n });\n\n // Update profile name and bio (username separately to avoid breaking on failure)\n try {\n console.log(`Updating name to: ${identity.name}`);\n console.log(`Updating bio to: ${identity.bio.substring(0, 60)}...`);\n await client.v1.updateAccountProfile({\n name: identity.name,\n description: identity.bio,\n });\n result.updated.push(\"name\", \"bio\");\n console.log(\"Name and bio updated successfully\");\n } catch (error) {\n console.error(\"Name/bio update error:\", error);\n result.errors.push(`Failed to update name/bio: ${(error as Error).message}`);\n }\n\n // Try to update username separately (optional, may fail if taken or restricted)\n if (identity.handle) {\n try {\n console.log(`Attempting to update username to: @${identity.handle}`);\n await client.v1.updateAccountProfile({\n screen_name: identity.handle,\n });\n result.updated.push(\"username\");\n console.log(\"Username updated successfully\");\n } catch (error) {\n // Don't fail the whole update if username change fails\n console.warn(`Could not update username: ${(error as Error).message}`);\n }\n }\n\n // Update profile image if available\n if (identity.profileImage) {\n try {\n console.log(`Downloading profile image from: ${identity.profileImage.substring(0, 60)}...`);\n let imageBuffer = await downloadImage(identity.profileImage);\n console.log(`Downloaded ${(imageBuffer.length / 1024 / 1024).toFixed(2)}MB`);\n\n // Check image dimensions - Twitter requires min 400x400\n const metadata = await sharp(imageBuffer).metadata();\n console.log(`Image dimensions: ${metadata.width}x${metadata.height}`);\n\n if (!metadata.width || !metadata.height || metadata.width < 400 || metadata.height < 400) {\n throw new Error(`Image too small (${metadata.width}x${metadata.height}). Twitter requires minimum 400x400 pixels.`);\n }\n\n // Compress if needed (Twitter profile image limit: 2MB)\n const MAX_PROFILE_SIZE = 2 * 1024 * 1024; // 2MB\n imageBuffer = await compressImageIfNeeded(imageBuffer, MAX_PROFILE_SIZE, \"Profile\");\n\n console.log(`Uploading profile image to X...`);\n await client.v1.updateAccountProfileImage(imageBuffer);\n result.updated.push(\"profile_image\");\n console.log(\"Profile image updated successfully\");\n } catch (error) {\n console.error(\"Profile image error:\", error);\n result.errors.push(`Failed to update profile image: ${(error as Error).message}`);\n }\n } else {\n console.log(\"No profile image URL in identity\");\n }\n\n // Update banner image if available\n if (identity.bannerImage) {\n try {\n console.log(`Downloading banner image from: ${identity.bannerImage.substring(0, 60)}...`);\n let imageBuffer = await downloadImage(identity.bannerImage);\n console.log(`Downloaded ${(imageBuffer.length / 1024 / 1024).toFixed(2)}MB`);\n\n // Compress if needed (Twitter banner limit: 5MB)\n const MAX_BANNER_SIZE = 5 * 1024 * 1024; // 5MB\n imageBuffer = await compressImageIfNeeded(imageBuffer, MAX_BANNER_SIZE, \"Banner\");\n\n console.log(`Uploading banner image to X...`);\n await client.v1.updateAccountProfileBanner(imageBuffer);\n result.updated.push(\"banner_image\");\n console.log(\"Banner image updated successfully\");\n } catch (error) {\n console.error(\"Banner image error:\", error);\n result.errors.push(`Failed to update banner: ${(error as Error).message}`);\n }\n } else {\n console.log(\"No banner image URL in identity\");\n }\n\n result.success = result.updated.length > 0;\n return result;\n } catch (error) {\n result.errors.push((error as Error).message);\n return result;\n }\n}\n\n/**\n * Download image from URL and return as Buffer\n */\nasync function downloadImage(url: string): Promise<Buffer> {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Failed to download image: ${response.statusText}`);\n }\n const arrayBuffer = await response.arrayBuffer();\n return Buffer.from(arrayBuffer);\n}\n\n/**\n * Compress image if it exceeds size limit by resizing\n * @param buffer Original image buffer\n * @param maxSizeBytes Maximum allowed size in bytes\n * @param type \"profile\" or \"banner\" for logging\n */\nasync function compressImageIfNeeded(\n buffer: Buffer,\n maxSizeBytes: number,\n type: string\n): Promise<Buffer> {\n if (buffer.length <= maxSizeBytes) {\n return buffer;\n }\n\n console.log(\n `${type} image is ${(buffer.length / 1024 / 1024).toFixed(2)}MB, resizing to fit ${(maxSizeBytes / 1024 / 1024).toFixed(0)}MB limit...`\n );\n\n // Calculate scale factor to fit within size limit\n const scaleFactor = Math.sqrt(maxSizeBytes / buffer.length) * 0.85; // 85% of target for safety\n\n // Get current dimensions and calculate new size\n const metadata = await sharp(buffer).metadata();\n const newWidth = Math.floor((metadata.width || 1000) * scaleFactor);\n\n // Resize and convert to JPEG with good quality\n const compressed = await sharp(buffer)\n .resize(newWidth, null, { fit: \"inside\", withoutEnlargement: true })\n .jpeg({ quality: 90, progressive: true })\n .toBuffer();\n\n console.log(\n `Resized ${type} image from ${(buffer.length / 1024 / 1024).toFixed(2)}MB to ${(compressed.length / 1024 / 1024).toFixed(2)}MB`\n );\n\n return compressed;\n}\n"],"mappings":"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","names":["paths","saveConfig","config"]}