spora 0.2.53 → 0.3.0

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 (87) hide show
  1. package/dist/{account-creator-WYY4YVJP.js → account-creator-SETL5CGT.js} +5 -5
  2. package/dist/chunk-FCAK5FYQ.js +127 -0
  3. package/dist/chunk-FCAK5FYQ.js.map +1 -0
  4. package/dist/{chunk-CIWFFTSP.js → chunk-GJFBWIW3.js} +2 -2
  5. package/dist/{chunk-7UHJLJNI.js → chunk-HERI4RPY.js} +2 -2
  6. package/dist/{chunk-E4DZYHGF.js → chunk-J7J557HV.js} +2 -2
  7. package/dist/{chunk-YF7WWJRO.js → chunk-JWMADEQO.js} +3 -3
  8. package/dist/chunk-LRKBNKMQ.js +79 -0
  9. package/dist/chunk-LRKBNKMQ.js.map +1 -0
  10. package/dist/{chunk-K6FZPWXD.js → chunk-NLWU5432.js} +5 -5
  11. package/dist/{chunk-VL4UUCMS.js → chunk-POEDIDM6.js} +2 -2
  12. package/dist/{chunk-5GPXH253.js → chunk-Q7YS3AIK.js} +5 -2
  13. package/dist/chunk-Q7YS3AIK.js.map +1 -0
  14. package/dist/{chunk-3NW3VIN5.js → chunk-QHFM2YW6.js} +13 -6
  15. package/dist/chunk-QHFM2YW6.js.map +1 -0
  16. package/dist/{chunk-DE772QJH.js → chunk-RNVEWVDN.js} +26 -2
  17. package/dist/chunk-RNVEWVDN.js.map +1 -0
  18. package/dist/{chunk-LTAYL5E2.js → chunk-SUFTVQME.js} +5 -5
  19. package/dist/{chunk-LTAYL5E2.js.map → chunk-SUFTVQME.js.map} +1 -1
  20. package/dist/{chunk-T3U56JW4.js → chunk-SXMDYUK3.js} +2 -2
  21. package/dist/{chunk-XJBOOX7N.js → chunk-YZ7RWJ6Z.js} +46 -10
  22. package/dist/chunk-YZ7RWJ6Z.js.map +1 -0
  23. package/dist/{chunk-H66LVLSP.js → chunk-ZN63YLI6.js} +144 -26
  24. package/dist/chunk-ZN63YLI6.js.map +1 -0
  25. package/dist/cli.js +40 -40
  26. package/dist/{client-YR2RA56D.js → client-23THPNVL.js} +32 -7
  27. package/dist/{client-YR2RA56D.js.map → client-23THPNVL.js.map} +1 -1
  28. package/dist/{client-KXYBQUMD.js → client-NVI3ZD4G.js} +11 -8
  29. package/dist/{client-KXYBQUMD.js.map → client-NVI3ZD4G.js.map} +1 -1
  30. package/dist/{colony-4EYP6EPG.js → colony-J4EZQI37.js} +7 -7
  31. package/dist/{config-BRWV7X4S.js → config-QRBOL4NX.js} +3 -3
  32. package/dist/{crypto-CK5M4W2X.js → crypto-ZVWJLD2J.js} +3 -3
  33. package/dist/decision-engine-WBD36PZI.js +19 -0
  34. package/dist/{heartbeat-QFWU47KI.js → heartbeat-GBT4G4C6.js} +129 -25
  35. package/dist/heartbeat-GBT4G4C6.js.map +1 -0
  36. package/dist/{identity-SJ77KTVG.js → identity-LN2R4KJU.js} +3 -3
  37. package/dist/{image-search-6RGKTFRT.js → image-search-SZVMGWLN.js} +3 -3
  38. package/dist/{init-FRZDY4MB.js → init-QWOV7F5B.js} +12 -12
  39. package/dist/llm-MHZG2VHU.js +16 -0
  40. package/dist/mcp-server.js +24 -24
  41. package/dist/{memory-ZC3LUAUW.js → memory-J6AYZ5Y2.js} +5 -3
  42. package/dist/{memory-SYYAGNJ5.js → memory-JMXU3UXR.js} +3 -3
  43. package/dist/{paths-IL7YUMNP.js → paths-KXOWF2B2.js} +2 -2
  44. package/dist/performance-7G6R6ELJ.js +18 -0
  45. package/dist/prompt-builder-IY2SLZ7F.js +25 -0
  46. package/dist/queue-MLRTMJRE.js +14 -0
  47. package/dist/strategy-TOVFBIZQ.js +12 -0
  48. package/dist/strategy-TOVFBIZQ.js.map +1 -0
  49. package/dist/{web-chat-BX4WCEDD.js → web-chat-2BAWTCGU.js} +108 -29
  50. package/dist/web-chat-2BAWTCGU.js.map +1 -0
  51. package/dist/x-client-HUXCQOAW.js +12 -0
  52. package/dist/x-client-HUXCQOAW.js.map +1 -0
  53. package/package.json +1 -1
  54. package/dist/chunk-3NW3VIN5.js.map +0 -1
  55. package/dist/chunk-5GPXH253.js.map +0 -1
  56. package/dist/chunk-DE772QJH.js.map +0 -1
  57. package/dist/chunk-H66LVLSP.js.map +0 -1
  58. package/dist/chunk-XJBOOX7N.js.map +0 -1
  59. package/dist/decision-engine-YQDGNP3C.js +0 -18
  60. package/dist/heartbeat-QFWU47KI.js.map +0 -1
  61. package/dist/llm-5FY4H7WC.js +0 -16
  62. package/dist/prompt-builder-V7ZM73TA.js +0 -19
  63. package/dist/queue-IDNLFXWC.js +0 -14
  64. package/dist/web-chat-BX4WCEDD.js.map +0 -1
  65. package/dist/x-client-DFMW2PX7.js +0 -12
  66. /package/dist/{account-creator-WYY4YVJP.js.map → account-creator-SETL5CGT.js.map} +0 -0
  67. /package/dist/{chunk-CIWFFTSP.js.map → chunk-GJFBWIW3.js.map} +0 -0
  68. /package/dist/{chunk-7UHJLJNI.js.map → chunk-HERI4RPY.js.map} +0 -0
  69. /package/dist/{chunk-E4DZYHGF.js.map → chunk-J7J557HV.js.map} +0 -0
  70. /package/dist/{chunk-YF7WWJRO.js.map → chunk-JWMADEQO.js.map} +0 -0
  71. /package/dist/{chunk-K6FZPWXD.js.map → chunk-NLWU5432.js.map} +0 -0
  72. /package/dist/{chunk-VL4UUCMS.js.map → chunk-POEDIDM6.js.map} +0 -0
  73. /package/dist/{chunk-T3U56JW4.js.map → chunk-SXMDYUK3.js.map} +0 -0
  74. /package/dist/{colony-4EYP6EPG.js.map → colony-J4EZQI37.js.map} +0 -0
  75. /package/dist/{config-BRWV7X4S.js.map → config-QRBOL4NX.js.map} +0 -0
  76. /package/dist/{crypto-CK5M4W2X.js.map → crypto-ZVWJLD2J.js.map} +0 -0
  77. /package/dist/{decision-engine-YQDGNP3C.js.map → decision-engine-WBD36PZI.js.map} +0 -0
  78. /package/dist/{identity-SJ77KTVG.js.map → identity-LN2R4KJU.js.map} +0 -0
  79. /package/dist/{image-search-6RGKTFRT.js.map → image-search-SZVMGWLN.js.map} +0 -0
  80. /package/dist/{init-FRZDY4MB.js.map → init-QWOV7F5B.js.map} +0 -0
  81. /package/dist/{llm-5FY4H7WC.js.map → llm-MHZG2VHU.js.map} +0 -0
  82. /package/dist/{memory-SYYAGNJ5.js.map → memory-J6AYZ5Y2.js.map} +0 -0
  83. /package/dist/{memory-ZC3LUAUW.js.map → memory-JMXU3UXR.js.map} +0 -0
  84. /package/dist/{paths-IL7YUMNP.js.map → paths-KXOWF2B2.js.map} +0 -0
  85. /package/dist/{prompt-builder-V7ZM73TA.js.map → performance-7G6R6ELJ.js.map} +0 -0
  86. /package/dist/{queue-IDNLFXWC.js.map → prompt-builder-IY2SLZ7F.js.map} +0 -0
  87. /package/dist/{x-client-DFMW2PX7.js.map → queue-MLRTMJRE.js.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  logger
3
- } from "./chunk-E4DZYHGF.js";
4
- import "./chunk-5GPXH253.js";
3
+ } from "./chunk-J7J557HV.js";
4
+ import "./chunk-Q7YS3AIK.js";
5
5
 
6
6
  // src/account-creator/x-signup.ts
7
7
  import { chromium } from "playwright";
