spora 0.3.5 → 0.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/{chunk-KQ37VL54.js → chunk-2L3N2H2J.js} +4 -4
  2. package/dist/{chunk-PNZ3XK2N.js → chunk-33RBC6EK.js} +3 -3
  3. package/dist/{chunk-JAF57FYU.js → chunk-52D7W3J3.js} +4 -4
  4. package/dist/chunk-52D7W3J3.js.map +1 -0
  5. package/dist/{chunk-GMSK775L.js → chunk-CSVTWZFG.js} +3 -3
  6. package/dist/chunk-CSVTWZFG.js.map +1 -0
  7. package/dist/{chunk-ML4EMUZC.js → chunk-VO22ASDZ.js} +2 -2
  8. package/dist/{chunk-B6VI6L4D.js → chunk-XL67LOSQ.js} +3 -3
  9. package/dist/cli.js +32 -32
  10. package/dist/cli.js.map +1 -1
  11. package/dist/{client-TWYR2IIQ.js → client-6ZQEQIQS.js} +3 -3
  12. package/dist/{client-BGLXHLID.js → client-OJSDO5LF.js} +3 -3
  13. package/dist/{colony-JVBCMZTK.js → colony-RFGN2GMM.js} +3 -3
  14. package/dist/{config-5EPXA325.js → config-4LP52J2E.js} +2 -2
  15. package/dist/{heartbeat-VPRJ4TXU.js → heartbeat-25KM7SUX.js} +7 -7
  16. package/dist/{init-PNFSGSIR.js → init-II73AQIG.js} +10 -10
  17. package/dist/init-II73AQIG.js.map +1 -0
  18. package/dist/{llm-UKK62ZBP.js → llm-2RNHCOGC.js} +3 -3
  19. package/dist/mcp-server.js +20 -20
  20. package/dist/{prompt-builder-VHGZFBL6.js → prompt-builder-64EEQLIZ.js} +4 -4
  21. package/dist/{queue-LNBQWMFX.js → queue-LSXMZYM6.js} +3 -3
  22. package/dist/{web-chat-QADQADSK.js → web-chat-TFMTA3VT.js} +3 -3
  23. package/dist/{x-client-W5IB7XOM.js → x-client-64DT2QIP.js} +3 -3
  24. package/package.json +1 -1
  25. package/dist/chunk-GMSK775L.js.map +0 -1
  26. package/dist/chunk-JAF57FYU.js.map +0 -1
  27. package/dist/init-PNFSGSIR.js.map +0 -1
  28. /package/dist/{chunk-KQ37VL54.js.map → chunk-2L3N2H2J.js.map} +0 -0
  29. /package/dist/{chunk-PNZ3XK2N.js.map → chunk-33RBC6EK.js.map} +0 -0
  30. /package/dist/{chunk-ML4EMUZC.js.map → chunk-VO22ASDZ.js.map} +0 -0
  31. /package/dist/{chunk-B6VI6L4D.js.map → chunk-XL67LOSQ.js.map} +0 -0
  32. /package/dist/{client-TWYR2IIQ.js.map → client-6ZQEQIQS.js.map} +0 -0
  33. /package/dist/{client-BGLXHLID.js.map → client-OJSDO5LF.js.map} +0 -0
  34. /package/dist/{colony-JVBCMZTK.js.map → colony-RFGN2GMM.js.map} +0 -0
  35. /package/dist/{config-5EPXA325.js.map → config-4LP52J2E.js.map} +0 -0
  36. /package/dist/{heartbeat-VPRJ4TXU.js.map → heartbeat-25KM7SUX.js.map} +0 -0
  37. /package/dist/{llm-UKK62ZBP.js.map → llm-2RNHCOGC.js.map} +0 -0
  38. /package/dist/{prompt-builder-VHGZFBL6.js.map → prompt-builder-64EEQLIZ.js.map} +0 -0
  39. /package/dist/{queue-LNBQWMFX.js.map → queue-LSXMZYM6.js.map} +0 -0
  40. /package/dist/{web-chat-QADQADSK.js.map → web-chat-TFMTA3VT.js.map} +0 -0
  41. /package/dist/{x-client-W5IB7XOM.js.map → x-client-64DT2QIP.js.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  loadConfig
3
- } from "./chunk-GMSK775L.js";
3
+ } from "./chunk-CSVTWZFG.js";
4
4
  import {
5
5
  FRAMEWORKS,
6
6
  GOAL_PRESETS,
@@ -388,7 +388,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
388
388
  },
