spora 0.3.2 → 0.3.4

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 (102) hide show
  1. package/dist/{account-creator-SETL5CGT.js → account-creator-AABUY2JU.js} +5 -5
  2. package/dist/{chunk-Q7YS3AIK.js → chunk-6KCIAMHL.js} +5 -6
  3. package/dist/chunk-6KCIAMHL.js.map +1 -0
  4. package/dist/{chunk-HERI4RPY.js → chunk-A6R5ZGK6.js} +2 -2
  5. package/dist/{chunk-QHFM2YW6.js → chunk-B6VI6L4D.js} +9 -44
  6. package/dist/chunk-B6VI6L4D.js.map +1 -0
  7. package/dist/{chunk-GJFBWIW3.js → chunk-FTFTB5Y5.js} +2 -2
  8. package/dist/{chunk-SXMDYUK3.js → chunk-GMSK775L.js} +29 -6
  9. package/dist/chunk-GMSK775L.js.map +1 -0
  10. package/dist/{chunk-POEDIDM6.js → chunk-H62HH5ZI.js} +2 -2
  11. package/dist/{chunk-NLWU5432.js → chunk-KQ37VL54.js} +5 -5
  12. package/dist/{chunk-JWMADEQO.js → chunk-ML4EMUZC.js} +3 -3
  13. package/dist/chunk-N5TBL3NY.js +86 -0
  14. package/dist/chunk-N5TBL3NY.js.map +1 -0
  15. package/dist/chunk-PNZ3XK2N.js +358 -0
  16. package/dist/chunk-PNZ3XK2N.js.map +1 -0
  17. package/dist/{chunk-J7J557HV.js → chunk-UCCAF2ZO.js} +2 -2
  18. package/dist/{chunk-RNVEWVDN.js → chunk-V6ZNR2SI.js} +2 -26
  19. package/dist/chunk-V6ZNR2SI.js.map +1 -0
  20. package/dist/cli.js +46 -46
  21. package/dist/cli.js.map +1 -1
  22. package/dist/{client-NVI3ZD4G.js → client-BGLXHLID.js} +10 -20
  23. package/dist/client-BGLXHLID.js.map +1 -0
  24. package/dist/client-TWYR2IIQ.js +373 -0
  25. package/dist/client-TWYR2IIQ.js.map +1 -0
  26. package/dist/{colony-J4EZQI37.js → colony-JVBCMZTK.js} +7 -7
  27. package/dist/{config-QRBOL4NX.js → config-5EPXA325.js} +3 -3
  28. package/dist/{crypto-ZVWJLD2J.js → crypto-HS4CGS4A.js} +3 -3
  29. package/dist/heartbeat-B2CZKMUF.js +901 -0
  30. package/dist/heartbeat-B2CZKMUF.js.map +1 -0
  31. package/dist/{identity-LN2R4KJU.js → identity-6CXRCXJQ.js} +3 -3
  32. package/dist/{init-ANGLSI2L.js → init-KXNLBFMG.js} +21 -21
  33. package/dist/init-KXNLBFMG.js.map +1 -0
  34. package/dist/llm-CUCO24K7.js +16 -0
  35. package/dist/mcp-server.js +24 -24
  36. package/dist/{memory-JMXU3UXR.js → memory-2OI3JXY2.js} +3 -3
  37. package/dist/{memory-J6AYZ5Y2.js → memory-LPU2I6NI.js} +3 -5
  38. package/dist/{paths-KXOWF2B2.js → paths-Q4TJEOMQ.js} +2 -2
  39. package/dist/prompt-builder-VHGZFBL6.js +19 -0
  40. package/dist/queue-LNBQWMFX.js +14 -0
  41. package/dist/web-chat/chat.html +38 -958
  42. package/dist/web-chat-DHHJTGFZ.js +253 -0
  43. package/dist/web-chat-DHHJTGFZ.js.map +1 -0
  44. package/dist/x-client-W5IB7XOM.js +12 -0
  45. package/package.json +2 -1
  46. package/dist/chunk-DFSYD45Q.js +0 -665
  47. package/dist/chunk-DFSYD45Q.js.map +0 -1
  48. package/dist/chunk-FCAK5FYQ.js +0 -127
  49. package/dist/chunk-FCAK5FYQ.js.map +0 -1
  50. package/dist/chunk-LRKBNKMQ.js +0 -79
  51. package/dist/chunk-LRKBNKMQ.js.map +0 -1
  52. package/dist/chunk-Q7YS3AIK.js.map +0 -1
  53. package/dist/chunk-QHFM2YW6.js.map +0 -1
  54. package/dist/chunk-R7PAD4OL.js +0 -44
  55. package/dist/chunk-R7PAD4OL.js.map +0 -1
  56. package/dist/chunk-RNVEWVDN.js.map +0 -1
  57. package/dist/chunk-SUFTVQME.js +0 -82
  58. package/dist/chunk-SUFTVQME.js.map +0 -1
  59. package/dist/chunk-SXMDYUK3.js.map +0 -1
  60. package/dist/chunk-YZ7RWJ6Z.js +0 -262
  61. package/dist/chunk-YZ7RWJ6Z.js.map +0 -1
  62. package/dist/client-23THPNVL.js +0 -382
  63. package/dist/client-23THPNVL.js.map +0 -1
  64. package/dist/client-NVI3ZD4G.js.map +0 -1
  65. package/dist/decision-engine-WBD36PZI.js +0 -19
  66. package/dist/goals-IM4AEHS4.js +0 -12
  67. package/dist/heartbeat-35HVB5PB.js +0 -317
  68. package/dist/heartbeat-35HVB5PB.js.map +0 -1
  69. package/dist/image-search-SZVMGWLN.js +0 -45
  70. package/dist/image-search-SZVMGWLN.js.map +0 -1
  71. package/dist/init-ANGLSI2L.js.map +0 -1
  72. package/dist/llm-MHZG2VHU.js +0 -16
  73. package/dist/performance-7G6R6ELJ.js +0 -18
  74. package/dist/prompt-builder-NSU4IFPB.js +0 -28
  75. package/dist/prompt-builder-NSU4IFPB.js.map +0 -1
  76. package/dist/queue-MLRTMJRE.js +0 -14
  77. package/dist/queue-MLRTMJRE.js.map +0 -1
  78. package/dist/strategy-TOVFBIZQ.js +0 -12
  79. package/dist/strategy-TOVFBIZQ.js.map +0 -1
  80. package/dist/web-chat/logo.png +0 -0
  81. package/dist/web-chat-N2AYUWT7.js +0 -802
  82. package/dist/web-chat-N2AYUWT7.js.map +0 -1
  83. package/dist/x-client-HUXCQOAW.js +0 -12
  84. package/dist/x-client-HUXCQOAW.js.map +0 -1
  85. /package/dist/{account-creator-SETL5CGT.js.map → account-creator-AABUY2JU.js.map} +0 -0
  86. /package/dist/{chunk-HERI4RPY.js.map → chunk-A6R5ZGK6.js.map} +0 -0
  87. /package/dist/{chunk-GJFBWIW3.js.map → chunk-FTFTB5Y5.js.map} +0 -0
  88. /package/dist/{chunk-POEDIDM6.js.map → chunk-H62HH5ZI.js.map} +0 -0
  89. /package/dist/{chunk-NLWU5432.js.map → chunk-KQ37VL54.js.map} +0 -0
  90. /package/dist/{chunk-JWMADEQO.js.map → chunk-ML4EMUZC.js.map} +0 -0
  91. /package/dist/{chunk-J7J557HV.js.map → chunk-UCCAF2ZO.js.map} +0 -0
  92. /package/dist/{colony-J4EZQI37.js.map → colony-JVBCMZTK.js.map} +0 -0
  93. /package/dist/{config-QRBOL4NX.js.map → config-5EPXA325.js.map} +0 -0
  94. /package/dist/{crypto-ZVWJLD2J.js.map → crypto-HS4CGS4A.js.map} +0 -0
  95. /package/dist/{decision-engine-WBD36PZI.js.map → identity-6CXRCXJQ.js.map} +0 -0
  96. /package/dist/{goals-IM4AEHS4.js.map → llm-CUCO24K7.js.map} +0 -0
  97. /package/dist/{identity-LN2R4KJU.js.map → memory-2OI3JXY2.js.map} +0 -0
  98. /package/dist/{llm-MHZG2VHU.js.map → memory-LPU2I6NI.js.map} +0 -0
  99. /package/dist/{memory-J6AYZ5Y2.js.map → paths-Q4TJEOMQ.js.map} +0 -0
  100. /package/dist/{memory-JMXU3UXR.js.map → prompt-builder-VHGZFBL6.js.map} +0 -0
  101. /package/dist/{paths-KXOWF2B2.js.map → queue-LNBQWMFX.js.map} +0 -0
  102. /package/dist/{performance-7G6R6ELJ.js.map → x-client-W5IB7XOM.js.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  logger
3
- } from "./chunk-J7J557HV.js";
4
- import "./chunk-Q7YS3AIK.js";
3
+ } from "./chunk-UCCAF2ZO.js";
4
+ import "./chunk-6KCIAMHL.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-KXOWF2B2.js");
74
+ const { paths, ensureDirectories } = await import("./paths-Q4TJEOMQ.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-KXOWF2B2.js");
468
+ const { paths, ensureDirectories } = await import("./paths-Q4TJEOMQ.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-SETL5CGT.js.map
498
+ //# sourceMappingURL=account-creator-AABUY2JU.js.map
@@ -17,6 +17,8 @@ var paths = {
17
17
  learnings: join(SPORA_DIR, "memory", "learnings.json"),
18
18
  relationships: join(SPORA_DIR, "memory", "relationships.json"),
19
19
  compacted: join(SPORA_DIR, "memory", "compacted"),
20
+ mood: join(SPORA_DIR, "memory", "mood.json"),
21
+ missions: join(SPORA_DIR, "missions"),
20
22
  queue: join(SPORA_DIR, "queue"),
21
23
  pendingPosts: join(SPORA_DIR, "queue", "pending-posts.json"),
22
24
  logs: join(SPORA_DIR, "logs"),
@@ -25,11 +27,7 @@ var paths = {
25
27
  llmKey: join(SPORA_DIR, "llm-key"),
26
28
  runtimePid: join(SPORA_DIR, "runtime.pid"),
27
29
  stopSignal: join(SPORA_DIR, "stop"),
28
- connectionToken: join(SPORA_DIR, "connection-token"),
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
+ connectionToken: join(SPORA_DIR, "connection-token")
33
31
  };
34
32
  function ensureDirectories() {
35
33
  const dirs = [
@@ -38,6 +36,7 @@ function ensureDirectories() {
38
36
  paths.memory,
39
37
  paths.interactions,
40
38
  paths.compacted,
39
+ paths.missions,
41
40
  paths.queue,
42
41
  paths.logs
43
42
  ];
@@ -60,4 +59,4 @@ export {
60
59
  sporaExists,
61
60
  hasXCredentials
62
61
  };
63
- //# sourceMappingURL=chunk-Q7YS3AIK.js.map
62
+ //# sourceMappingURL=chunk-6KCIAMHL.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 mood: join(SPORA_DIR, \"memory\", \"mood.json\"),\n missions: join(SPORA_DIR, \"missions\"),\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} 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.missions,\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,MAAM,KAAK,WAAW,UAAU,WAAW;AAAA,EAC3C,UAAU,KAAK,WAAW,UAAU;AAAA,EACpC,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;AACrD;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,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,7 +1,7 @@
1
1
  import {
2
2
  ensureDirectories,
3
3
  paths
4
- } from "./chunk-Q7YS3AIK.js";
4
+ } from "./chunk-6KCIAMHL.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-HERI4RPY.js.map
156
+ //# sourceMappingURL=chunk-A6R5ZGK6.js.map
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  loadConfig
3
- } from "./chunk-SXMDYUK3.js";
3
+ } from "./chunk-GMSK775L.js";
4
4
  import {
5
5
  logger
6
- } from "./chunk-J7J557HV.js";
6
+ } from "./chunk-UCCAF2ZO.js";
7
7
  import {
8
8
  ensureDirectories,
9
9
  paths
10
- } from "./chunk-Q7YS3AIK.js";
10
+ } from "./chunk-6KCIAMHL.js";
11
11
 