@@ -71,7 +71,7 @@ async function checkInbox(inboxId, waitMs = 6e4) {
71
71
  // src/account-creator/x-signup.ts
72
72
  async function debugScreenshot(page, step) {
73
73
  try {
74
- const { paths, ensureDirectories } = await import("./paths-IL7YUMNP.js");
74
+ const { paths, ensureDirectories } = await import("./paths-KXOWF2B2.js");
75
75
  ensureDirectories();
76
76
  const screenshotPath = `${paths.dataDir}/debug-${step}.png`;
77
77
  await page.screenshot({ path: screenshotPath });
@@ -465,7 +465,7 @@ async function createXAccount(options) {
465
465
  async function saveSession(context) {
466
466
  const storageState = await context.storageState();
467
467
  const { writeFileSync } = await import("fs");
468
- const { paths, ensureDirectories } = await import("./paths-IL7YUMNP.js");
468
+ const { paths, ensureDirectories } = await import("./paths-KXOWF2B2.js");
469
469
  ensureDirectories();
470
470
  writeFileSync(paths.browserAuth, JSON.stringify(storageState));
471
471
  logger.info("Browser session saved.");
@@ -495,4 +495,4 @@ async function provisionAccount(options) {
495
495
  export {
496
496
  provisionAccount
497
497
  };
498
- //# sourceMappingURL=account-creator-WYY4YVJP.js.map
498
+ //# sourceMappingURL=account-creator-SETL5CGT.js.map
@@ -0,0 +1,127 @@
1
+ import {
2
+ paths
3
+ } from "./chunk-Q7YS3AIK.js";
4
+
5
+ // src/memory/performance.ts
6
+ import { existsSync, readFileSync, writeFileSync } from "fs";
7
+ function loadPerformance() {
8
+ if (!existsSync(paths.performance)) {
9
+ return { trackedPosts: [], selfMetrics: [] };
10
+ }
11
+ try {
12
+ return JSON.parse(readFileSync(paths.performance, "utf-8"));
13
+ } catch {
14
+ return { trackedPosts: [], selfMetrics: [] };
15
+ }
16
+ }
17
+ function savePerformance(data) {
18
+ writeFileSync(paths.performance, JSON.stringify(data, null, 2));
19
+ }
20
+ function trackPost(tweetId, content, type) {
21
+ const data = loadPerformance();
22
+ if (data.trackedPosts.some((p) => p.tweetId === tweetId)) return;
23
+ data.trackedPosts.push({
24
+ tweetId,
25
+ content,
26
+ type,
27
+ postedAt: (/* @__PURE__ */ new Date()).toISOString(),
28
+ metrics: [],
29
+ retired: false
30
+ });
31
+ savePerformance(data);
32
+ }
33
+ function getActiveTrackedPosts() {
34
+ const data = loadPerformance();
35
+ return data.trackedPosts.filter((p) => !p.retired);
36
+ }
37
+ function updatePostMetrics(tweetId, metric) {
38
+ const data = loadPerformance();
39
+ const post = data.trackedPosts.find((p) => p.tweetId === tweetId);
40
+ if (!post) return;
41
+ post.metrics.push(metric);
42
+ savePerformance(data);
43
+ }
44
+ function retireOldPosts() {
45
+ const data = loadPerformance();
46
+ const cutoff = Date.now() - 72 * 60 * 60 * 1e3;
47
+ let changed = false;
48
+ for (const post of data.trackedPosts) {
49
+ if (!post.retired && new Date(post.postedAt).getTime() < cutoff) {
50
+ post.retired = true;
51
+ changed = true;
52
+ }
53
+ }
54
+ const pruneCutoff = Date.now() - 30 * 24 * 60 * 60 * 1e3;
55
+ const before = data.trackedPosts.length;
56
+ data.trackedPosts = data.trackedPosts.filter(
57
+ (p) => !p.retired || new Date(p.postedAt).getTime() > pruneCutoff
58
+ );
59
+ if (data.trackedPosts.length !== before) changed = true;
60
+ if (changed) savePerformance(data);
61
+ }
62
+ function updateSelfMetrics(metric) {
63
+ const data = loadPerformance();
64
+ data.selfMetrics.push(metric);
65
+ if (data.selfMetrics.length > 100) {
66
+ data.selfMetrics = data.selfMetrics.slice(-100);
67
+ }
68
+ savePerformance(data);
69
+ }
70
+ function getPerformanceSummary() {
71
+ const data = loadPerformance();
72
+ const lines = [];
73
+ const oneDayAgo = Date.now() - 24 * 60 * 60 * 1e3;
74
+ const recentPosts = data.trackedPosts.filter(
75
+ (p) => new Date(p.postedAt).getTime() > oneDayAgo
76
+ );
77
+ if (recentPosts.length > 0) {
78
+ const postStats = recentPosts.map((p) => {
79
+ const latest = p.metrics.length > 0 ? p.metrics[p.metrics.length - 1] : null;
80
+ return {
81
+ content: p.content,
82
+ type: p.type,
83
+ likes: latest?.likes ?? 0,
84
+ retweets: latest?.retweets ?? 0,
85
+ replies: latest?.replies ?? 0
86
+ };
87
+ });
88
+ const totalLikes = postStats.reduce((s, p) => s + p.likes, 0);
89
+ const totalRTs = postStats.reduce((s, p) => s + p.retweets, 0);
90
+ const avgLikes = Math.round(totalLikes / postStats.length);
91
+ lines.push(`- Last 24h: ${postStats.length} posts, avg ${avgLikes} likes, ${totalRTs} total retweets`);
92
+ const sorted = [...postStats].sort((a, b) => b.likes - a.likes);
93
+ if (sorted.length > 0 && sorted[0].likes > 0) {
94
+ lines.push(`- Best performing: "${sorted[0].content.slice(0, 60)}..." (${sorted[0].likes} likes, ${sorted[0].retweets} RTs)`);
95
+ }
96
+ if (sorted.length > 1) {
97
+ const worst = sorted[sorted.length - 1];
98
+ lines.push(`- Lowest performing: "${worst.content.slice(0, 60)}..." (${worst.likes} likes)`);
99
+ }
100
+ } else {
101
+ lines.push("- No tracked posts in the last 24 hours yet.");
102
+ }
103
+ if (data.selfMetrics.length > 0) {
104
+ const latest = data.selfMetrics[data.selfMetrics.length - 1];
105
+ lines.push(`- Followers: ${latest.followers} | Following: ${latest.following} | Total tweets: ${latest.totalTweets}`);
106
+ const dayAgoMetric = data.selfMetrics.find(
107
+ (m) => Math.abs(new Date(m.checkedAt).getTime() - (Date.now() - 24 * 60 * 60 * 1e3)) < 12 * 60 * 60 * 1e3
108
+ );
109
+ if (dayAgoMetric) {
110
+ const diff = latest.followers - dayAgoMetric.followers;
111
+ if (diff !== 0) {
112
+ lines.push(`- Follower trend: ${diff > 0 ? "+" : ""}${diff} in the last ~24h`);
113
+ }
114
+ }
115
+ }
116
+ return lines.length > 0 ? lines.join("\n") : "";
117
+ }
118
+
119
+ export {
120
+ trackPost,
121
+ getActiveTrackedPosts,
122
+ updatePostMetrics,
123
+ retireOldPosts,
124
+ updateSelfMetrics,
125
+ getPerformanceSummary
126
+ };
127
+ //# sourceMappingURL=chunk-FCAK5FYQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/memory/performance.ts"],"sourcesContent":["import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { paths } from \"../utils/paths.js\";\n\nexport interface EngagementMetric {\n checkedAt: string;\n likes: number;\n retweets: number;\n replies: number;\n}\n\nexport interface TrackedPost {\n tweetId: string;\n content: string;\n type: \"post\" | \"reply\";\n postedAt: string;\n metrics: EngagementMetric[];\n retired: boolean;\n}\n\nexport interface SelfMetric {\n checkedAt: string;\n followers: number;\n following: number;\n totalTweets: number;\n}\n\nexport interface PerformanceData {\n trackedPosts: TrackedPost[];\n selfMetrics: SelfMetric[];\n}\n\nfunction loadPerformance(): PerformanceData {\n if (!existsSync(paths.performance)) {\n return { trackedPosts: [], selfMetrics: [] };\n }\n try {\n return JSON.parse(readFileSync(paths.performance, \"utf-8\"));\n } catch {\n return { trackedPosts: [], selfMetrics: [] };\n }\n}\n\nfunction savePerformance(data: PerformanceData): void {\n writeFileSync(paths.performance, JSON.stringify(data, null, 2));\n}\n\nexport function trackPost(tweetId: string, content: string, type: \"post\" | \"reply\"): void {\n const data = loadPerformance();\n // Don't double-track\n if (data.trackedPosts.some(p => p.tweetId === tweetId)) return;\n data.trackedPosts.push({\n tweetId,\n content,\n type,\n postedAt: new Date().toISOString(),\n metrics: [],\n retired: false,\n });\n savePerformance(data);\n}\n\nexport function getActiveTrackedPosts(): TrackedPost[] {\n const data = loadPerformance();\n return data.trackedPosts.filter(p => !p.retired);\n}\n\nexport function updatePostMetrics(tweetId: string, metric: EngagementMetric): void {\n const data = loadPerformance();\n const post = data.trackedPosts.find(p => p.tweetId === tweetId);\n if (!post) return;\n post.metrics.push(metric);\n savePerformance(data);\n}\n\nexport function retireOldPosts(): void {\n const data = loadPerformance();\n const cutoff = Date.now() - 72 * 60 * 60 * 1000; // 72 hours\n let changed = false;\n for (const post of data.trackedPosts) {\n if (!post.retired && new Date(post.postedAt).getTime() < cutoff) {\n post.retired = true;\n changed = true;\n }\n }\n // Also prune very old retired posts (older than 30 days) to prevent file bloat\n const pruneCutoff = Date.now() - 30 * 24 * 60 * 60 * 1000;\n const before = data.trackedPosts.length;\n data.trackedPosts = data.trackedPosts.filter(\n p => !p.retired || new Date(p.postedAt).getTime() > pruneCutoff\n );\n if (data.trackedPosts.length !== before) changed = true;\n if (changed) savePerformance(data);\n}\n\nexport function updateSelfMetrics(metric: SelfMetric): void {\n const data = loadPerformance();\n data.selfMetrics.push(metric);\n // Keep only last 100 snapshots\n if (data.selfMetrics.length > 100) {\n data.selfMetrics = data.selfMetrics.slice(-100);\n }\n savePerformance(data);\n}\n\nexport function getPerformanceSummary(): string {\n const data = loadPerformance();\n const lines: string[] = [];\n\n // Post performance (last 24h)\n const oneDayAgo = Date.now() - 24 * 60 * 60 * 1000;\n const recentPosts = data.trackedPosts.filter(\n p => new Date(p.postedAt).getTime() > oneDayAgo\n );\n\n if (recentPosts.length > 0) {\n // Get latest metrics for each post\n const postStats = recentPosts.map(p => {\n const latest = p.metrics.length > 0 ? p.metrics[p.metrics.length - 1] : null;\n return {\n content: p.content,\n type: p.type,\n likes: latest?.likes ?? 0,\n retweets: latest?.retweets ?? 0,\n replies: latest?.replies ?? 0,\n };\n });\n\n const totalLikes = postStats.reduce((s, p) => s + p.likes, 0);\n const totalRTs = postStats.reduce((s, p) => s + p.retweets, 0);\n const avgLikes = Math.round(totalLikes / postStats.length);\n\n lines.push(`- Last 24h: ${postStats.length} posts, avg ${avgLikes} likes, ${totalRTs} total retweets`);\n\n // Best and worst performing\n const sorted = [...postStats].sort((a, b) => b.likes - a.likes);\n if (sorted.length > 0 && sorted[0].likes > 0) {\n lines.push(`- Best performing: \"${sorted[0].content.slice(0, 60)}...\" (${sorted[0].likes} likes, ${sorted[0].retweets} RTs)`);\n }\n if (sorted.length > 1) {\n const worst = sorted[sorted.length - 1];\n lines.push(`- Lowest performing: \"${worst.content.slice(0, 60)}...\" (${worst.likes} likes)`);\n }\n } else {\n lines.push(\"- No tracked posts in the last 24 hours yet.\");\n }\n\n // Self metrics\n if (data.selfMetrics.length > 0) {\n const latest = data.selfMetrics[data.selfMetrics.length - 1];\n lines.push(`- Followers: ${latest.followers} | Following: ${latest.following} | Total tweets: ${latest.totalTweets}`);\n\n // Trend: compare to 24h ago\n const dayAgoMetric = data.selfMetrics.find(m =>\n Math.abs(new Date(m.checkedAt).getTime() - (Date.now() - 24 * 60 * 60 * 1000)) < 12 * 60 * 60 * 1000\n );\n if (dayAgoMetric) {\n const diff = latest.followers - dayAgoMetric.followers;\n if (diff !== 0) {\n lines.push(`- Follower trend: ${diff > 0 ? \"+\" : \"\"}${diff} in the last ~24h`);\n }\n }\n }\n\n return lines.length > 0 ? lines.join(\"\\n\") : \"\";\n}\n"],"mappings":"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","names":[]}
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  ensureDirectories,
3
3
  paths
4
- } from "./chunk-5GPXH253.js";
4
+ } from "./chunk-Q7YS3AIK.js";
5
5
 
6
6
  // src/identity/index.ts
7
7
  import { readFileSync, writeFileSync, existsSync } from "fs";
@@ -619,4 +619,4 @@ export {
619
619
  mutateIdentity,
620
620
  renderIdentityDocument
621
621
  };
622
- //# sourceMappingURL=chunk-CIWFFTSP.js.map
622
+ //# sourceMappingURL=chunk-GJFBWIW3.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  ensureDirectories,
3
3
  paths
4
- } from "./chunk-5GPXH253.js";
4
+ } from "./chunk-Q7YS3AIK.js";
5
5
 
6
6
  // src/colony/memory.ts
7
7
  import { readFileSync, writeFileSync, existsSync } from "fs";
@@ -153,4 +153,4 @@ export {
153
153
  getTodayEntries,
154
154
  renderColonyBriefing
155
155
  };
156
- //# sourceMappingURL=chunk-7UHJLJNI.js.map
156
+ //# sourceMappingURL=chunk-HERI4RPY.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  ensureDirectories,
3
3
  paths
4
- } from "./chunk-5GPXH253.js";
4
+ } from "./chunk-Q7YS3AIK.js";
5
5
 