389
389
  async ({ content }) => {
390
390
  try {
391
- const { getXClient } = await import("./x-client-W5IB7XOM.js");
391
+ const { getXClient } = await import("./x-client-64DT2QIP.js");
392
392
  const client = await getXClient();
393
393
  const result = await client.postTweet(content);
394
394
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
@@ -406,7 +406,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
406
406
  },
407
407
  async ({ tweetId, content }) => {
408
408
  try {
409
- const { getXClient } = await import("./x-client-W5IB7XOM.js");
409
+ const { getXClient } = await import("./x-client-64DT2QIP.js");
410
410
  const client = await getXClient();
411
411
  const result = await client.replyToTweet(tweetId, content);
412
412
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
@@ -421,7 +421,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
421
421
  { tweetId: z.string().describe("The ID of the tweet to like") },
422
422
  async ({ tweetId }) => {
423
423
  try {
424
- const { getXClient } = await import("./x-client-W5IB7XOM.js");
424
+ const { getXClient } = await import("./x-client-64DT2QIP.js");
425
425
  const client = await getXClient();
426
426
  const result = await client.likeTweet(tweetId);
427
427
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
@@ -436,7 +436,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
436
436
  { tweetId: z.string().describe("The ID of the tweet to retweet") },
437
437
  async ({ tweetId }) => {
438
438
  try {
439
- const { getXClient } = await import("./x-client-W5IB7XOM.js");
439
+ const { getXClient } = await import("./x-client-64DT2QIP.js");
440
440
  const client = await getXClient();
441
441
  const result = await client.retweet(tweetId);
442
442
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
@@ -451,7 +451,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
451
451
  { userId: z.string().describe("The user ID to follow") },
452
452
  async ({ userId }) => {
453
453
  try {
454
- const { getXClient } = await import("./x-client-W5IB7XOM.js");
454
+ const { getXClient } = await import("./x-client-64DT2QIP.js");
455
455
  const client = await getXClient();
456
456
  const result = await client.followUser(userId);
457
457
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
@@ -466,7 +466,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
466
466
  { userId: z.string().describe("The user ID to unfollow") },
467
467
  async ({ userId }) => {
468
468
  try {
469
- const { getXClient } = await import("./x-client-W5IB7XOM.js");
469
+ const { getXClient } = await import("./x-client-64DT2QIP.js");
470
470
  const client = await getXClient();
471
471
  const result = await client.unfollowUser(userId);
472
472
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
@@ -481,7 +481,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
481
481
  { count: z.number().optional().describe("Number of tweets to fetch (default 20)") },
482
482
  async ({ count }) => {
483
483
  try {
484
- const { getXClient } = await import("./x-client-W5IB7XOM.js");
484
+ const { getXClient } = await import("./x-client-64DT2QIP.js");
485
485
  const client = await getXClient();
486
486
  const result = await client.getTimeline({ count: count ?? 20 });
487
487
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
@@ -496,7 +496,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
496
496
  { count: z.number().optional().describe("Number of mentions to fetch (default 20)") },
497
497
  async ({ count }) => {
498
498
  try {
499
- const { getXClient } = await import("./x-client-W5IB7XOM.js");
499
+ const { getXClient } = await import("./x-client-64DT2QIP.js");
500
500
  const client = await getXClient();
501
501
  const result = await client.getMentions({ count: count ?? 20 });
502
502
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
@@ -514,7 +514,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
514
514
  },
515
515
  async ({ query, count }) => {
516
516
  try {
517
- const { getXClient } = await import("./x-client-W5IB7XOM.js");
517
+ const { getXClient } = await import("./x-client-64DT2QIP.js");
518
518
  const client = await getXClient();
519
519
  const result = await client.searchTweets(query, { count: count ?? 20 });
520
520
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
@@ -529,7 +529,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
529
529
  { handle: z.string().describe("X handle (without @)") },
530
530
  async ({ handle }) => {
531
531
  try {
532
- const { getXClient } = await import("./x-client-W5IB7XOM.js");
532
+ const { getXClient } = await import("./x-client-64DT2QIP.js");
533
533
  const client = await getXClient();
534
534
  const result = await client.getProfile(handle);
535
535
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
@@ -547,7 +547,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
547
547
  },
548
548
  async ({ content, scheduledFor }) => {
549
549
  try {
550
- const { addToQueue } = await import("./queue-LNBQWMFX.js");
550
+ const { addToQueue } = await import("./queue-LSXMZYM6.js");
551
551
  const entry = addToQueue(content, scheduledFor);
552
552
  return {
553
553
  content: [
@@ -565,7 +565,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
565
565
  {},
566
566
  async () => {
567
567
  try {
568
- const { flushQueue } = await import("./queue-LNBQWMFX.js");
568
+ const { flushQueue } = await import("./queue-LSXMZYM6.js");
569
569
  const results = await flushQueue();
570
570
  return {
571
571
  content: [
@@ -586,7 +586,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
586
586
  { message: z.string().optional().describe("Optional message to post to the Colony community") },
587
587
  async ({ message }) => {
588
588
  try {
589
- const { colonyCheckin } = await import("./colony-JVBCMZTK.js");
589
+ const { colonyCheckin } = await import("./colony-RFGN2GMM.js");
590
590
  const result = await colonyCheckin(message);
591
591
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
592
592
  } catch (error) {
@@ -600,7 +600,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
600
600
  {},
601
601
  async () => {
602
602
  try {
603
- const { getColonyMemory } = await import("./colony-JVBCMZTK.js");
603
+ const { getColonyMemory } = await import("./colony-RFGN2GMM.js");
604
604
  const memory = getColonyMemory();
605
605
  return { content: [{ type: "text", text: JSON.stringify(memory, null, 2) }] };
606
606
  } catch (error) {
@@ -614,7 +614,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
614
614
  {},
615
615
  async () => {
616
616
  try {
617
- const { getActivePlans } = await import("./colony-JVBCMZTK.js");
617
+ const { getActivePlans } = await import("./colony-RFGN2GMM.js");
618
618
  const plans = getActivePlans();
619
619
  return {
620
620
  content: [
@@ -637,7 +637,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
637
637
  },
638
638
  async ({ description }) => {
639
639
  try {
640
- const { proposePlan } = await import("./colony-JVBCMZTK.js");
640
+ const { proposePlan } = await import("./colony-RFGN2GMM.js");
641
641
  const result = await proposePlan(description);
642
642
  if (result.success) {
643
643
  return {
@@ -660,7 +660,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
660
660
  },
661
661
  async ({ planId }) => {
662
662
  try {
663
- const { joinPlan } = await import("./colony-JVBCMZTK.js");
663
+ const { joinPlan } = await import("./colony-RFGN2GMM.js");
664
664
  const result = await joinPlan(planId);
665
665
  if (result.success) {
666
666
  return { content: [{ type: "text", text: "Joined the plan! Go execute it." }] };
@@ -679,7 +679,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
679
679
  },
680
680
  async ({ status }) => {
681
681
  try {
682
- const { postStatus } = await import("./colony-JVBCMZTK.js");
682
+ const { postStatus } = await import("./colony-RFGN2GMM.js");
683
683
  const result = await postStatus(status);
684
684
  if (result.success) {
685
685
  return { content: [{ type: "text", text: "Status posted to the Colony." }] };
@@ -696,7 +696,7 @@ Identity saved. Your Spore is alive. Use spora_get_identity to read the full doc
696
696
  {},
697
697
  async () => {
698
698
  try {
699
- const { getTodaysActivity } = await import("./colony-JVBCMZTK.js");
699
+ const { getTodaysActivity } = await import("./colony-RFGN2GMM.js");
700
700
  const activity = getTodaysActivity();
701
701
  return {
702
702
  content: [
@@ -3,9 +3,9 @@ import {
3
3
  buildHeartbeatUserMessage,
4
4
  buildModeSpecificUserMessage,
5
5
  buildSystemPrompt
6
- } from "./chunk-PNZ3XK2N.js";
7
- import "./chunk-ML4EMUZC.js";
8
- import "./chunk-GMSK775L.js";
6
+ } from "./chunk-33RBC6EK.js";
7
+ import "./chunk-VO22ASDZ.js";
8
+ import "./chunk-CSVTWZFG.js";
9
9
  import "./chunk-FTFTB5Y5.js";
10
10
  import "./chunk-UCCAF2ZO.js";
11
11
  import "./chunk-V6ZNR2SI.js";
@@ -16,4 +16,4 @@ export {
16
16
  buildModeSpecificUserMessage,
17
17
  buildSystemPrompt
18
18
  };
19
- //# sourceMappingURL=prompt-builder-VHGZFBL6.js.map
19
+ //# sourceMappingURL=prompt-builder-64EEQLIZ.js.map
@@ -2,8 +2,8 @@ import {
2
2
  addToQueue,
3
3
  flushQueue,
4
4
  showQueue
5
- } from "./chunk-B6VI6L4D.js";
6
- import "./chunk-GMSK775L.js";
5
+ } from "./chunk-XL67LOSQ.js";
6
+ import "./chunk-CSVTWZFG.js";
7
7
  import "./chunk-UCCAF2ZO.js";
8
8
  import "./chunk-6KCIAMHL.js";
9
9
  export {
@@ -11,4 +11,4 @@ export {
11
11
  flushQueue,
12
12
  showQueue
13
13
  };
14
- //# sourceMappingURL=queue-LNBQWMFX.js.map
14
+ //# sourceMappingURL=queue-LSXMZYM6.js.map
@@ -181,11 +181,11 @@ async function startWebChat() {
181
181
  server.setMessageHandler(async (message) => {
182
182
  try {
183
183
  if (!systemPrompt || messageCount % 10 === 0) {
184
- const { buildChatPrompt } = await import("./prompt-builder-VHGZFBL6.js");
184
+ const { buildChatPrompt } = await import("./prompt-builder-64EEQLIZ.js");
185
185
  systemPrompt = buildChatPrompt();
186
186
  }
187
187
  messageCount++;
188
- const { hasLLMKey, chat: chatLLM } = await import("./llm-UKK62ZBP.js");
188
+ const { hasLLMKey, chat: chatLLM } = await import("./llm-2RNHCOGC.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-QADQADSK.js.map
253
+ //# sourceMappingURL=web-chat-TFMTA3VT.js.map
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  getXClient,
3
3
  resetXClient
4
- } from "./chunk-KQ37VL54.js";
5
- import "./chunk-GMSK775L.js";
4
+ } from "./chunk-2L3N2H2J.js";
5
+ import "./chunk-CSVTWZFG.js";
6
6
  import "./chunk-UCCAF2ZO.js";
7
7
  import "./chunk-6KCIAMHL.js";
8
8
  export {
9
9
  getXClient,
10
10
  resetXClient
11
11
  };
12
- //# sourceMappingURL=x-client-W5IB7XOM.js.map
12
+ //# sourceMappingURL=x-client-64DT2QIP.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spora",
3
- "version": "0.3.5",
3
+ "version": "0.3.6",
4
4
  "description": "AI agents (Spores) that autonomously manage X/Twitter accounts",
5
5
  "type": "module",
6
6
  "author": "Spora",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/utils/config.ts"],"sourcesContent":["import { readFileSync, writeFileSync, existsSync } from \"node:fs\";\nimport { z } from \"zod\";\nimport { paths, ensureDirectories } from \"./paths.js\";\n\nexport const ConfigSchema = z.object({\n version: z.literal(1),\n xMethod: z.enum([\"api\", \"browser\"]),\n xApiTier: z.enum([\"free\", \"basic\"]).optional(),\n\n credits: z.object({\n monthlyPostLimit: z.number(),\n postsUsedThisMonth: z.number(),\n resetDate: z.string(),\n }),\n\n schedule: z.object({\n postsPerDay: z.number(),\n activeHoursStart: z.number().min(0).max(23),\n activeHoursEnd: z.number().min(0).max(23),\n timezone: z.string(),\n }),\n\n llm: z.object({\n provider: z.enum([\"anthropic\", \"openai\", \"deepseek\"]).default(\"deepseek\"),\n model: z.string().default(\"deepseek-v3.2-speciale\"),\n baseUrl: z.string().default(\"https://api.llm-stats.com/v1\"),\n }).optional(),\n\n runtime: z.object({\n heartbeatIntervalMs: z.number().default(300_000),\n actionsPerHeartbeat: z.number().default(3),\n enabled: z.boolean().default(false),\n\n // Mode system configuration\n modeSystem: z.object({\n enabled: z.boolean().default(true),\n allowRestMode: z.boolean().default(true),\n modeWeightOverrides: z.record(z.number()).optional(),\n }).optional(),\n\n // Curiosity system configuration\n curiositySystem: z.object({\n enabled: z.boolean().default(true),\n explorationChance: z.number().default(0.15),\n maxSearchesPerHeartbeat: z.number().default(3),\n }).optional(),\n\n // Mission system configuration\n missionSystem: z.object({\n enabled: z.boolean().default(true),\n maxActiveMissions: z.number().default(5),\n }).optional(),\n\n // Variation/mood system configuration\n variationSystem: z.object({\n enabled: z.boolean().default(true),\n moodDriftRate: z.number().default(0.1),\n }).optional(),\n }).optional(),\n\n connection: z.object({\n token: z.string().optional(),\n apiEndpoint: z.string().default(\"https://spora.dev/api/v1\"),\n lastSync: z.string().optional(),\n configVersion: z.number().default(0),\n }).optional(),\n});\n\nexport type Config = z.infer<typeof ConfigSchema>;\n\nexport function loadConfig(): Config {\n if (!existsSync(paths.config)) {\n throw new Error(\"Spora not initialized. Run `spora init` first.\");\n }\n const raw = readFileSync(paths.config, \"utf-8\");\n return ConfigSchema.parse(JSON.parse(raw));\n}\n\nexport function saveConfig(config: Config): void {\n ensureDirectories();\n ConfigSchema.parse(config);\n writeFileSync(paths.config, JSON.stringify(config, null, 2));\n}\n\nexport function createDefaultConfig(overrides: {\n xMethod: \"api\" | \"browser\";\n xApiTier?: \"free\" | \"basic\";\n timezone?: string;\n}): Config {\n const monthlyLimit = overrides.xApiTier === \"basic\" ? 10000 : 500;\n const now = new Date();\n const resetDate = new Date(now.getFullYear(), now.getMonth() + 1, 1).toISOString();\n\n return {\n version: 1,\n xMethod: overrides.xMethod,\n xApiTier: overrides.xApiTier,\n credits: {\n monthlyPostLimit: monthlyLimit,\n postsUsedThisMonth: 0,\n resetDate,\n },\n schedule: {\n postsPerDay: Math.floor(monthlyLimit / 30),\n activeHoursStart: 8,\n activeHoursEnd: 22,\n timezone: overrides.timezone ?? Intl.DateTimeFormat().resolvedOptions().timeZone,\n },\n };\n}\n"],"mappings":";;;;;;AAAA,SAAS,cAAc,eAAe,kBAAkB;AACxD,SAAS,SAAS;AAGX,IAAM,eAAe,EAAE,OAAO;AAAA,EACnC,SAAS,EAAE,QAAQ,CAAC;AAAA,EACpB,SAAS,EAAE,KAAK,CAAC,OAAO,SAAS,CAAC;AAAA,EAClC,UAAU,EAAE,KAAK,CAAC,QAAQ,OAAO,CAAC,EAAE,SAAS;AAAA,EAE7C,SAAS,EAAE,OAAO;AAAA,IAChB,kBAAkB,EAAE,OAAO;AAAA,IAC3B,oBAAoB,EAAE,OAAO;AAAA,IAC7B,WAAW,EAAE,OAAO;AAAA,EACtB,CAAC;AAAA,EAED,UAAU,EAAE,OAAO;AAAA,IACjB,aAAa,EAAE,OAAO;AAAA,IACtB,kBAAkB,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE;AAAA,IAC1C,gBAAgB,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE;AAAA,IACxC,UAAU,EAAE,OAAO;AAAA,EACrB,CAAC;AAAA,EAED,KAAK,EAAE,OAAO;AAAA,IACZ,UAAU,EAAE,KAAK,CAAC,aAAa,UAAU,UAAU,CAAC,EAAE,QAAQ,UAAU;AAAA,IACxE,OAAO,EAAE,OAAO,EAAE,QAAQ,wBAAwB;AAAA,IAClD,SAAS,EAAE,OAAO,EAAE,QAAQ,8BAA8B;AAAA,EAC5D,CAAC,EAAE,SAAS;AAAA,EAEZ,SAAS,EAAE,OAAO;AAAA,IAChB,qBAAqB,EAAE,OAAO,EAAE,QAAQ,GAAO;AAAA,IAC/C,qBAAqB,EAAE,OAAO,EAAE,QAAQ,CAAC;AAAA,IACzC,SAAS,EAAE,QAAQ,EAAE,QAAQ,KAAK;AAAA;AAAA,IAGlC,YAAY,EAAE,OAAO;AAAA,MACnB,SAAS,EAAE,QAAQ,EAAE,QAAQ,IAAI;AAAA,MACjC,eAAe,EAAE,QAAQ,EAAE,QAAQ,IAAI;AAAA,MACvC,qBAAqB,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,IACrD,CAAC,EAAE,SAAS;AAAA;AAAA,IAGZ,iBAAiB,EAAE,OAAO;AAAA,MACxB,SAAS,EAAE,QAAQ,EAAE,QAAQ,IAAI;AAAA,MACjC,mBAAmB,EAAE,OAAO,EAAE,QAAQ,IAAI;AAAA,MAC1C,yBAAyB,EAAE,OAAO,EAAE,QAAQ,CAAC;AAAA,IAC/C,CAAC,EAAE,SAAS;AAAA;AAAA,IAGZ,eAAe,EAAE,OAAO;AAAA,MACtB,SAAS,EAAE,QAAQ,EAAE,QAAQ,IAAI;AAAA,MACjC,mBAAmB,EAAE,OAAO,EAAE,QAAQ,CAAC;AAAA,IACzC,CAAC,EAAE,SAAS;AAAA;AAAA,IAGZ,iBAAiB,EAAE,OAAO;AAAA,MACxB,SAAS,EAAE,QAAQ,EAAE,QAAQ,IAAI;AAAA,MACjC,eAAe,EAAE,OAAO,EAAE,QAAQ,GAAG;AAAA,IACvC,CAAC,EAAE,SAAS;AAAA,EACd,CAAC,EAAE,SAAS;AAAA,EAEZ,YAAY,EAAE,OAAO;AAAA,IACnB,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,IAC3B,aAAa,EAAE,OAAO,EAAE,QAAQ,0BAA0B;AAAA,IAC1D,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,IAC9B,eAAe,EAAE,OAAO,EAAE,QAAQ,CAAC;AAAA,EACrC,CAAC,EAAE,SAAS;AACd,CAAC;AAIM,SAAS,aAAqB;AACnC,MAAI,CAAC,WAAW,MAAM,MAAM,GAAG;AAC7B,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AACA,QAAM,MAAM,aAAa,MAAM,QAAQ,OAAO;AAC9C,SAAO,aAAa,MAAM,KAAK,MAAM,GAAG,CAAC;AAC3C;AAEO,SAAS,WAAW,QAAsB;AAC/C,oBAAkB;AAClB,eAAa,MAAM,MAAM;AACzB,gBAAc,MAAM,QAAQ,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAC7D;AAEO,SAAS,oBAAoB,WAIzB;AACT,QAAM,eAAe,UAAU,aAAa,UAAU,MAAQ;AAC9D,QAAM,MAAM,oBAAI,KAAK;AACrB,QAAM,YAAY,IAAI,KAAK,IAAI,YAAY,GAAG,IAAI,SAAS,IAAI,GAAG,CAAC,EAAE,YAAY;AAEjF,SAAO;AAAA,IACL,SAAS;AAAA,IACT,SAAS,UAAU;AAAA,IACnB,UAAU,UAAU;AAAA,IACpB,SAAS;AAAA,MACP,kBAAkB;AAAA,MAClB,oBAAoB;AAAA,MACpB;AAAA,IACF;AAAA,IACA,UAAU;AAAA,MACR,aAAa,KAAK,MAAM,eAAe,EAAE;AAAA,MACzC,kBAAkB;AAAA,MAClB,gBAAgB;AAAA,MAChB,UAAU,UAAU,YAAY,KAAK,eAAe,EAAE,gBAAgB,EAAE;AAAA,IAC1E;AAAA,EACF;AACF;","names":[]}
@@ -1 +0,0 @@
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":[]}
@@ -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 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"]}