12
12
  // src/scheduler/queue.ts
13
13
  import { readFileSync, writeFileSync, existsSync } from "fs";
@@ -48,15 +48,14 @@ function nextScheduledTime() {
48
48
  }
49
49
  return next.toISOString();
50
50
  }
51
- function addToQueue(content, scheduledFor, imageQuery) {
51
+ function addToQueue(content, scheduledFor) {
52
52
  const queue = loadQueue();
53
53
  const entry = {
54
54
  id: `post-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,
55
55
  content,
56
56
  scheduledFor: scheduledFor ?? nextScheduledTime(),
57
57
  status: "pending",
58
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
59
- ...imageQuery ? { imageQuery } : {}
58
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
60
59
  };
61
60
  queue.entries.push(entry);
62
61
  saveQueue(queue);
@@ -68,52 +67,18 @@ async function flushQueue() {
68
67
  const now = /* @__PURE__ */ new Date();
69
68
  let posted = 0;
70
69
  let failed = 0;
71
- const { getXClient } = await import("./x-client-HUXCQOAW.js");
70
+ const { getXClient } = await import("./x-client-W5IB7XOM.js");
72
71
  const client = await getXClient();
73
- const STALE_THRESHOLD_MS = 5 * 60 * 1e3;
74
- for (const entry of queue.entries) {
75
- if (entry.status !== "pending") continue;
76
- const scheduledTime = new Date(entry.scheduledFor).getTime();
77
- if (scheduledTime < now.getTime() - STALE_THRESHOLD_MS) {
78
- entry.status = "expired";
79
- logger.info(`Expired stale post: ${entry.id} (was scheduled for ${entry.scheduledFor})`);
80
- }
81
- }
82
72
  for (const entry of queue.entries) {
83
73
  if (entry.status !== "pending") continue;
84
74
  if (new Date(entry.scheduledFor) > now) continue;
85
75
  try {
86
- let result;
87
- if (entry.imageQuery) {
88
- try {
89
- const { searchImage, downloadImage } = await import("./image-search-SZVMGWLN.js");
90
- const imageUrl = await searchImage(entry.imageQuery);
91
- if (imageUrl) {
92
- const imageBuffer = await downloadImage(imageUrl);
93
- result = await client.postTweetWithMedia(entry.content, imageBuffer);
94
- if (result.success) {
95
- logger.info(`Posted with image: ${entry.id}`);
96
- }
97
- }
98
- } catch (imgErr) {
99
- logger.warn(`Image attach failed for ${entry.id}, posting text only: ${imgErr.message}`);
100
- }
101
- }
102
- if (!result) {
103
- result = await client.postTweet(entry.content);
104
- }
76
+ const result = await client.postTweet(entry.content);
105
77
  if (result.success) {
106
78
  entry.status = "posted";
107
79
  entry.postedAt = (/* @__PURE__ */ new Date()).toISOString();
108
80
  posted++;
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
- }
81
+ logger.info(`Posted: ${entry.id}`);
117
82
  } else {
118
83
  entry.status = "failed";
119
84
  entry.error = result.error;
@@ -156,4 +121,4 @@ export {
156
121
  flushQueue,
157
122
  showQueue
158
123
  };
159
- //# sourceMappingURL=chunk-QHFM2YW6.js.map
124
+ //# sourceMappingURL=chunk-B6VI6L4D.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}\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): 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 };\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 for (const entry of queue.entries) {\n if (entry.status !== \"pending\") continue;\n if (new Date(entry.scheduledFor) > now) continue;\n\n try {\n const result = await client.postTweet(entry.content);\n if (result.success) {\n entry.status = \"posted\";\n entry.postedAt = new Date().toISOString();\n posted++;\n logger.info(`Posted: ${entry.id}`);\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;AAmBxD,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,cAAmC;AAC7E,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,EACpC;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;AAEhC,aAAW,SAAS,MAAM,SAAS;AACjC,QAAI,MAAM,WAAW,UAAW;AAChC,QAAI,IAAI,KAAK,MAAM,YAAY,IAAI,IAAK;AAExC,QAAI;AACF,YAAM,SAAS,MAAM,OAAO,UAAU,MAAM,OAAO;AACnD,UAAI,OAAO,SAAS;AAClB,cAAM,SAAS;AACf,cAAM,YAAW,oBAAI,KAAK,GAAE,YAAY;AACxC;AACA,eAAO,KAAK,WAAW,MAAM,EAAE,EAAE;AAAA,MACnC,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-Q7YS3AIK.js";
4
+ } from "./chunk-6KCIAMHL.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-GJFBWIW3.js.map
622
+ //# sourceMappingURL=chunk-FTFTB5Y5.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  ensureDirectories,
3
3
  paths
4
- } from "./chunk-Q7YS3AIK.js";
4
+ } from "./chunk-6KCIAMHL.js";
5
5
 
6
6
  // src/utils/config.ts
7
7
  import { readFileSync, writeFileSync, existsSync } from "fs";
@@ -22,13 +22,36 @@ var ConfigSchema = z.object({
22
22
  timezone: z.string()
23
23
  }),
24
24
  llm: z.object({
25
- provider: z.enum(["anthropic", "openai"]).default("anthropic"),
26
- model: z.string().default("claude-sonnet-4-20250514")
25
+ provider: z.enum(["anthropic", "openai", "deepseek"]).default("deepseek"),
26
+ model: z.string().default("deepseek-v3.2-speciale"),
27
+ baseUrl: z.string().default("https://api.llm-stats.com/v1")
27
28
  }).optional(),
28
29
  runtime: z.object({
29
- heartbeatIntervalMs: z.number().default(36e5),
30
+ heartbeatIntervalMs: z.number().default(3e5),
30
31
  actionsPerHeartbeat: z.number().default(3),
31
- enabled: z.boolean().default(false)
32
+ enabled: z.boolean().default(false),
33
+ // Mode system configuration
34
+ modeSystem: z.object({
35
+ enabled: z.boolean().default(true),
36
+ allowRestMode: z.boolean().default(true),
37
+ modeWeightOverrides: z.record(z.number()).optional()
38
+ }).optional(),
39
+ // Curiosity system configuration
40
+ curiositySystem: z.object({
41
+ enabled: z.boolean().default(true),
42
+ explorationChance: z.number().default(0.15),
43
+ maxSearchesPerHeartbeat: z.number().default(3)
44
+ }).optional(),
45
+ // Mission system configuration
46
+ missionSystem: z.object({
47
+ enabled: z.boolean().default(true),
48
+ maxActiveMissions: z.number().default(5)
49
+ }).optional(),
50
+ // Variation/mood system configuration
51
+ variationSystem: z.object({
52
+ enabled: z.boolean().default(true),
53
+ moodDriftRate: z.number().default(0.1)
54
+ }).optional()
32
55
  }).optional(),
33
56
  connection: z.object({
34
57
  token: z.string().optional(),
@@ -77,4 +100,4 @@ export {
77
100
  saveConfig,
78
101
  createDefaultConfig
79
102
  };
80
- //# sourceMappingURL=chunk-SXMDYUK3.js.map
103
+ //# sourceMappingURL=chunk-GMSK775L.js.map
@@ -0,0 +1 @@
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":"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","names":[]}
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  ensureDirectories,
3
3
  paths
4
- } from "./chunk-Q7YS3AIK.js";
4
+ } from "./chunk-6KCIAMHL.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-POEDIDM6.js.map
56
+ //# sourceMappingURL=chunk-H62HH5ZI.js.map
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  loadConfig
3
- } from "./chunk-SXMDYUK3.js";
3
+ } from "./chunk-GMSK775L.js";
4
4
  import {
5
5
  logger
6
- } from "./chunk-J7J557HV.js";
6
+ } from "./chunk-UCCAF2ZO.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-23THPNVL.js");
14
+ const { XApiClient } = await import("./client-TWYR2IIQ.js");
15
15
  clientInstance = new XApiClient();
16
16
  logger.info("X client initialized: API mode");
17
17
  } else {
18
- const { XBrowserClient } = await import("./client-NVI3ZD4G.js");
18
+ const { XBrowserClient } = await import("./client-BGLXHLID.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-NLWU5432.js.map
32
+ //# sourceMappingURL=chunk-KQ37VL54.js.map
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  loadConfig,
3
3
  saveConfig
4
- } from "./chunk-SXMDYUK3.js";
4
+ } from "./chunk-GMSK775L.js";
5
5
  import {
6
6
  logger
7
- } from "./chunk-J7J557HV.js";
7
+ } from "./chunk-UCCAF2ZO.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-JWMADEQO.js.map
57
+ //# sourceMappingURL=chunk-ML4EMUZC.js.map
@@ -0,0 +1,86 @@
1
+ import {
2
+ loadConfig
3
+ } from "./chunk-GMSK775L.js";
4
+ import {
5
+ logger
6
+ } from "./chunk-UCCAF2ZO.js";
7
+ import {
8
+ paths
9
+ } from "./chunk-6KCIAMHL.js";
10
+
11
+ // src/runtime/llm.ts
12
+ import OpenAI from "openai";
13
+ import { readFileSync, existsSync } from "fs";
14
+ var client = null;
15
+ var DEFAULT_MODEL = "deepseek-v3.2-speciale";
16
+ var DEFAULT_BASE_URL = "https://api.llm-stats.com/v1";
17
+ function getLLMApiKey() {
18
+ if (process.env.LLM_API_KEY) {
19
+ return process.env.LLM_API_KEY;
20
+ }
21
+ if (process.env.ANTHROPIC_API_KEY) {
22
+ return process.env.ANTHROPIC_API_KEY;
23
+ }
24
+ if (existsSync(paths.llmKey)) {
25
+ return readFileSync(paths.llmKey, "utf-8").trim();
26
+ }
27
+ return null;
28
+ }
29
+ function hasLLMKey() {
30
+ return getLLMApiKey() !== null;
31
+ }
32
+ function getClient() {
33
+ if (client) return client;
34
+ const apiKey = getLLMApiKey();
35
+ if (!apiKey) {
36
+ throw new Error("No LLM API key configured. Run `spora set-llm-key` first.");
37
+ }
38
+ const config = loadConfig();
39
+ const baseURL = config.llm?.baseUrl ?? DEFAULT_BASE_URL;
40
+ client = new OpenAI({ apiKey, baseURL });
41
+ return client;
42
+ }
43
+ async function generateResponse(systemPrompt, userMessage) {
44
+ const config = loadConfig();
45
+ const model = config.llm?.model ?? DEFAULT_MODEL;
46
+ logger.info(`Calling LLM (${model})...`);
47
+ const openai = getClient();
48
+ const response = await openai.chat.completions.create({
49
+ model,
50
+ max_tokens: 2048,
51
+ messages: [
52
+ { role: "system", content: systemPrompt },
53
+ { role: "user", content: userMessage }
54
+ ]
55
+ });
56
+ const content = response.choices[0]?.message?.content ?? "";
57
+ const inputTokens = response.usage?.prompt_tokens ?? 0;
58
+ const outputTokens = response.usage?.completion_tokens ?? 0;
59
+ logger.info(`LLM response: ${inputTokens} in, ${outputTokens} out`);
60
+ return { content, inputTokens, outputTokens };
61
+ }
62
+ async function chat(systemPrompt, messages) {
63
+ const config = loadConfig();
64
+ const model = config.llm?.model ?? DEFAULT_MODEL;
65
+ const openai = getClient();
66
+ const response = await openai.chat.completions.create({
67
+ model,
68
+ max_tokens: 2048,
69
+ messages: [
70
+ { role: "system", content: systemPrompt },
71
+ ...messages
72
+ ]
73
+ });
74
+ const content = response.choices[0]?.message?.content ?? "";
75
+ const inputTokens = response.usage?.prompt_tokens ?? 0;
76
+ const outputTokens = response.usage?.completion_tokens ?? 0;
77
+ return { content, inputTokens, outputTokens };
78
+ }
79
+
80
+ export {
81
+ getLLMApiKey,
82
+ hasLLMKey,
83
+ generateResponse,
84
+ chat
85
+ };
86
+ //# sourceMappingURL=chunk-N5TBL3NY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime/llm.ts"],"sourcesContent":["import OpenAI from \"openai\";\nimport { readFileSync, existsSync } from \"node:fs\";\nimport { paths } from \"../utils/paths.js\";\nimport { loadConfig } from \"../utils/config.js\";\nimport { logger } from \"../utils/logger.js\";\n\nlet client: OpenAI | null = null;\n\nconst DEFAULT_MODEL = \"deepseek-v3.2-speciale\";\nconst DEFAULT_BASE_URL = \"https://api.llm-stats.com/v1\";\n\nexport function getLLMApiKey(): string | null {\n // Check env first (support both old and new env var names), then file\n if (process.env.LLM_API_KEY) {\n return process.env.LLM_API_KEY;\n }\n if (process.env.ANTHROPIC_API_KEY) {\n return process.env.ANTHROPIC_API_KEY;\n }\n if (existsSync(paths.llmKey)) {\n return readFileSync(paths.llmKey, \"utf-8\").trim();\n }\n return null;\n}\n\nexport function hasLLMKey(): boolean {\n return getLLMApiKey() !== null;\n}\n\nfunction getClient(): OpenAI {\n if (client) return client;\n const apiKey = getLLMApiKey();\n if (!apiKey) {\n throw new Error(\"No LLM API key configured. Run `spora set-llm-key` first.\");\n }\n const config = loadConfig();\n const baseURL = config.llm?.baseUrl ?? DEFAULT_BASE_URL;\n client = new OpenAI({ apiKey, baseURL });\n return client;\n}\n\nexport interface LLMResponse {\n content: string;\n inputTokens: number;\n outputTokens: number;\n}\n\nexport async function generateResponse(\n systemPrompt: string,\n userMessage: string,\n): Promise<LLMResponse> {\n const config = loadConfig();\n const model = config.llm?.model ?? DEFAULT_MODEL;\n\n logger.info(`Calling LLM (${model})...`);\n\n const openai = getClient();\n const response = await openai.chat.completions.create({\n model,\n max_tokens: 2048,\n messages: [\n { role: \"system\", content: systemPrompt },\n { role: \"user\", content: userMessage },\n ],\n });\n\n const content = response.choices[0]?.message?.content ?? \"\";\n const inputTokens = response.usage?.prompt_tokens ?? 0;\n const outputTokens = response.usage?.completion_tokens ?? 0;\n\n logger.info(`LLM response: ${inputTokens} in, ${outputTokens} out`);\n\n return { content, inputTokens, outputTokens };\n}\n\nexport async function chat(\n systemPrompt: string,\n messages: Array<{ role: \"user\" | \"assistant\"; content: string }>,\n): Promise<LLMResponse> {\n const config = loadConfig();\n const model = config.llm?.model ?? DEFAULT_MODEL;\n\n const openai = getClient();\n const response = await openai.chat.completions.create({\n model,\n max_tokens: 2048,\n messages: [\n { role: \"system\", content: systemPrompt },\n ...messages,\n ],\n });\n\n const content = response.choices[0]?.message?.content ?? \"\";\n const inputTokens = response.usage?.prompt_tokens ?? 0;\n const outputTokens = response.usage?.completion_tokens ?? 0;\n\n return { content, inputTokens, outputTokens };\n}\n"],"mappings":";;;;;;;;;;;AAAA,OAAO,YAAY;AACnB,SAAS,cAAc,kBAAkB;AAKzC,IAAI,SAAwB;AAE5B,IAAM,gBAAgB;AACtB,IAAM,mBAAmB;AAElB,SAAS,eAA8B;AAE5C,MAAI,QAAQ,IAAI,aAAa;AAC3B,WAAO,QAAQ,IAAI;AAAA,EACrB;AACA,MAAI,QAAQ,IAAI,mBAAmB;AACjC,WAAO,QAAQ,IAAI;AAAA,EACrB;AACA,MAAI,WAAW,MAAM,MAAM,GAAG;AAC5B,WAAO,aAAa,MAAM,QAAQ,OAAO,EAAE,KAAK;AAAA,EAClD;AACA,SAAO;AACT;AAEO,SAAS,YAAqB;AACnC,SAAO,aAAa,MAAM;AAC5B;AAEA,SAAS,YAAoB;AAC3B,MAAI,OAAQ,QAAO;AACnB,QAAM,SAAS,aAAa;AAC5B,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,2DAA2D;AAAA,EAC7E;AACA,QAAM,SAAS,WAAW;AAC1B,QAAM,UAAU,OAAO,KAAK,WAAW;AACvC,WAAS,IAAI,OAAO,EAAE,QAAQ,QAAQ,CAAC;AACvC,SAAO;AACT;AAQA,eAAsB,iBACpB,cACA,aACsB;AACtB,QAAM,SAAS,WAAW;AAC1B,QAAM,QAAQ,OAAO,KAAK,SAAS;AAEnC,SAAO,KAAK,gBAAgB,KAAK,MAAM;AAEvC,QAAM,SAAS,UAAU;AACzB,QAAM,WAAW,MAAM,OAAO,KAAK,YAAY,OAAO;AAAA,IACpD;AAAA,IACA,YAAY;AAAA,IACZ,UAAU;AAAA,MACR,EAAE,MAAM,UAAU,SAAS,aAAa;AAAA,MACxC,EAAE,MAAM,QAAQ,SAAS,YAAY;AAAA,IACvC;AAAA,EACF,CAAC;AAED,QAAM,UAAU,SAAS,QAAQ,CAAC,GAAG,SAAS,WAAW;AACzD,QAAM,cAAc,SAAS,OAAO,iBAAiB;AACrD,QAAM,eAAe,SAAS,OAAO,qBAAqB;AAE1D,SAAO,KAAK,iBAAiB,WAAW,QAAQ,YAAY,MAAM;AAElE,SAAO,EAAE,SAAS,aAAa,aAAa;AAC9C;AAEA,eAAsB,KACpB,cACA,UACsB;AACtB,QAAM,SAAS,WAAW;AAC1B,QAAM,QAAQ,OAAO,KAAK,SAAS;AAEnC,QAAM,SAAS,UAAU;AACzB,QAAM,WAAW,MAAM,OAAO,KAAK,YAAY,OAAO;AAAA,IACpD;AAAA,IACA,YAAY;AAAA,IACZ,UAAU;AAAA,MACR,EAAE,MAAM,UAAU,SAAS,aAAa;AAAA,MACxC,GAAG;AAAA,IACL;AAAA,EACF,CAAC;AAED,QAAM,UAAU,SAAS,QAAQ,CAAC,GAAG,SAAS,WAAW;AACzD,QAAM,cAAc,SAAS,OAAO,iBAAiB;AACrD,QAAM,eAAe,SAAS,OAAO,qBAAqB;AAE1D,SAAO,EAAE,SAAS,aAAa,aAAa;AAC9C;","names":[]}