6
6
  // src/utils/logger.ts
7
7
  import { appendFileSync } from "fs";
@@ -44,4 +44,4 @@ export {
44
44
  setLogLevel,
45
45
  logger
46
46
  };
47
- //# sourceMappingURL=chunk-E4DZYHGF.js.map
47
+ //# sourceMappingURL=chunk-J7J557HV.js.map
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  loadConfig,
3
3
  saveConfig
4
- } from "./chunk-T3U56JW4.js";
4
+ } from "./chunk-SXMDYUK3.js";
5
5
  import {
6
6
  logger
7
- } from "./chunk-E4DZYHGF.js";
7
+ } from "./chunk-J7J557HV.js";
8
8
 
9
9
  // src/x-client/rate-limiter.ts
10
10
  var RateLimiter = class {
@@ -54,4 +54,4 @@ var rateLimiter = new RateLimiter();
54
54
  export {
55
55
  rateLimiter
56
56
  };
57
- //# sourceMappingURL=chunk-YF7WWJRO.js.map
57
+ //# sourceMappingURL=chunk-JWMADEQO.js.map
@@ -0,0 +1,79 @@
1
+ import {
2
+ paths
3
+ } from "./chunk-Q7YS3AIK.js";
4
+
5
+ // src/memory/strategy.ts
6
+ import { existsSync, readFileSync, writeFileSync } from "fs";
7
+ function defaultStrategy() {
8
+ return {
9
+ lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
10
+ currentFocus: [],
11
+ contentInsights: [],
12
+ peopleToEngage: [],
13
+ experiments: [],
14
+ shortTermGoals: [],
15
+ currentMood: ""
16
+ };
17
+ }
18
+ function loadStrategy() {
19
+ if (!existsSync(paths.strategy)) {
20
+ return defaultStrategy();
21
+ }
22
+ try {
23
+ return { ...defaultStrategy(), ...JSON.parse(readFileSync(paths.strategy, "utf-8")) };
24
+ } catch {
25
+ return defaultStrategy();
26
+ }
27
+ }
28
+ function saveStrategy(strategy) {
29
+ strategy.contentInsights = strategy.contentInsights.slice(-15);
30
+ strategy.peopleToEngage = strategy.peopleToEngage.slice(-20);
31
+ strategy.experiments = strategy.experiments.slice(-10);
32
+ strategy.shortTermGoals = strategy.shortTermGoals.slice(-5);
33
+ writeFileSync(paths.strategy, JSON.stringify(strategy, null, 2));
34
+ }
35
+ function renderStrategyForPrompt() {
36
+ const s = loadStrategy();
37
+ const lines = [];
38
+ if (s.currentFocus.length > 0) {
39
+ lines.push(`**Focus areas:** ${s.currentFocus.join(", ")}`);
40
+ }
41
+ if (s.contentInsights.length > 0) {
42
+ lines.push("**What's working:**");
43
+ for (const i of s.contentInsights.slice(-5)) {
44
+ lines.push(`- ${i.insight} (${i.confidence} confidence)`);
45
+ }
46
+ }
47
+ if (s.peopleToEngage.length > 0) {
48
+ lines.push("**People to engage with:**");
49
+ for (const p of s.peopleToEngage.slice(-5)) {
50
+ lines.push(`- @${p.handle}: ${p.reason} (${p.priority} priority)`);
51
+ }
52
+ }
53
+ if (s.experiments.length > 0) {
54
+ const pending = s.experiments.filter((e) => e.status === "pending");
55
+ if (pending.length > 0) {
56
+ lines.push("**Experiments to try:**");
57
+ for (const e of pending.slice(-3)) {
58
+ lines.push(`- ${e.description}`);
59
+ }
60
+ }
61
+ }
62
+ if (s.shortTermGoals.length > 0) {
63
+ lines.push("**Short-term goals:**");
64
+ for (const g of s.shortTermGoals) {
65
+ lines.push(`- ${g}`);
66
+ }
67
+ }
68
+ if (s.currentMood) {
69
+ lines.push(`**Current energy:** ${s.currentMood}`);
70
+ }
71
+ return lines.length > 0 ? lines.join("\n") : "";
72
+ }
73
+
74
+ export {
75
+ loadStrategy,
76
+ saveStrategy,
77
+ renderStrategyForPrompt
78
+ };
79
+ //# sourceMappingURL=chunk-LRKBNKMQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/memory/strategy.ts"],"sourcesContent":["import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { paths } from \"../utils/paths.js\";\n\nexport interface ContentInsight {\n insight: string;\n confidence: \"low\" | \"medium\" | \"high\";\n}\n\nexport interface PersonOfInterest {\n handle: string;\n reason: string;\n priority: \"high\" | \"medium\" | \"low\";\n}\n\nexport interface Experiment {\n description: string;\n status: \"pending\" | \"tried\" | \"successful\" | \"failed\";\n result?: string;\n}\n\nexport interface Strategy {\n lastUpdated: string;\n currentFocus: string[];\n contentInsights: ContentInsight[];\n peopleToEngage: PersonOfInterest[];\n experiments: Experiment[];\n shortTermGoals: string[];\n currentMood: string;\n}\n\nfunction defaultStrategy(): Strategy {\n return {\n lastUpdated: new Date().toISOString(),\n currentFocus: [],\n contentInsights: [],\n peopleToEngage: [],\n experiments: [],\n shortTermGoals: [],\n currentMood: \"\",\n };\n}\n\nexport function loadStrategy(): Strategy {\n if (!existsSync(paths.strategy)) {\n return defaultStrategy();\n }\n try {\n return { ...defaultStrategy(), ...JSON.parse(readFileSync(paths.strategy, \"utf-8\")) };\n } catch {\n return defaultStrategy();\n }\n}\n\nexport function saveStrategy(strategy: Strategy): void {\n // Keep arrays bounded to prevent bloat\n strategy.contentInsights = strategy.contentInsights.slice(-15);\n strategy.peopleToEngage = strategy.peopleToEngage.slice(-20);\n strategy.experiments = strategy.experiments.slice(-10);\n strategy.shortTermGoals = strategy.shortTermGoals.slice(-5);\n writeFileSync(paths.strategy, JSON.stringify(strategy, null, 2));\n}\n\nexport function renderStrategyForPrompt(): string {\n const s = loadStrategy();\n const lines: string[] = [];\n\n if (s.currentFocus.length > 0) {\n lines.push(`**Focus areas:** ${s.currentFocus.join(\", \")}`);\n }\n\n if (s.contentInsights.length > 0) {\n lines.push(\"**What's working:**\");\n for (const i of s.contentInsights.slice(-5)) {\n lines.push(`- ${i.insight} (${i.confidence} confidence)`);\n }\n }\n\n if (s.peopleToEngage.length > 0) {\n lines.push(\"**People to engage with:**\");\n for (const p of s.peopleToEngage.slice(-5)) {\n lines.push(`- @${p.handle}: ${p.reason} (${p.priority} priority)`);\n }\n }\n\n if (s.experiments.length > 0) {\n const pending = s.experiments.filter(e => e.status === \"pending\");\n if (pending.length > 0) {\n lines.push(\"**Experiments to try:**\");\n for (const e of pending.slice(-3)) {\n lines.push(`- ${e.description}`);\n }\n }\n }\n\n if (s.shortTermGoals.length > 0) {\n lines.push(\"**Short-term goals:**\");\n for (const g of s.shortTermGoals) {\n lines.push(`- ${g}`);\n }\n }\n\n if (s.currentMood) {\n lines.push(`**Current energy:** ${s.currentMood}`);\n }\n\n return lines.length > 0 ? lines.join(\"\\n\") : \"\";\n}\n"],"mappings":";;;;;AAAA,SAAS,YAAY,cAAc,qBAAqB;AA8BxD,SAAS,kBAA4B;AACnC,SAAO;AAAA,IACL,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC,cAAc,CAAC;AAAA,IACf,iBAAiB,CAAC;AAAA,IAClB,gBAAgB,CAAC;AAAA,IACjB,aAAa,CAAC;AAAA,IACd,gBAAgB,CAAC;AAAA,IACjB,aAAa;AAAA,EACf;AACF;AAEO,SAAS,eAAyB;AACvC,MAAI,CAAC,WAAW,MAAM,QAAQ,GAAG;AAC/B,WAAO,gBAAgB;AAAA,EACzB;AACA,MAAI;AACF,WAAO,EAAE,GAAG,gBAAgB,GAAG,GAAG,KAAK,MAAM,aAAa,MAAM,UAAU,OAAO,CAAC,EAAE;AAAA,EACtF,QAAQ;AACN,WAAO,gBAAgB;AAAA,EACzB;AACF;AAEO,SAAS,aAAa,UAA0B;AAErD,WAAS,kBAAkB,SAAS,gBAAgB,MAAM,GAAG;AAC7D,WAAS,iBAAiB,SAAS,eAAe,MAAM,GAAG;AAC3D,WAAS,cAAc,SAAS,YAAY,MAAM,GAAG;AACrD,WAAS,iBAAiB,SAAS,eAAe,MAAM,EAAE;AAC1D,gBAAc,MAAM,UAAU,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AACjE;AAEO,SAAS,0BAAkC;AAChD,QAAM,IAAI,aAAa;AACvB,QAAM,QAAkB,CAAC;AAEzB,MAAI,EAAE,aAAa,SAAS,GAAG;AAC7B,UAAM,KAAK,oBAAoB,EAAE,aAAa,KAAK,IAAI,CAAC,EAAE;AAAA,EAC5D;AAEA,MAAI,EAAE,gBAAgB,SAAS,GAAG;AAChC,UAAM,KAAK,qBAAqB;AAChC,eAAW,KAAK,EAAE,gBAAgB,MAAM,EAAE,GAAG;AAC3C,YAAM,KAAK,KAAK,EAAE,OAAO,KAAK,EAAE,UAAU,cAAc;AAAA,IAC1D;AAAA,EACF;AAEA,MAAI,EAAE,eAAe,SAAS,GAAG;AAC/B,UAAM,KAAK,4BAA4B;AACvC,eAAW,KAAK,EAAE,eAAe,MAAM,EAAE,GAAG;AAC1C,YAAM,KAAK,MAAM,EAAE,MAAM,KAAK,EAAE,MAAM,KAAK,EAAE,QAAQ,YAAY;AAAA,IACnE;AAAA,EACF;AAEA,MAAI,EAAE,YAAY,SAAS,GAAG;AAC5B,UAAM,UAAU,EAAE,YAAY,OAAO,OAAK,EAAE,WAAW,SAAS;AAChE,QAAI,QAAQ,SAAS,GAAG;AACtB,YAAM,KAAK,yBAAyB;AACpC,iBAAW,KAAK,QAAQ,MAAM,EAAE,GAAG;AACjC,cAAM,KAAK,KAAK,EAAE,WAAW,EAAE;AAAA,MACjC;AAAA,IACF;AAAA,EACF;AAEA,MAAI,EAAE,eAAe,SAAS,GAAG;AAC/B,UAAM,KAAK,uBAAuB;AAClC,eAAW,KAAK,EAAE,gBAAgB;AAChC,YAAM,KAAK,KAAK,CAAC,EAAE;AAAA,IACrB;AAAA,EACF;AAEA,MAAI,EAAE,aAAa;AACjB,UAAM,KAAK,uBAAuB,EAAE,WAAW,EAAE;AAAA,EACnD;AAEA,SAAO,MAAM,SAAS,IAAI,MAAM,KAAK,IAAI,IAAI;AAC/C;","names":[]}
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  loadConfig
3
- } from "./chunk-T3U56JW4.js";
3
+ } from "./chunk-SXMDYUK3.js";
4
4
  import {
5
5
  logger
6
- } from "./chunk-E4DZYHGF.js";
6
+ } from "./chunk-J7J557HV.js";
7
7
 
8
8
  // src/x-client/index.ts
9
9
  var clientInstance = null;
@@ -11,11 +11,11 @@ async function getXClient() {
11
11
  if (clientInstance) return clientInstance;
12
12
  const config = loadConfig();
13
13
  if (config.xMethod === "api") {
14
- const { XApiClient } = await import("./client-YR2RA56D.js");
14
+ const { XApiClient } = await import("./client-23THPNVL.js");
15
15
  clientInstance = new XApiClient();
16
16
  logger.info("X client initialized: API mode");
17
17
  } else {
18
- const { XBrowserClient } = await import("./client-KXYBQUMD.js");
18
+ const { XBrowserClient } = await import("./client-NVI3ZD4G.js");
19
19
  clientInstance = new XBrowserClient();
20
20
  logger.info("X client initialized: Browser mode");
21
21
  }
@@ -29,4 +29,4 @@ export {
29
29
  getXClient,
30
30
  resetXClient
31
31
  };
32
- //# sourceMappingURL=chunk-K6FZPWXD.js.map
32
+ //# sourceMappingURL=chunk-NLWU5432.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  ensureDirectories,
3
3
  paths
4
- } from "./chunk-5GPXH253.js";
4
+ } from "./chunk-Q7YS3AIK.js";
5
5
 
6
6
  // src/utils/crypto.ts
7
7
  import { createCipheriv, createDecipheriv, randomBytes, createHash } from "crypto";
@@ -53,4 +53,4 @@ export {
53
53
  saveCredentials,
54
54
  loadCredentials
55
55
  };
56
- //# sourceMappingURL=chunk-VL4UUCMS.js.map
56
+ //# sourceMappingURL=chunk-POEDIDM6.js.map
@@ -26,7 +26,10 @@ var paths = {
26
26
  runtimePid: join(SPORA_DIR, "runtime.pid"),
27
27
  stopSignal: join(SPORA_DIR, "stop"),
28
28
  connectionToken: join(SPORA_DIR, "connection-token"),
29
- lastChatMessage: join(SPORA_DIR, "last-chat-message.json")
29
+ lastChatMessage: join(SPORA_DIR, "last-chat-message.json"),
30
+ performance: join(SPORA_DIR, "memory", "performance.json"),
31
+ strategy: join(SPORA_DIR, "memory", "strategy.json"),
32
+ goals: join(SPORA_DIR, "memory", "goals.json")
30
33
  };
31
34
  function ensureDirectories() {
32
35
  const dirs = [
@@ -57,4 +60,4 @@ export {
57
60
  sporaExists,
58
61
  hasXCredentials
59
62
  };
60
- //# sourceMappingURL=chunk-5GPXH253.js.map
63
+ //# sourceMappingURL=chunk-Q7YS3AIK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/paths.ts"],"sourcesContent":["import { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { mkdirSync, existsSync } from \"node:fs\";\n\nconst SPORA_DIR = join(homedir(), \".spora\");\n\nexport const paths = {\n root: SPORA_DIR,\n config: join(SPORA_DIR, \"config.json\"),\n credentials: join(SPORA_DIR, \"credentials.json\"),\n spore: join(SPORA_DIR, \"spore.json\"),\n identity: join(SPORA_DIR, \"identity.json\"),\n colonyToken: join(SPORA_DIR, \"colony-token.json\"),\n browser: join(SPORA_DIR, \"browser\"),\n browserAuth: join(SPORA_DIR, \"browser\", \"auth-state.json\"),\n memory: join(SPORA_DIR, \"memory\"),\n interactions: join(SPORA_DIR, \"memory\", \"interactions\"),\n learnings: join(SPORA_DIR, \"memory\", \"learnings.json\"),\n relationships: join(SPORA_DIR, \"memory\", \"relationships.json\"),\n compacted: join(SPORA_DIR, \"memory\", \"compacted\"),\n queue: join(SPORA_DIR, \"queue\"),\n pendingPosts: join(SPORA_DIR, \"queue\", \"pending-posts.json\"),\n logs: join(SPORA_DIR, \"logs\"),\n logFile: join(SPORA_DIR, \"logs\", \"spora.log\"),\n dataDir: SPORA_DIR,\n llmKey: join(SPORA_DIR, \"llm-key\"),\n runtimePid: join(SPORA_DIR, \"runtime.pid\"),\n stopSignal: join(SPORA_DIR, \"stop\"),\n connectionToken: join(SPORA_DIR, \"connection-token\"),\n lastChatMessage: join(SPORA_DIR, \"last-chat-message.json\"),\n performance: join(SPORA_DIR, \"memory\", \"performance.json\"),\n strategy: join(SPORA_DIR, \"memory\", \"strategy.json\"),\n goals: join(SPORA_DIR, \"memory\", \"goals.json\"),\n} as const;\n\nexport function ensureDirectories(): void {\n const dirs = [\n paths.root,\n paths.browser,\n paths.memory,\n paths.interactions,\n paths.compacted,\n paths.queue,\n paths.logs,\n ];\n\n for (const dir of dirs) {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n }\n}\n\nexport function sporaExists(): boolean {\n return existsSync(paths.config) && existsSync(paths.identity);\n}\n\nexport function hasXCredentials(): boolean {\n return existsSync(paths.credentials);\n}\n"],"mappings":";AAAA,SAAS,eAAe;AACxB,SAAS,YAAY;AACrB,SAAS,WAAW,kBAAkB;AAEtC,IAAM,YAAY,KAAK,QAAQ,GAAG,QAAQ;AAEnC,IAAM,QAAQ;AAAA,EACnB,MAAM;AAAA,EACN,QAAQ,KAAK,WAAW,aAAa;AAAA,EACrC,aAAa,KAAK,WAAW,kBAAkB;AAAA,EAC/C,OAAO,KAAK,WAAW,YAAY;AAAA,EACnC,UAAU,KAAK,WAAW,eAAe;AAAA,EACzC,aAAa,KAAK,WAAW,mBAAmB;AAAA,EAChD,SAAS,KAAK,WAAW,SAAS;AAAA,EAClC,aAAa,KAAK,WAAW,WAAW,iBAAiB;AAAA,EACzD,QAAQ,KAAK,WAAW,QAAQ;AAAA,EAChC,cAAc,KAAK,WAAW,UAAU,cAAc;AAAA,EACtD,WAAW,KAAK,WAAW,UAAU,gBAAgB;AAAA,EACrD,eAAe,KAAK,WAAW,UAAU,oBAAoB;AAAA,EAC7D,WAAW,KAAK,WAAW,UAAU,WAAW;AAAA,EAChD,OAAO,KAAK,WAAW,OAAO;AAAA,EAC9B,cAAc,KAAK,WAAW,SAAS,oBAAoB;AAAA,EAC3D,MAAM,KAAK,WAAW,MAAM;AAAA,EAC5B,SAAS,KAAK,WAAW,QAAQ,WAAW;AAAA,EAC5C,SAAS;AAAA,EACT,QAAQ,KAAK,WAAW,SAAS;AAAA,EACjC,YAAY,KAAK,WAAW,aAAa;AAAA,EACzC,YAAY,KAAK,WAAW,MAAM;AAAA,EAClC,iBAAiB,KAAK,WAAW,kBAAkB;AAAA,EACnD,iBAAiB,KAAK,WAAW,wBAAwB;AAAA,EACzD,aAAa,KAAK,WAAW,UAAU,kBAAkB;AAAA,EACzD,UAAU,KAAK,WAAW,UAAU,eAAe;AAAA,EACnD,OAAO,KAAK,WAAW,UAAU,YAAY;AAC/C;AAEO,SAAS,oBAA0B;AACxC,QAAM,OAAO;AAAA,IACX,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAEA,aAAW,OAAO,MAAM;AACtB,QAAI,CAAC,WAAW,GAAG,GAAG;AACpB,gBAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAAA,IACpC;AAAA,EACF;AACF;AAEO,SAAS,cAAuB;AACrC,SAAO,WAAW,MAAM,MAAM,KAAK,WAAW,MAAM,QAAQ;AAC9D;AAEO,SAAS,kBAA2B;AACzC,SAAO,WAAW,MAAM,WAAW;AACrC;","names":[]}
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  loadConfig
3
- } from "./chunk-T3U56JW4.js";
3
+ } from "./chunk-SXMDYUK3.js";
4
4
  import {
5
5
  logger
6
- } from "./chunk-E4DZYHGF.js";
6
+ } from "./chunk-J7J557HV.js";
7
7
  import {
8
8
  ensureDirectories,
9
9
  paths
10
- } from "./chunk-5GPXH253.js";
10
+ } from "./chunk-Q7YS3AIK.js";
11
11
 
12
12
  // src/scheduler/queue.ts
13
13
  import { readFileSync, writeFileSync, existsSync } from "fs";
@@ -68,7 +68,7 @@ async function flushQueue() {
68
68
  const now = /* @__PURE__ */ new Date();
69
69
  let posted = 0;
70
70
  let failed = 0;
71
- const { getXClient } = await import("./x-client-DFMW2PX7.js");
71
+ const { getXClient } = await import("./x-client-HUXCQOAW.js");
72
72
  const client = await getXClient();
73
73
  const STALE_THRESHOLD_MS = 5 * 60 * 1e3;
74
74
  for (const entry of queue.entries) {
@@ -86,7 +86,7 @@ async function flushQueue() {
86
86
  let result;
87
87
  if (entry.imageQuery) {
88
88
  try {
89
- const { searchImage, downloadImage } = await import("./image-search-6RGKTFRT.js");
89
+ const { searchImage, downloadImage } = await import("./image-search-SZVMGWLN.js");
90
90
  const imageUrl = await searchImage(entry.imageQuery);
91
91
  if (imageUrl) {
92
92
  const imageBuffer = await downloadImage(imageUrl);
@@ -107,6 +107,13 @@ async function flushQueue() {
107
107
  entry.postedAt = (/* @__PURE__ */ new Date()).toISOString();
108
108
  posted++;
109
109
  if (!entry.imageQuery) logger.info(`Posted: ${entry.id}`);
110
+ if (result.tweetId) {
111
+ try {
112
+ const { trackPost } = await import("./performance-7G6R6ELJ.js");
113
+ trackPost(result.tweetId, entry.content, "post");
114
+ } catch {
115
+ }
116
+ }
110
117
  } else {
111
118
  entry.status = "failed";
112
119
  entry.error = result.error;
@@ -149,4 +156,4 @@ export {
149
156
  flushQueue,
150
157
  showQueue
151
158
  };
152
- //# sourceMappingURL=chunk-3NW3VIN5.js.map
159
+ //# sourceMappingURL=chunk-QHFM2YW6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/scheduler/queue.ts"],"sourcesContent":["import { readFileSync, writeFileSync, existsSync } from \"node:fs\";\nimport { paths, ensureDirectories } from \"../utils/paths.js\";\nimport { loadConfig, saveConfig } from \"../utils/config.js\";\nimport { logger } from \"../utils/logger.js\";\n\nexport interface QueueEntry {\n id: string;\n content: string;\n scheduledFor: string;\n status: \"pending\" | \"posted\" | \"failed\" | \"expired\";\n createdAt: string;\n postedAt?: string;\n error?: string;\n imageQuery?: string; // Optional image search query to attach when posting\n}\n\ninterface QueueData {\n entries: QueueEntry[];\n}\n\nfunction loadQueue(): QueueData {\n if (!existsSync(paths.pendingPosts)) {\n return { entries: [] };\n }\n return JSON.parse(readFileSync(paths.pendingPosts, \"utf-8\")) as QueueData;\n}\n\nfunction saveQueue(data: QueueData): void {\n ensureDirectories();\n writeFileSync(paths.pendingPosts, JSON.stringify(data, null, 2));\n}\n\nfunction nextScheduledTime(): string {\n const config = loadConfig();\n const now = new Date();\n const queue = loadQueue();\n\n // Find the latest scheduled time in the queue\n const pendingEntries = queue.entries.filter((e) => e.status === \"pending\");\n let lastScheduled = now;\n\n if (pendingEntries.length > 0) {\n const latest = new Date(\n pendingEntries.reduce((max, e) =>\n new Date(e.scheduledFor) > new Date(max.scheduledFor) ? e : max\n ).scheduledFor\n );\n if (latest > lastScheduled) lastScheduled = latest;\n }\n\n // Add a random interval within the active hours\n const intervalMinutes = Math.floor(\n ((config.schedule.activeHoursEnd - config.schedule.activeHoursStart) * 60) /\n config.schedule.postsPerDay\n );\n\n const next = new Date(lastScheduled.getTime() + intervalMinutes * 60 * 1000);\n\n // Clamp to active hours\n if (next.getHours() >= config.schedule.activeHoursEnd) {\n next.setDate(next.getDate() + 1);\n next.setHours(config.schedule.activeHoursStart, Math.floor(Math.random() * 60), 0, 0);\n }\n if (next.getHours() < config.schedule.activeHoursStart) {\n next.setHours(config.schedule.activeHoursStart, Math.floor(Math.random() * 60), 0, 0);\n }\n\n return next.toISOString();\n}\n\nexport function addToQueue(content: string, scheduledFor?: string, imageQuery?: string): QueueEntry {\n const queue = loadQueue();\n\n const entry: QueueEntry = {\n id: `post-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,\n content,\n scheduledFor: scheduledFor ?? nextScheduledTime(),\n status: \"pending\",\n createdAt: new Date().toISOString(),\n ...(imageQuery ? { imageQuery } : {}),\n };\n\n queue.entries.push(entry);\n saveQueue(queue);\n\n logger.info(`Post queued: ${entry.id} scheduled for ${entry.scheduledFor}`);\n return entry;\n}\n\nexport async function flushQueue(): Promise<{\n posted: number;\n failed: number;\n remaining: number;\n}> {\n const queue = loadQueue();\n const now = new Date();\n let posted = 0;\n let failed = 0;\n\n const { getXClient } = await import(\"../x-client/index.js\");\n const client = await getXClient();\n\n // Expire stale posts (scheduled more than 5 minutes ago — from previous sessions)\n const STALE_THRESHOLD_MS = 5 * 60 * 1000;\n for (const entry of queue.entries) {\n if (entry.status !== \"pending\") continue;\n const scheduledTime = new Date(entry.scheduledFor).getTime();\n if (scheduledTime < now.getTime() - STALE_THRESHOLD_MS) {\n entry.status = \"expired\";\n logger.info(`Expired stale post: ${entry.id} (was scheduled for ${entry.scheduledFor})`);\n }\n }\n\n for (const entry of queue.entries) {\n if (entry.status !== \"pending\") continue;\n if (new Date(entry.scheduledFor) > now) continue;\n\n try {\n let result;\n\n // If entry has an imageQuery, search and attach image\n if (entry.imageQuery) {\n try {\n const { searchImage, downloadImage } = await import(\"../utils/image-search.js\");\n const imageUrl = await searchImage(entry.imageQuery);\n if (imageUrl) {\n const imageBuffer = await downloadImage(imageUrl);\n result = await client.postTweetWithMedia(entry.content, imageBuffer);\n if (result.success) {\n logger.info(`Posted with image: ${entry.id}`);\n }\n }\n } catch (imgErr) {\n logger.warn(`Image attach failed for ${entry.id}, posting text only: ${(imgErr as Error).message}`);\n }\n }\n\n // Fall back to text-only if no image or image failed\n if (!result) {\n result = await client.postTweet(entry.content);\n }\n\n if (result.success) {\n entry.status = \"posted\";\n entry.postedAt = new Date().toISOString();\n posted++;\n if (!entry.imageQuery) logger.info(`Posted: ${entry.id}`);\n // Track for performance monitoring\n if (result.tweetId) {\n try {\n const { trackPost } = await import(\"../memory/performance.js\");\n trackPost(result.tweetId, entry.content, \"post\");\n } catch { /* non-critical */ }\n }\n } else {\n entry.status = \"failed\";\n entry.error = result.error;\n failed++;\n logger.warn(`Failed to post: ${entry.id} - ${result.error}`);\n }\n } catch (error) {\n entry.status = \"failed\";\n entry.error = (error as Error).message;\n failed++;\n }\n\n // Small delay between posts to avoid rate limits\n await new Promise((resolve) => setTimeout(resolve, 2000));\n }\n\n saveQueue(queue);\n\n const remaining = queue.entries.filter((e) => e.status === \"pending\").length;\n return { posted, failed, remaining };\n}\n\nexport function showQueue(): void {\n const queue = loadQueue();\n const pending = queue.entries.filter((e) => e.status === \"pending\");\n\n if (pending.length === 0) {\n console.log(\"Queue is empty.\");\n return;\n }\n\n console.log(`\\n${pending.length} posts queued:\\n`);\n for (const entry of pending.sort(\n (a, b) => new Date(a.scheduledFor).getTime() - new Date(b.scheduledFor).getTime()\n )) {\n const time = new Date(entry.scheduledFor).toLocaleString();\n const preview = entry.content.length > 60 ? entry.content.slice(0, 60) + \"...\" : entry.content;\n console.log(` [${time}] ${preview}`);\n }\n console.log();\n}\n"],"mappings":";;;;;;;;;;;;AAAA,SAAS,cAAc,eAAe,kBAAkB;AAoBxD,SAAS,YAAuB;AAC9B,MAAI,CAAC,WAAW,MAAM,YAAY,GAAG;AACnC,WAAO,EAAE,SAAS,CAAC,EAAE;AAAA,EACvB;AACA,SAAO,KAAK,MAAM,aAAa,MAAM,cAAc,OAAO,CAAC;AAC7D;AAEA,SAAS,UAAU,MAAuB;AACxC,oBAAkB;AAClB,gBAAc,MAAM,cAAc,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AACjE;AAEA,SAAS,oBAA4B;AACnC,QAAM,SAAS,WAAW;AAC1B,QAAM,MAAM,oBAAI,KAAK;AACrB,QAAM,QAAQ,UAAU;AAGxB,QAAM,iBAAiB,MAAM,QAAQ,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS;AACzE,MAAI,gBAAgB;AAEpB,MAAI,eAAe,SAAS,GAAG;AAC7B,UAAM,SAAS,IAAI;AAAA,MACjB,eAAe;AAAA,QAAO,CAAC,KAAK,MAC1B,IAAI,KAAK,EAAE,YAAY,IAAI,IAAI,KAAK,IAAI,YAAY,IAAI,IAAI;AAAA,MAC9D,EAAE;AAAA,IACJ;AACA,QAAI,SAAS,cAAe,iBAAgB;AAAA,EAC9C;AAGA,QAAM,kBAAkB,KAAK;AAAA,KACzB,OAAO,SAAS,iBAAiB,OAAO,SAAS,oBAAoB,KACrE,OAAO,SAAS;AAAA,EACpB;AAEA,QAAM,OAAO,IAAI,KAAK,cAAc,QAAQ,IAAI,kBAAkB,KAAK,GAAI;AAG3E,MAAI,KAAK,SAAS,KAAK,OAAO,SAAS,gBAAgB;AACrD,SAAK,QAAQ,KAAK,QAAQ,IAAI,CAAC;AAC/B,SAAK,SAAS,OAAO,SAAS,kBAAkB,KAAK,MAAM,KAAK,OAAO,IAAI,EAAE,GAAG,GAAG,CAAC;AAAA,EACtF;AACA,MAAI,KAAK,SAAS,IAAI,OAAO,SAAS,kBAAkB;AACtD,SAAK,SAAS,OAAO,SAAS,kBAAkB,KAAK,MAAM,KAAK,OAAO,IAAI,EAAE,GAAG,GAAG,CAAC;AAAA,EACtF;AAEA,SAAO,KAAK,YAAY;AAC1B;AAEO,SAAS,WAAW,SAAiB,cAAuB,YAAiC;AAClG,QAAM,QAAQ,UAAU;AAExB,QAAM,QAAoB;AAAA,IACxB,IAAI,QAAQ,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAAA,IAChE;AAAA,IACA,cAAc,gBAAgB,kBAAkB;AAAA,IAChD,QAAQ;AAAA,IACR,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;AAAA,EACrC;AAEA,QAAM,QAAQ,KAAK,KAAK;AACxB,YAAU,KAAK;AAEf,SAAO,KAAK,gBAAgB,MAAM,EAAE,kBAAkB,MAAM,YAAY,EAAE;AAC1E,SAAO;AACT;AAEA,eAAsB,aAInB;AACD,QAAM,QAAQ,UAAU;AACxB,QAAM,MAAM,oBAAI,KAAK;AACrB,MAAI,SAAS;AACb,MAAI,SAAS;AAEb,QAAM,EAAE,WAAW,IAAI,MAAM,OAAO,wBAAsB;AAC1D,QAAM,SAAS,MAAM,WAAW;AAGhC,QAAM,qBAAqB,IAAI,KAAK;AACpC,aAAW,SAAS,MAAM,SAAS;AACjC,QAAI,MAAM,WAAW,UAAW;AAChC,UAAM,gBAAgB,IAAI,KAAK,MAAM,YAAY,EAAE,QAAQ;AAC3D,QAAI,gBAAgB,IAAI,QAAQ,IAAI,oBAAoB;AACtD,YAAM,SAAS;AACf,aAAO,KAAK,uBAAuB,MAAM,EAAE,uBAAuB,MAAM,YAAY,GAAG;AAAA,IACzF;AAAA,EACF;AAEA,aAAW,SAAS,MAAM,SAAS;AACjC,QAAI,MAAM,WAAW,UAAW;AAChC,QAAI,IAAI,KAAK,MAAM,YAAY,IAAI,IAAK;AAExC,QAAI;AACF,UAAI;AAGJ,UAAI,MAAM,YAAY;AACpB,YAAI;AACF,gBAAM,EAAE,aAAa,cAAc,IAAI,MAAM,OAAO,4BAA0B;AAC9E,gBAAM,WAAW,MAAM,YAAY,MAAM,UAAU;AACnD,cAAI,UAAU;AACZ,kBAAM,cAAc,MAAM,cAAc,QAAQ;AAChD,qBAAS,MAAM,OAAO,mBAAmB,MAAM,SAAS,WAAW;AACnE,gBAAI,OAAO,SAAS;AAClB,qBAAO,KAAK,sBAAsB,MAAM,EAAE,EAAE;AAAA,YAC9C;AAAA,UACF;AAAA,QACF,SAAS,QAAQ;AACf,iBAAO,KAAK,2BAA2B,MAAM,EAAE,wBAAyB,OAAiB,OAAO,EAAE;AAAA,QACpG;AAAA,MACF;AAGA,UAAI,CAAC,QAAQ;AACX,iBAAS,MAAM,OAAO,UAAU,MAAM,OAAO;AAAA,MAC/C;AAEA,UAAI,OAAO,SAAS;AAClB,cAAM,SAAS;AACf,cAAM,YAAW,oBAAI,KAAK,GAAE,YAAY;AACxC;AACA,YAAI,CAAC,MAAM,WAAY,QAAO,KAAK,WAAW,MAAM,EAAE,EAAE;AAExD,YAAI,OAAO,SAAS;AAClB,cAAI;AACF,kBAAM,EAAE,UAAU,IAAI,MAAM,OAAO,2BAA0B;AAC7D,sBAAU,OAAO,SAAS,MAAM,SAAS,MAAM;AAAA,UACjD,QAAQ;AAAA,UAAqB;AAAA,QAC/B;AAAA,MACF,OAAO;AACL,cAAM,SAAS;AACf,cAAM,QAAQ,OAAO;AACrB;AACA,eAAO,KAAK,mBAAmB,MAAM,EAAE,MAAM,OAAO,KAAK,EAAE;AAAA,MAC7D;AAAA,IACF,SAAS,OAAO;AACd,YAAM,SAAS;AACf,YAAM,QAAS,MAAgB;AAC/B;AAAA,IACF;AAGA,UAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,GAAI,CAAC;AAAA,EAC1D;AAEA,YAAU,KAAK;AAEf,QAAM,YAAY,MAAM,QAAQ,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS,EAAE;AACtE,SAAO,EAAE,QAAQ,QAAQ,UAAU;AACrC;AAEO,SAAS,YAAkB;AAChC,QAAM,QAAQ,UAAU;AACxB,QAAM,UAAU,MAAM,QAAQ,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS;AAElE,MAAI,QAAQ,WAAW,GAAG;AACxB,YAAQ,IAAI,iBAAiB;AAC7B;AAAA,EACF;AAEA,UAAQ,IAAI;AAAA,EAAK,QAAQ,MAAM;AAAA,CAAkB;AACjD,aAAW,SAAS,QAAQ;AAAA,IAC1B,CAAC,GAAG,MAAM,IAAI,KAAK,EAAE,YAAY,EAAE,QAAQ,IAAI,IAAI,KAAK,EAAE,YAAY,EAAE,QAAQ;AAAA,EAClF,GAAG;AACD,UAAM,OAAO,IAAI,KAAK,MAAM,YAAY,EAAE,eAAe;AACzD,UAAM,UAAU,MAAM,QAAQ,SAAS,KAAK,MAAM,QAAQ,MAAM,GAAG,EAAE,IAAI,QAAQ,MAAM;AACvF,YAAQ,IAAI,MAAM,IAAI,KAAK,OAAO,EAAE;AAAA,EACtC;AACA,UAAQ,IAAI;AACd;","names":[]}
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  ensureDirectories,
3
3
  paths
4
- } from "./chunk-5GPXH253.js";
4
+ } from "./chunk-Q7YS3AIK.js";
5
5
 
6
6
  // src/memory/index.ts
7
7
  import { readFileSync, writeFileSync, appendFileSync, existsSync, readdirSync } from "fs";
@@ -66,6 +66,29 @@ function saveRelationships(data) {
66
66
  ensureDirectories();
67
67
  writeFileSync(paths.relationships, JSON.stringify(data, null, 2));
68
68
  }
69
+ function getActiveConversations(hours = 24) {
70
+ const cutoff = new Date(Date.now() - hours * 60 * 60 * 1e3);
71
+ const recent = getRecentInteractions(50);
72
+ const conversations = [];
73
+ const seenHandles = /* @__PURE__ */ new Set();
74
+ for (const entry of recent) {
75
+ if (entry.type !== "mention_received") continue;
76
+ if (!entry.targetHandle || !entry.content) continue;
77
+ if (new Date(entry.timestamp) < cutoff) continue;
78
+ if (seenHandles.has(entry.targetHandle)) continue;
79
+ seenHandles.add(entry.targetHandle);
80
+ const timeDiff = Date.now() - new Date(entry.timestamp).getTime();
81
+ const minutesAgo = Math.floor(timeDiff / 6e4);
82
+ const timeAgo = minutesAgo < 60 ? `${minutesAgo}m ago` : `${Math.floor(minutesAgo / 60)}h ago`;
83
+ conversations.push({
84
+ handle: entry.targetHandle,
85
+ content: entry.content.slice(0, 100),
86
+ timeAgo,
87
+ tweetId: entry.tweetId
88
+ });
89
+ }
90
+ return conversations;
91
+ }
69
92
  function updateRelationship(userId, update) {
70
93
  const data = loadRelationships();
71
94
  const existing = data.accounts[userId];
@@ -100,6 +123,7 @@ export {
100
123
  addLearning,
101
124
  loadRelationships,
102
125
  saveRelationships,
126
+ getActiveConversations,
103
127
  updateRelationship
104
128
  };
105
- //# sourceMappingURL=chunk-DE772QJH.js.map
129
+ //# sourceMappingURL=chunk-RNVEWVDN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/memory/index.ts"],"sourcesContent":["import { readFileSync, writeFileSync, appendFileSync, existsSync, readdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { paths, ensureDirectories } from \"../utils/paths.js\";\n\nexport interface InteractionEntry {\n id: string;\n timestamp: string;\n type: \"post\" | \"reply\" | \"like\" | \"retweet\" | \"follow\" | \"mention_received\";\n tweetId?: string;\n targetUserId?: string;\n targetHandle?: string;\n content?: string;\n inReplyTo?: string;\n sentiment?: \"positive\" | \"negative\" | \"neutral\";\n creditsUsed: number;\n success: boolean;\n error?: string;\n}\n\nexport interface Learning {\n id: string;\n timestamp: string;\n content: string;\n source: string;\n tags: string[];\n}\n\nexport interface Relationship {\n handle: string;\n firstSeen: string;\n lastInteraction: string;\n interactionCount: number;\n sentiment: number;\n tags: string[];\n notes: string[];\n isSpore: boolean;\n}\n\nexport interface RelationshipsData {\n accounts: Record<string, Relationship>;\n}\n\nexport interface LearningsData {\n learnings: Learning[];\n}\n\n// --- Interaction Log ---\n\nfunction todayLogPath(): string {\n const date = new Date().toISOString().split(\"T\")[0];\n return join(paths.interactions, `${date}.jsonl`);\n}\n\nexport function logInteraction(entry: InteractionEntry): void {\n ensureDirectories();\n appendFileSync(todayLogPath(), JSON.stringify(entry) + \"\\n\");\n}\n\nexport function getInteractions(date?: string): InteractionEntry[] {\n const targetDate = date ?? new Date().toISOString().split(\"T\")[0];\n const filePath = join(paths.interactions, `${targetDate}.jsonl`);\n\n if (!existsSync(filePath)) return [];\n\n return readFileSync(filePath, \"utf-8\")\n .trim()\n .split(\"\\n\")\n .filter(Boolean)\n .map((line) => JSON.parse(line) as InteractionEntry);\n}\n\nexport function getRecentInteractions(count: number = 20): InteractionEntry[] {\n ensureDirectories();\n const files = readdirSync(paths.interactions)\n .filter((f) => f.endsWith(\".jsonl\"))\n .sort()\n .reverse();\n\n const entries: InteractionEntry[] = [];\n for (const file of files) {\n if (entries.length >= count) break;\n const filePath = join(paths.interactions, file);\n const lines = readFileSync(filePath, \"utf-8\").trim().split(\"\\n\").filter(Boolean);\n for (const line of lines.reverse()) {\n if (entries.length >= count) break;\n entries.push(JSON.parse(line) as InteractionEntry);\n }\n }\n\n return entries;\n}\n\n// --- Learnings ---\n\nexport function loadLearnings(): LearningsData {\n if (!existsSync(paths.learnings)) {\n return { learnings: [] };\n }\n return JSON.parse(readFileSync(paths.learnings, \"utf-8\")) as LearningsData;\n}\n\nexport function saveLearnings(data: LearningsData): void {\n ensureDirectories();\n writeFileSync(paths.learnings, JSON.stringify(data, null, 2));\n}\n\nexport function addLearning(content: string, source: string, tags: string[] = []): void {\n const data = loadLearnings();\n data.learnings.push({\n id: `learn-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n timestamp: new Date().toISOString(),\n content,\n source,\n tags,\n });\n saveLearnings(data);\n}\n\n// --- Relationships ---\n\nexport function loadRelationships(): RelationshipsData {\n if (!existsSync(paths.relationships)) {\n return { accounts: {} };\n }\n return JSON.parse(readFileSync(paths.relationships, \"utf-8\")) as RelationshipsData;\n}\n\nexport function saveRelationships(data: RelationshipsData): void {\n ensureDirectories();\n writeFileSync(paths.relationships, JSON.stringify(data, null, 2));\n}\n\nexport interface ActiveConversation {\n handle: string;\n content: string;\n timeAgo: string;\n tweetId?: string;\n}\n\nexport function getActiveConversations(hours: number = 24): ActiveConversation[] {\n const cutoff = new Date(Date.now() - hours * 60 * 60 * 1000);\n const recent = getRecentInteractions(50);\n\n // Find mentions and replies directed at us\n const conversations: ActiveConversation[] = [];\n const seenHandles = new Set<string>();\n\n for (const entry of recent) {\n if (entry.type !== \"mention_received\") continue;\n if (!entry.targetHandle || !entry.content) continue;\n if (new Date(entry.timestamp) < cutoff) continue;\n if (seenHandles.has(entry.targetHandle)) continue;\n seenHandles.add(entry.targetHandle);\n\n const timeDiff = Date.now() - new Date(entry.timestamp).getTime();\n const minutesAgo = Math.floor(timeDiff / 60000);\n const timeAgo = minutesAgo < 60\n ? `${minutesAgo}m ago`\n : `${Math.floor(minutesAgo / 60)}h ago`;\n\n conversations.push({\n handle: entry.targetHandle,\n content: entry.content.slice(0, 100),\n timeAgo,\n tweetId: entry.tweetId,\n });\n }\n\n return conversations;\n}\n\nexport function updateRelationship(\n userId: string,\n update: Partial<Relationship> & { handle: string }\n): void {\n const data = loadRelationships();\n const existing = data.accounts[userId];\n\n if (existing) {\n data.accounts[userId] = {\n ...existing,\n ...update,\n lastInteraction: new Date().toISOString(),\n interactionCount: existing.interactionCount + 1,\n };\n } else {\n data.accounts[userId] = {\n handle: update.handle,\n firstSeen: new Date().toISOString(),\n lastInteraction: new Date().toISOString(),\n interactionCount: 1,\n sentiment: update.sentiment ?? 0,\n tags: update.tags ?? [],\n notes: update.notes ?? [],\n isSpore: update.isSpore ?? false,\n };\n }\n\n saveRelationships(data);\n}\n"],"mappings":"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","names":[]}
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  loadConfig
3
- } from "./chunk-T3U56JW4.js";
3
+ } from "./chunk-SXMDYUK3.js";
4
4
  import {
5
5
  logger
6
- } from "./chunk-E4DZYHGF.js";
6
+ } from "./chunk-J7J557HV.js";
7
7
  import {
8
8
  paths
9
- } from "./chunk-5GPXH253.js";
9
+ } from "./chunk-Q7YS3AIK.js";
10
10
 
11
11
  // src/runtime/llm.ts
12
12
  import Anthropic from "@anthropic-ai/sdk";
@@ -40,7 +40,7 @@ async function generateResponse(systemPrompt, userMessage, options) {
40
40
  const anthropic = getClient();
41
41
  const response = await anthropic.messages.create({
42
42
  model,
43
- max_tokens: 1024,
43
+ max_tokens: 2048,
44
44
  temperature: options?.temperature ?? 1,
45
45
  system: systemPrompt,
46
46
  messages: [{ role: "user", content: userMessage }]
@@ -79,4 +79,4 @@ export {
79
79
  generateResponse,
80
80
  chat
81
81
  };
82
- //# sourceMappingURL=chunk-LTAYL5E2.js.map
82
+ //# sourceMappingURL=chunk-SUFTVQME.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/runtime/llm.ts"],"sourcesContent":["import 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 client: Anthropic | null = null;\n\nexport function getLLMApiKey(): string | null {\n // Check env first, then file\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(): Anthropic {\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 client = new Anthropic({ apiKey });\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 options?: { temperature?: number },\n): Promise<LLMResponse> {\n const config = loadConfig();\n const model = config.llm?.model ?? \"claude-sonnet-4-20250514\";\n\n logger.info(`Calling LLM (${model})...`);\n\n const anthropic = getClient();\n const response = await anthropic.messages.create({\n model,\n max_tokens: 1024,\n temperature: options?.temperature ?? 1.0,\n system: systemPrompt,\n messages: [{ role: \"user\", content: userMessage }],\n });\n\n const textBlock = response.content.find((b) => b.type === \"text\");\n const content = textBlock ? textBlock.text : \"\";\n\n logger.info(`LLM response: ${response.usage.input_tokens} in, ${response.usage.output_tokens} out`);\n\n return {\n content,\n inputTokens: response.usage.input_tokens,\n outputTokens: response.usage.output_tokens,\n };\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 ?? \"claude-sonnet-4-20250514\";\n\n const anthropic = getClient();\n const response = await anthropic.messages.create({\n model,\n max_tokens: 1024,\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"],"mappings":";;;;;;;;;;;AAAA,OAAO,eAAe;AACtB,SAAS,cAAc,kBAAkB;AAKzC,IAAI,SAA2B;AAExB,SAAS,eAA8B;AAE5C,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,YAAuB;AAC9B,MAAI,OAAQ,QAAO;AACnB,QAAM,SAAS,aAAa;AAC5B,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,2DAA2D;AAAA,EAC7E;AACA,WAAS,IAAI,UAAU,EAAE,OAAO,CAAC;AACjC,SAAO;AACT;AAQA,eAAsB,iBACpB,cACA,aACA,SACsB;AACtB,QAAM,SAAS,WAAW;AAC1B,QAAM,QAAQ,OAAO,KAAK,SAAS;AAEnC,SAAO,KAAK,gBAAgB,KAAK,MAAM;AAEvC,QAAM,YAAY,UAAU;AAC5B,QAAM,WAAW,MAAM,UAAU,SAAS,OAAO;AAAA,IAC/C;AAAA,IACA,YAAY;AAAA,IACZ,aAAa,SAAS,eAAe;AAAA,IACrC,QAAQ;AAAA,IACR,UAAU,CAAC,EAAE,MAAM,QAAQ,SAAS,YAAY,CAAC;AAAA,EACnD,CAAC;AAED,QAAM,YAAY,SAAS,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM;AAChE,QAAM,UAAU,YAAY,UAAU,OAAO;AAE7C,SAAO,KAAK,iBAAiB,SAAS,MAAM,YAAY,QAAQ,SAAS,MAAM,aAAa,MAAM;AAElG,SAAO;AAAA,IACL;AAAA,IACA,aAAa,SAAS,MAAM;AAAA,IAC5B,cAAc,SAAS,MAAM;AAAA,EAC/B;AACF;AAEA,eAAsB,KACpB,cACA,UACsB;AACtB,QAAM,SAAS,WAAW;AAC1B,QAAM,QAAQ,OAAO,KAAK,SAAS;AAEnC,QAAM,YAAY,UAAU;AAC5B,QAAM,WAAW,MAAM,UAAU,SAAS,OAAO;AAAA,IAC/C;AAAA,IACA,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR;AAAA,EACF,CAAC;AAED,QAAM,YAAY,SAAS,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM;AAChE,QAAM,UAAU,YAAY,UAAU,OAAO;AAE7C,SAAO;AAAA,IACL;AAAA,IACA,aAAa,SAAS,MAAM;AAAA,IAC5B,cAAc,SAAS,MAAM;AAAA,EAC/B;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/runtime/llm.ts"],"sourcesContent":["import 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 client: Anthropic | null = null;\n\nexport function getLLMApiKey(): string | null {\n // Check env first, then file\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(): Anthropic {\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 client = new Anthropic({ apiKey });\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 options?: { temperature?: number },\n): Promise<LLMResponse> {\n const config = loadConfig();\n const model = config.llm?.model ?? \"claude-sonnet-4-20250514\";\n\n logger.info(`Calling LLM (${model})...`);\n\n const anthropic = getClient();\n const response = await anthropic.messages.create({\n model,\n max_tokens: 2048,\n temperature: options?.temperature ?? 1.0,\n system: systemPrompt,\n messages: [{ role: \"user\", content: userMessage }],\n });\n\n const textBlock = response.content.find((b) => b.type === \"text\");\n const content = textBlock ? textBlock.text : \"\";\n\n logger.info(`LLM response: ${response.usage.input_tokens} in, ${response.usage.output_tokens} out`);\n\n return {\n content,\n inputTokens: response.usage.input_tokens,\n outputTokens: response.usage.output_tokens,\n };\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 ?? \"claude-sonnet-4-20250514\";\n\n const anthropic = getClient();\n const response = await anthropic.messages.create({\n model,\n max_tokens: 1024,\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"],"mappings":";;;;;;;;;;;AAAA,OAAO,eAAe;AACtB,SAAS,cAAc,kBAAkB;AAKzC,IAAI,SAA2B;AAExB,SAAS,eAA8B;AAE5C,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,YAAuB;AAC9B,MAAI,OAAQ,QAAO;AACnB,QAAM,SAAS,aAAa;AAC5B,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,2DAA2D;AAAA,EAC7E;AACA,WAAS,IAAI,UAAU,EAAE,OAAO,CAAC;AACjC,SAAO;AACT;AAQA,eAAsB,iBACpB,cACA,aACA,SACsB;AACtB,QAAM,SAAS,WAAW;AAC1B,QAAM,QAAQ,OAAO,KAAK,SAAS;AAEnC,SAAO,KAAK,gBAAgB,KAAK,MAAM;AAEvC,QAAM,YAAY,UAAU;AAC5B,QAAM,WAAW,MAAM,UAAU,SAAS,OAAO;AAAA,IAC/C;AAAA,IACA,YAAY;AAAA,IACZ,aAAa,SAAS,eAAe;AAAA,IACrC,QAAQ;AAAA,IACR,UAAU,CAAC,EAAE,MAAM,QAAQ,SAAS,YAAY,CAAC;AAAA,EACnD,CAAC;AAED,QAAM,YAAY,SAAS,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM;AAChE,QAAM,UAAU,YAAY,UAAU,OAAO;AAE7C,SAAO,KAAK,iBAAiB,SAAS,MAAM,YAAY,QAAQ,SAAS,MAAM,aAAa,MAAM;AAElG,SAAO;AAAA,IACL;AAAA,IACA,aAAa,SAAS,MAAM;AAAA,IAC5B,cAAc,SAAS,MAAM;AAAA,EAC/B;AACF;AAEA,eAAsB,KACpB,cACA,UACsB;AACtB,QAAM,SAAS,WAAW;AAC1B,QAAM,QAAQ,OAAO,KAAK,SAAS;AAEnC,QAAM,YAAY,UAAU;AAC5B,QAAM,WAAW,MAAM,UAAU,SAAS,OAAO;AAAA,IAC/C;AAAA,IACA,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR;AAAA,EACF,CAAC;AAED,QAAM,YAAY,SAAS,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM;AAChE,QAAM,UAAU,YAAY,UAAU,OAAO;AAE7C,SAAO;AAAA,IACL;AAAA,IACA,aAAa,SAAS,MAAM;AAAA,IAC5B,cAAc,SAAS,MAAM;AAAA,EAC/B;AACF;","names":[]}
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  ensureDirectories,
3
3
  paths
4
- } from "./chunk-5GPXH253.js";
4
+ } from "./chunk-Q7YS3AIK.js";
5
5
 
6
6
  // src/utils/config.ts
7
7
  import { readFileSync, writeFileSync, existsSync } from "fs";
@@ -77,4 +77,4 @@ export {
77
77
  saveConfig,
78
78
  createDefaultConfig
79
79
  };
80
- //# sourceMappingURL=chunk-T3U56JW4.js.map
80
+ //# sourceMappingURL=chunk-SXMDYUK3.js.map