spora 0.7.0 → 0.7.2

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 (103) hide show
  1. package/README.md +7 -5
  2. package/dist/autonomy-DAV7X6QS.js +19 -0
  3. package/dist/{chunk-53YLFYJF.js → chunk-3RYCUGXE.js} +6 -2
  4. package/dist/chunk-3RYCUGXE.js.map +1 -0
  5. package/dist/{chunk-AH7HPXYC.js → chunk-AOQ3WLZV.js} +153 -143
  6. package/dist/chunk-AOQ3WLZV.js.map +1 -0
  7. package/dist/chunk-E5NR6HT4.js +29 -0
  8. package/dist/chunk-E5NR6HT4.js.map +1 -0
  9. package/dist/{chunk-EBO4F5NU.js → chunk-JBYZ7K56.js} +2 -2
  10. package/dist/chunk-KWWAIS3C.js +180 -0
  11. package/dist/chunk-KWWAIS3C.js.map +1 -0
  12. package/dist/{chunk-UINSD4FT.js → chunk-LXQNVVIY.js} +6 -6
  13. package/dist/{chunk-UINSD4FT.js.map → chunk-LXQNVVIY.js.map} +1 -1
  14. package/dist/{chunk-AIEXQCQS.js → chunk-M6YOQVSI.js} +2 -2
  15. package/dist/{chunk-B6RPMDML.js → chunk-NO3NQN67.js} +16 -6
  16. package/dist/chunk-NO3NQN67.js.map +1 -0
  17. package/dist/{chunk-QOKQ5OTU.js → chunk-NPV3OV2K.js} +3 -14
  18. package/dist/chunk-NPV3OV2K.js.map +1 -0
  19. package/dist/{chunk-SBQILQCJ.js → chunk-OACD3HGE.js} +7 -7
  20. package/dist/{chunk-UM57WU5I.js → chunk-P6KZIJYL.js} +2 -2
  21. package/dist/{chunk-AHXZIGQE.js → chunk-T7L2L7ZL.js} +2 -2
  22. package/dist/{chunk-ZJZKH7N7.js → chunk-VZBHRUZS.js} +2 -2
  23. package/dist/chunk-VZBHRUZS.js.map +1 -0
  24. package/dist/chunk-WIK74GGJ.js +295 -0
  25. package/dist/chunk-WIK74GGJ.js.map +1 -0
  26. package/dist/{chunk-YLJVFCT4.js → chunk-WN35MRMF.js} +2 -2
  27. package/dist/cli.js +173 -138
  28. package/dist/cli.js.map +1 -1
  29. package/dist/client-57BQKVYF.js +337 -0
  30. package/dist/client-57BQKVYF.js.map +1 -0
  31. package/dist/{colony-LCWN5IAN.js → colony-JPZC3R34.js} +7 -7
  32. package/dist/{config-TFAFYSIW.js → config-FL4VJVKZ.js} +3 -3
  33. package/dist/{crypto-FHSQ72NU.js → crypto-NOXNL4GP.js} +3 -3
  34. package/dist/{goals-5TAPXNR2.js → goals-RBKLMILE.js} +3 -3
  35. package/dist/{heartbeat-ZHRCEMF5.js → heartbeat-TNEPE3ZP.js} +83 -88
  36. package/dist/heartbeat-TNEPE3ZP.js.map +1 -0
  37. package/dist/{identity-O4FLSZKZ.js → identity-VDUW4I2K.js} +3 -3
  38. package/dist/{init-G3WINLAP.js → init-ISSXETHY.js} +59 -46
  39. package/dist/init-ISSXETHY.js.map +1 -0
  40. package/dist/llm-T33QTPVW.js +22 -0
  41. package/dist/mcp-server.js +28 -28
  42. package/dist/mcp-server.js.map +1 -1
  43. package/dist/{memory-O3AJIKBX.js → memory-OIAH33G2.js} +3 -3
  44. package/dist/{memory-7FBE26K3.js → memory-PNW7SX7A.js} +3 -3
  45. package/dist/{paths-5GFUUHCZ.js → paths-BYR6MEPR.js} +2 -2
  46. package/dist/prompt-builder-5NYONN2W.js +23 -0
  47. package/dist/queue-G5PTE6R6.js +14 -0
  48. package/dist/{strategy-S45TX766.js → strategy-Z4JSFHSP.js} +3 -3
  49. package/dist/{web-chat-RQIILEQK.js → web-chat-3HM35XM4.js} +31 -80
  50. package/dist/web-chat-3HM35XM4.js.map +1 -0
  51. package/dist/x-client-GY6XSPK6.js +12 -0
  52. package/package.json +1 -1
  53. package/dist/account-creator-ZD643X3Z.js +0 -498
  54. package/dist/account-creator-ZD643X3Z.js.map +0 -1
  55. package/dist/chunk-535NMUUW.js +0 -96
  56. package/dist/chunk-535NMUUW.js.map +0 -1
  57. package/dist/chunk-53YLFYJF.js.map +0 -1
  58. package/dist/chunk-55XPDJ6P.js +0 -124
  59. package/dist/chunk-55XPDJ6P.js.map +0 -1
  60. package/dist/chunk-AH7HPXYC.js.map +0 -1
  61. package/dist/chunk-B6RPMDML.js.map +0 -1
  62. package/dist/chunk-E6GMS76S.js +0 -154
  63. package/dist/chunk-E6GMS76S.js.map +0 -1
  64. package/dist/chunk-JJZ7T2IZ.js +0 -32
  65. package/dist/chunk-JJZ7T2IZ.js.map +0 -1
  66. package/dist/chunk-QOKQ5OTU.js.map +0 -1
  67. package/dist/chunk-TF2XYGGG.js +0 -249
  68. package/dist/chunk-TF2XYGGG.js.map +0 -1
  69. package/dist/chunk-ZJZKH7N7.js.map +0 -1
  70. package/dist/client-B6NGVRHM.js +0 -381
  71. package/dist/client-B6NGVRHM.js.map +0 -1
  72. package/dist/client-DDCS5FJS.js +0 -412
  73. package/dist/client-DDCS5FJS.js.map +0 -1
  74. package/dist/decision-engine-DRPIZLHI.js +0 -19
  75. package/dist/heartbeat-ZHRCEMF5.js.map +0 -1
  76. package/dist/init-G3WINLAP.js.map +0 -1
  77. package/dist/llm-3LSNADSR.js +0 -16
  78. package/dist/prompt-builder-U2J4H7YX.js +0 -24
  79. package/dist/queue-USY7JXDV.js +0 -14
  80. package/dist/research-TQLP42BC.js +0 -13
  81. package/dist/web-chat-RQIILEQK.js.map +0 -1
  82. package/dist/x-client-TYU5QSLG.js +0 -12
  83. package/dist/x-client-TYU5QSLG.js.map +0 -1
  84. /package/dist/{config-TFAFYSIW.js.map → autonomy-DAV7X6QS.js.map} +0 -0
  85. /package/dist/{chunk-EBO4F5NU.js.map → chunk-JBYZ7K56.js.map} +0 -0
  86. /package/dist/{chunk-AIEXQCQS.js.map → chunk-M6YOQVSI.js.map} +0 -0
  87. /package/dist/{chunk-SBQILQCJ.js.map → chunk-OACD3HGE.js.map} +0 -0
  88. /package/dist/{chunk-UM57WU5I.js.map → chunk-P6KZIJYL.js.map} +0 -0
  89. /package/dist/{chunk-AHXZIGQE.js.map → chunk-T7L2L7ZL.js.map} +0 -0
  90. /package/dist/{chunk-YLJVFCT4.js.map → chunk-WN35MRMF.js.map} +0 -0
  91. /package/dist/{colony-LCWN5IAN.js.map → colony-JPZC3R34.js.map} +0 -0
  92. /package/dist/{crypto-FHSQ72NU.js.map → config-FL4VJVKZ.js.map} +0 -0
  93. /package/dist/{decision-engine-DRPIZLHI.js.map → crypto-NOXNL4GP.js.map} +0 -0
  94. /package/dist/{goals-5TAPXNR2.js.map → goals-RBKLMILE.js.map} +0 -0
  95. /package/dist/{identity-O4FLSZKZ.js.map → identity-VDUW4I2K.js.map} +0 -0
  96. /package/dist/{llm-3LSNADSR.js.map → llm-T33QTPVW.js.map} +0 -0
  97. /package/dist/{memory-7FBE26K3.js.map → memory-OIAH33G2.js.map} +0 -0
  98. /package/dist/{memory-O3AJIKBX.js.map → memory-PNW7SX7A.js.map} +0 -0
  99. /package/dist/{paths-5GFUUHCZ.js.map → paths-BYR6MEPR.js.map} +0 -0
  100. /package/dist/{prompt-builder-U2J4H7YX.js.map → prompt-builder-5NYONN2W.js.map} +0 -0
  101. /package/dist/{queue-USY7JXDV.js.map → queue-G5PTE6R6.js.map} +0 -0
  102. /package/dist/{research-TQLP42BC.js.map → strategy-Z4JSFHSP.js.map} +0 -0
  103. /package/dist/{strategy-S45TX766.js.map → x-client-GY6XSPK6.js.map} +0 -0
package/dist/cli.js CHANGED
@@ -1,7 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- loadConfig
4
- } from "./chunk-B6RPMDML.js";
5
2
  import {
6
3
  FRAMEWORKS,
7
4
  GOAL_PRESETS,
@@ -11,15 +8,20 @@ import {
11
8
  mutateIdentity,
12
9
  renderIdentityDocument,
13
10
  saveIdentity
14
- } from "./chunk-AIEXQCQS.js";
11
+ } from "./chunk-M6YOQVSI.js";
12
+ import {
13
+ loadConfig
14
+ } from "./chunk-NO3NQN67.js";
15
15
  import {
16
16
  hasXCredentials,
17
17
  sporaExists
18
- } from "./chunk-53YLFYJF.js";
18
+ } from "./chunk-3RYCUGXE.js";
19
19
 
20
20
  // src/cli.ts
21
21
  import { Command } from "commander";
22
22
  import chalk from "chalk";
23
+ import { readFileSync } from "fs";
24
+ import { join } from "path";
23
25
  var BANNER = `
24
26
  \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557
25
27
  \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557
@@ -29,101 +31,43 @@ var BANNER = `
29
31
  \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D
30
32
  `;
31
33
  var program = new Command();
32
- program.name("spora").description("AI agents (Spores) that autonomously manage X/Twitter accounts").version("0.1.6");
33
- program.command("init").description("Set up X account credentials for your Spore").option("--token <token>", "Connection token from spora.dev for auto-connect").option("--method <method>", "Connection method: create | browser | api").option("--username <username>", "X username (without @)").option("--password <password>", "X password").option("--email <email>", "Email associated with X account").option("--account-name <name>", "Name for the new X account (create mode)").option("--api-key <key>", "X API Key (api mode)").option("--api-secret <secret>", "X API Secret (api mode)").option("--access-token <token>", "X Access Token (api mode)").option("--access-token-secret <secret>", "X Access Token Secret (api mode)").option("--bearer-token <token>", "X Bearer Token (api mode)").option("--api-tier <tier>", "X API tier: free | basic (api mode)").action(async (opts) => {
34
+ var packageJsonPath = join(import.meta.dirname, "../package.json");
35
+ var cliVersion = JSON.parse(readFileSync(packageJsonPath, "utf-8")).version;
36
+ program.name("spora").description("AI agents (Spores) that autonomously manage X/Twitter accounts").version(cliVersion);
37
+ program.command("init").description("Set up X account credentials for your Spore").option("--token <token>", "Connection token from spora.dev for auto-connect").option("--method <method>", "Connection method (api only)").option("--api-key <key>", "X API Key (api mode)").option("--api-secret <secret>", "X API Secret (api mode)").option("--access-token <token>", "X Access Token (api mode)").option("--access-token-secret <secret>", "X Access Token Secret (api mode)").option("--bearer-token <token>", "X Bearer Token (optional, recommended)").option("--api-tier <tier>", "X API tier: free | basic (api mode)").action(async (opts) => {
34
38
  if (opts.method) {
35
- const { ensureDirectories } = await import("./paths-5GFUUHCZ.js");
36
- const { saveCredentials } = await import("./crypto-FHSQ72NU.js");
37
- const { createDefaultConfig, saveConfig } = await import("./config-TFAFYSIW.js");
39
+ const { ensureDirectories } = await import("./paths-BYR6MEPR.js");
40
+ const { saveCredentials } = await import("./crypto-NOXNL4GP.js");
41
+ const { createDefaultConfig, saveConfig } = await import("./config-FL4VJVKZ.js");
38
42
  ensureDirectories();
39
- if (opts.method === "create") {
40
- const accountName = opts.accountName ?? `Spore${Math.floor(Math.random() * 9e3) + 1e3}`;
41
- console.log(JSON.stringify({ status: "Ensuring browser is installed..." }));
42
- const { execSync } = await import("child_process");
43
- try {
44
- execSync("npx playwright install chromium", { stdio: "pipe" });
45
- } catch {
46
- }
47
- console.log(JSON.stringify({ status: "Creating X account...", name: accountName }));
48
- try {
49
- const { provisionAccount } = await import("./account-creator-ZD643X3Z.js");
50
- const result = await provisionAccount({
51
- name: accountName
52
- });
53
- if (result.success) {
54
- saveCredentials({
55
- method: "browser",
56
- username: result.username,
57
- password: result.password,
58
- email: result.email
59
- });
60
- const config2 = createDefaultConfig({ xMethod: "browser" });
61
- saveConfig(config2);
62
- console.log(JSON.stringify({
63
- success: true,
64
- method: "browser",
65
- username: result.username,
66
- email: result.email,
67
- message: "X account created and credentials saved!"
68
- }));
69
- } else {
70
- console.log(JSON.stringify({
71
- success: false,
72
- error: result.error,
73
- message: "Automated creation failed. Try again with --method browser and provide existing credentials."
74
- }));
75
- process.exit(1);
76
- }
77
- } catch (error) {
78
- console.log(JSON.stringify({
79
- success: false,
80
- error: error.message,
81
- message: "Account creation failed. Try --method browser with existing credentials instead."
82
- }));
83
- process.exit(1);
84
- }
85
- return;
43
+ if (opts.method !== "api") {
44
+ console.log(JSON.stringify({ error: "Only API mode is supported. Use --method api." }));
45
+ process.exit(1);
86
46
  }
87
- if (opts.method === "browser") {
88
- if (!opts.username || !opts.password) {
89
- console.log(JSON.stringify({ error: "Browser mode requires --username and --password" }));
90
- process.exit(1);
91
- }
92
- saveCredentials({
93
- method: "browser",
94
- username: opts.username,
95
- password: opts.password,
96
- email: opts.email
97
- });
98
- } else if (opts.method === "api") {
99
- if (!opts.apiKey || !opts.apiSecret || !opts.accessToken || !opts.accessTokenSecret || !opts.bearerToken) {
100
- console.log(JSON.stringify({ error: "API mode requires --api-key, --api-secret, --access-token, --access-token-secret, --bearer-token" }));
101
- process.exit(1);
102
- }
103
- saveCredentials({
104
- method: "api",
105
- apiKey: opts.apiKey,
106
- apiSecret: opts.apiSecret,
107
- accessToken: opts.accessToken,
108
- accessTokenSecret: opts.accessTokenSecret,
109
- bearerToken: opts.bearerToken
110
- });
111
- } else {
112
- console.log(JSON.stringify({ error: "Method must be 'create', 'browser', or 'api'" }));
47
+ if (!opts.apiKey || !opts.apiSecret || !opts.accessToken || !opts.accessTokenSecret) {
48
+ console.log(JSON.stringify({ error: "API mode requires --api-key, --api-secret, --access-token, --access-token-secret" }));
113
49
  process.exit(1);
114
50
  }
51
+ saveCredentials({
52
+ method: "api",
53
+ apiKey: opts.apiKey,
54
+ apiSecret: opts.apiSecret,
55
+ accessToken: opts.accessToken,
56
+ accessTokenSecret: opts.accessTokenSecret,
57
+ bearerToken: opts.bearerToken
58
+ });
115
59
  const config = createDefaultConfig({
116
- xMethod: opts.method === "create" ? "browser" : opts.method,
60
+ xMethod: "api",
117
61
  xApiTier: opts.apiTier
118
62
  });
119
63
  saveConfig(config);
120
- console.log(JSON.stringify({ success: true, method: opts.method, username: opts.username || "api-mode" }));
64
+ console.log(JSON.stringify({ success: true, method: opts.method }));
121
65
  return;
122
66
  }
123
67
  console.log(chalk.cyan(BANNER));
124
68
  console.log(chalk.bold("Welcome to Spora."));
125
69
  console.log(chalk.gray("The global town square for AI agents.\n"));
126
- const { runInit } = await import("./init-G3WINLAP.js");
70
+ const { runInit } = await import("./init-ISSXETHY.js");
127
71
  await runInit(opts.token);
128
72
  });
129
73
  program.command("serve").description("Start the Spora MCP server (stdio)").action(async () => {
@@ -135,7 +79,7 @@ program.command("chat").description("Open web-based chat interface with your Spo
135
79
  console.log(chalk.red("\u2717 No identity found. Run `spora create` first."));
136
80
  process.exit(1);
137
81
  }
138
- const { startWebChat } = await import("./web-chat-RQIILEQK.js");
82
+ const { startWebChat } = await import("./web-chat-3HM35XM4.js");
139
83
  await startWebChat();
140
84
  });
141
85
  program.command("tui").description("Start terminal-based chat interface (TUI)").action(async () => {
@@ -278,7 +222,7 @@ program.command("journal").description("Add a reflection to the evolution journa
278
222
  });
279
223
  program.command("post").description("Post a tweet").argument("<content>", "Tweet content (max 280 chars)").action(async (content) => {
280
224
  try {
281
- const { getXClient } = await import("./x-client-TYU5QSLG.js");
225
+ const { getXClient } = await import("./x-client-GY6XSPK6.js");
282
226
  const client = await getXClient();
283
227
  const result = await client.postTweet(content);
284
228
  console.log(JSON.stringify(result, null, 2));
@@ -289,7 +233,7 @@ program.command("post").description("Post a tweet").argument("<content>", "Tweet
289
233
  });
290
234
  program.command("reply").description("Reply to a tweet").argument("<tweetId>", "Tweet ID to reply to").argument("<content>", "Reply content").action(async (tweetId, content) => {
291
235
  try {
292
- const { getXClient } = await import("./x-client-TYU5QSLG.js");
236
+ const { getXClient } = await import("./x-client-GY6XSPK6.js");
293
237
  const client = await getXClient();
294
238
  const result = await client.replyToTweet(tweetId, content);
295
239
  console.log(JSON.stringify(result, null, 2));
@@ -300,7 +244,7 @@ program.command("reply").description("Reply to a tweet").argument("<tweetId>", "
300
244
  });
301
245
  program.command("like").description("Like a tweet").argument("<tweetId>", "Tweet ID").action(async (tweetId) => {
302
246
  try {
303
- const { getXClient } = await import("./x-client-TYU5QSLG.js");
247
+ const { getXClient } = await import("./x-client-GY6XSPK6.js");
304
248
  const client = await getXClient();
305
249
  const result = await client.likeTweet(tweetId);
306
250
  console.log(JSON.stringify(result, null, 2));
@@ -311,7 +255,7 @@ program.command("like").description("Like a tweet").argument("<tweetId>", "Tweet
311
255
  });
312
256
  program.command("retweet").description("Retweet a tweet").argument("<tweetId>", "Tweet ID").action(async (tweetId) => {
313
257
  try {
314
- const { getXClient } = await import("./x-client-TYU5QSLG.js");
258
+ const { getXClient } = await import("./x-client-GY6XSPK6.js");
315
259
  const client = await getXClient();
316
260
  const result = await client.retweet(tweetId);
317
261
  console.log(JSON.stringify(result, null, 2));
@@ -322,7 +266,7 @@ program.command("retweet").description("Retweet a tweet").argument("<tweetId>",
322
266
  });
323
267
  program.command("follow").description("Follow a user").argument("<handle>", "User handle or ID").action(async (handle) => {
324
268
  try {
325
- const { getXClient } = await import("./x-client-TYU5QSLG.js");
269
+ const { getXClient } = await import("./x-client-GY6XSPK6.js");
326
270
  const client = await getXClient();
327
271
  const result = await client.followUser(handle);
328
272
  console.log(JSON.stringify(result, null, 2));
@@ -333,7 +277,7 @@ program.command("follow").description("Follow a user").argument("<handle>", "Use
333
277
  });
334
278
  program.command("unfollow").description("Unfollow a user").argument("<handle>", "User handle or ID").action(async (handle) => {
335
279
  try {
336
- const { getXClient } = await import("./x-client-TYU5QSLG.js");
280
+ const { getXClient } = await import("./x-client-GY6XSPK6.js");
337
281
  const client = await getXClient();
338
282
  const result = await client.unfollowUser(handle);
339
283
  console.log(JSON.stringify(result, null, 2));
@@ -344,7 +288,7 @@ program.command("unfollow").description("Unfollow a user").argument("<handle>",
344
288
  });
345
289
  program.command("timeline").description("Read home timeline").option("-c, --count <n>", "Number of tweets", "20").action(async (opts) => {
346
290
  try {
347
- const { getXClient } = await import("./x-client-TYU5QSLG.js");
291
+ const { getXClient } = await import("./x-client-GY6XSPK6.js");
348
292
  const client = await getXClient();
349
293
  const result = await client.getTimeline({ count: parseInt(opts.count) });
350
294
  console.log(JSON.stringify(result, null, 2));
@@ -355,7 +299,7 @@ program.command("timeline").description("Read home timeline").option("-c, --coun
355
299
  });
356
300
  program.command("mentions").description("Read mentions").option("-c, --count <n>", "Number of mentions", "20").action(async (opts) => {
357
301
  try {
358
- const { getXClient } = await import("./x-client-TYU5QSLG.js");
302
+ const { getXClient } = await import("./x-client-GY6XSPK6.js");
359
303
  const client = await getXClient();
360
304
  const result = await client.getMentions({ count: parseInt(opts.count) });
361
305
  console.log(JSON.stringify(result, null, 2));
@@ -366,7 +310,7 @@ program.command("mentions").description("Read mentions").option("-c, --count <n>
366
310
  });
367
311
  program.command("search").description("Search for tweets").argument("<query>", "Search query").option("-c, --count <n>", "Number of results", "20").action(async (query, opts) => {
368
312
  try {
369
- const { getXClient } = await import("./x-client-TYU5QSLG.js");
313
+ const { getXClient } = await import("./x-client-GY6XSPK6.js");
370
314
  const client = await getXClient();
371
315
  const result = await client.searchTweets(query, { count: parseInt(opts.count) });
372
316
  console.log(JSON.stringify(result, null, 2));
@@ -377,7 +321,7 @@ program.command("search").description("Search for tweets").argument("<query>", "
377
321
  });
378
322
  program.command("profile").description("Get a user's X profile").argument("<handle>", "X handle (without @)").action(async (handle) => {
379
323
  try {
380
- const { getXClient } = await import("./x-client-TYU5QSLG.js");
324
+ const { getXClient } = await import("./x-client-GY6XSPK6.js");
381
325
  const client = await getXClient();
382
326
  const result = await client.getProfile(handle);
383
327
  console.log(JSON.stringify(result, null, 2));
@@ -399,7 +343,7 @@ program.command("credits").description("Check remaining posting credits").action
399
343
  });
400
344
  program.command("memory").description("Read memory (interactions, learnings, relationships)").argument("<type>", "interactions | learnings | relationships").option("-d, --date <date>", "For interactions: specific date (YYYY-MM-DD)").option("-c, --count <n>", "For interactions: count", "20").action(async (type, opts) => {
401
345
  try {
402
- const { getRecentInteractions, getInteractions, loadLearnings, loadRelationships } = await import("./memory-O3AJIKBX.js");
346
+ const { getRecentInteractions, getInteractions, loadLearnings, loadRelationships } = await import("./memory-OIAH33G2.js");
403
347
  let data;
404
348
  switch (type) {
405
349
  case "interactions":
@@ -423,7 +367,7 @@ program.command("memory").description("Read memory (interactions, learnings, rel
423
367
  });
424
368
  program.command("learn").description("Store a learning").argument("<content>", "What you learned").option("-t, --tags <tags...>", "Tags for categorization").action(async (content, opts) => {
425
369
  try {
426
- const { addLearning } = await import("./memory-O3AJIKBX.js");
370
+ const { addLearning } = await import("./memory-OIAH33G2.js");
427
371
  addLearning(content, "agent", opts.tags ?? []);
428
372
  console.log(JSON.stringify({ success: true }));
429
373
  } catch (error) {
@@ -433,7 +377,7 @@ program.command("learn").description("Store a learning").argument("<content>", "
433
377
  });
434
378
  program.command("note").description("Add a relationship note about someone").argument("<handle>", "Their X handle").argument("<content>", "Your note").action(async (handle, content) => {
435
379
  try {
436
- const { updateRelationship } = await import("./memory-O3AJIKBX.js");
380
+ const { updateRelationship } = await import("./memory-OIAH33G2.js");
437
381
  updateRelationship(handle, { handle, notes: [content] });
438
382
  console.log(JSON.stringify({ success: true, handle }));
439
383
  } catch (error) {
@@ -443,7 +387,7 @@ program.command("note").description("Add a relationship note about someone").arg
443
387
  });
444
388
  program.command("schedule").description("Queue a post for later").argument("<content>", "Tweet content").option("--at <datetime>", "ISO datetime to post at").action(async (content, opts) => {
445
389
  try {
446
- const { addToQueue } = await import("./queue-USY7JXDV.js");
390
+ const { addToQueue } = await import("./queue-G5PTE6R6.js");
447
391
  const entry = addToQueue(content, opts.at);
448
392
  console.log(JSON.stringify({ success: true, id: entry.id, scheduledFor: entry.scheduledFor }));
449
393
  } catch (error) {
@@ -453,7 +397,7 @@ program.command("schedule").description("Queue a post for later").argument("<con
453
397
  });
454
398
  program.command("flush").description("Post all queued items whose time has come").action(async () => {
455
399
  try {
456
- const { flushQueue } = await import("./queue-USY7JXDV.js");
400
+ const { flushQueue } = await import("./queue-G5PTE6R6.js");
457
401
  const results = await flushQueue();
458
402
  console.log(JSON.stringify(results, null, 2));
459
403
  } catch (error) {
@@ -462,13 +406,13 @@ program.command("flush").description("Post all queued items whose time has come"
462
406
  }
463
407
  });
464
408
  program.command("queue").description("Show scheduled posts").action(async () => {
465
- const { showQueue } = await import("./queue-USY7JXDV.js");
409
+ const { showQueue } = await import("./queue-G5PTE6R6.js");
466
410
  showQueue();
467
411
  });
468
412
  var colony = program.command("colony").description("Colony commands");
469
413
  colony.command("checkin").description("Check into The Colony \u2014 sync memory, discover Spores").option("-m, --message <msg>", "Optional message to post").action(async (opts) => {
470
414
  try {
471
- const { colonyCheckin } = await import("./colony-LCWN5IAN.js");
415
+ const { colonyCheckin } = await import("./colony-JPZC3R34.js");
472
416
  const result = await colonyCheckin(opts.message);
473
417
  console.log(JSON.stringify(result, null, 2));
474
418
  } catch (error) {
@@ -478,7 +422,7 @@ colony.command("checkin").description("Check into The Colony \u2014 sync memory,
478
422
  });
479
423
  colony.command("memory").description("Read the Colony's shared memory").action(async () => {
480
424
  try {
481
- const { renderColonyBriefing } = await import("./memory-7FBE26K3.js");
425
+ const { renderColonyBriefing } = await import("./memory-PNW7SX7A.js");
482
426
  console.log(renderColonyBriefing());
483
427
  } catch (error) {
484
428
  console.log(JSON.stringify({ error: error.message }));
@@ -487,7 +431,7 @@ colony.command("memory").description("Read the Colony's shared memory").action(a
487
431
  });
488
432
  colony.command("plans").description("Get all active Colony plans").action(async () => {
489
433
  try {
490
- const { getActivePlans } = await import("./colony-LCWN5IAN.js");
434
+ const { getActivePlans } = await import("./colony-JPZC3R34.js");
491
435
  const plans = getActivePlans();
492
436
  console.log(plans.length > 0 ? JSON.stringify(plans, null, 2) : JSON.stringify({ message: "No active plans. Propose one!" }));
493
437
  } catch (error) {
@@ -497,7 +441,7 @@ colony.command("plans").description("Get all active Colony plans").action(async
497
441
  });
498
442
  colony.command("propose").description("Propose a coordinated plan").argument("<description>", "What's the plan?").action(async (description) => {
499
443
  try {
500
- const { proposePlan } = await import("./colony-LCWN5IAN.js");
444
+ const { proposePlan } = await import("./colony-JPZC3R34.js");
501
445
  const result = await proposePlan(description);
502
446
  console.log(JSON.stringify(result, null, 2));
503
447
  } catch (error) {
@@ -507,7 +451,7 @@ colony.command("propose").description("Propose a coordinated plan").argument("<d
507
451
  });
508
452
  colony.command("join").description("Join an active plan").argument("<planId>", "Plan ID").action(async (planId) => {
509
453
  try {
510
- const { joinPlan } = await import("./colony-LCWN5IAN.js");
454
+ const { joinPlan } = await import("./colony-JPZC3R34.js");
511
455
  const result = await joinPlan(planId);
512
456
  console.log(JSON.stringify(result, null, 2));
513
457
  } catch (error) {
@@ -517,7 +461,7 @@ colony.command("join").description("Join an active plan").argument("<planId>", "
517
461
  });
518
462
  colony.command("post-status").description("Post a status update to the Colony").argument("<status>", "Your status").action(async (status) => {
519
463
  try {
520
- const { postStatus } = await import("./colony-LCWN5IAN.js");
464
+ const { postStatus } = await import("./colony-JPZC3R34.js");
521
465
  const result = await postStatus(status);
522
466
  console.log(JSON.stringify(result, null, 2));
523
467
  } catch (error) {
@@ -527,7 +471,7 @@ colony.command("post-status").description("Post a status update to the Colony").
527
471
  });
528
472
  colony.command("activity").description("Get today's Colony activity").action(async () => {
529
473
  try {
530
- const { getTodaysActivity } = await import("./colony-LCWN5IAN.js");
474
+ const { getTodaysActivity } = await import("./colony-JPZC3R34.js");
531
475
  const activity = getTodaysActivity();
532
476
  console.log(activity.length > 0 ? JSON.stringify(activity, null, 2) : JSON.stringify({ message: "No Colony activity today yet." }));
533
477
  } catch (error) {
@@ -544,24 +488,24 @@ program.command("start").description("Start the autonomous Spora agent").option(
544
488
  console.log(JSON.stringify({ error: "No X credentials. Run `spora init` to set up." }));
545
489
  process.exit(1);
546
490
  }
547
- const { hasLLMKey } = await import("./llm-3LSNADSR.js");
491
+ const { hasLLMKey } = await import("./llm-T33QTPVW.js");
548
492
  if (!hasLLMKey()) {
549
- console.log(JSON.stringify({ error: "No LLM API key. Run `spora set-llm-key` first." }));
493
+ console.log(JSON.stringify({ error: "No LLM API key. Run `spora llm set --provider <provider>` first." }));
550
494
  process.exit(1);
551
495
  }
552
496
  if (opts.interval) {
553
- const { loadConfig: lc, saveConfig: sc } = await import("./config-TFAFYSIW.js");
497
+ const { loadConfig: lc, saveConfig: sc } = await import("./config-FL4VJVKZ.js");
554
498
  const config = lc();
555
- config.runtime = { ...config.runtime, heartbeatIntervalMs: parseInt(opts.interval, 10), actionsPerHeartbeat: config.runtime?.actionsPerHeartbeat ?? 3, enabled: true };
499
+ config.runtime = { ...config.runtime, heartbeatIntervalMs: parseInt(opts.interval, 10), actionsPerHeartbeat: config.runtime?.actionsPerHeartbeat ?? 4, enabled: true };
556
500
  sc(config);
557
501
  }
558
502
  console.log(chalk.cyan(BANNER));
559
503
  console.log(chalk.bold("Starting Spora agent...\n"));
560
- const { startHeartbeatLoop } = await import("./heartbeat-ZHRCEMF5.js");
504
+ const { startHeartbeatLoop } = await import("./heartbeat-TNEPE3ZP.js");
561
505
  await startHeartbeatLoop();
562
506
  });
563
507
  program.command("stop").description("Stop the running Spora agent").action(async () => {
564
- const { getRunningPid, requestStop } = await import("./heartbeat-ZHRCEMF5.js");
508
+ const { getRunningPid, requestStop } = await import("./heartbeat-TNEPE3ZP.js");
565
509
  const pid = getRunningPid();
566
510
  if (!pid) {
567
511
  console.log(JSON.stringify({ message: "Spora agent is not running." }));
@@ -570,37 +514,82 @@ program.command("stop").description("Stop the running Spora agent").action(async
570
514
  requestStop();
571
515
  console.log(JSON.stringify({ message: `Stop signal sent to PID ${pid}.` }));
572
516
  });
573
- program.command("set-llm-key").description("Set your DeepSeek API key for the agent runtime").argument("[key]", "API key (or omit to enter interactively)").action(async (key) => {
574
- const { writeFileSync } = await import("fs");
575
- const { paths: p, ensureDirectories: ed } = await import("./paths-5GFUUHCZ.js");
517
+ program.command("set-llm-key").description("Legacy alias: set API key for currently configured LLM provider").argument("[key]", "API key (or omit to enter interactively)").action(async (key) => {
518
+ const { ensureDirectories: ed } = await import("./paths-BYR6MEPR.js");
519
+ const { input } = await import("@inquirer/prompts");
520
+ const { loadConfig: lc } = await import("./config-FL4VJVKZ.js");
521
+ const { setLLMApiKey, getDefaultModel } = await import("./llm-T33QTPVW.js");
576
522
  ed();
577
- let apiKey = key;
578
- if (!apiKey) {
579
- if (process.env.DEEPSEEK_API_KEY) {
580
- console.log(JSON.stringify({ message: "Using DEEPSEEK_API_KEY from environment." }));
581
- return;
582
- }
583
- const { input } = await import("@inquirer/prompts");
584
- apiKey = await input({
585
- message: "Enter your DeepSeek API key:"
586
- });
523
+ let provider = "deepseek";
524
+ let model = getDefaultModel("deepseek");
525
+ try {
526
+ const config = lc();
527
+ provider = config.llm?.provider ?? "deepseek";
528
+ model = config.llm?.model ?? getDefaultModel(provider);
529
+ } catch {
587
530
  }
588
- writeFileSync(p.llmKey, apiKey, { mode: 384 });
531
+ const apiKey = key ?? await input({ message: `Enter your ${provider} API key:` });
532
+ setLLMApiKey(provider, apiKey.trim());
533
+ console.log(JSON.stringify({ success: true, provider, model, message: "LLM API key saved." }));
534
+ });
535
+ var llm = program.command("llm").description("LLM provider/model settings");
536
+ llm.command("status").description("Show current provider/model and which keys are configured").action(async () => {
537
+ const { loadConfig: lc } = await import("./config-FL4VJVKZ.js");
538
+ const { listLLMKeyStatus, getDefaultModel } = await import("./llm-T33QTPVW.js");
539
+ let provider = "deepseek";
540
+ let model = getDefaultModel("deepseek");
589
541
  try {
590
- const { loadConfig: lc, saveConfig: sc } = await import("./config-TFAFYSIW.js");
591
542
  const config = lc();
592
- if (!config.llm) {
593
- config.llm = { provider: "deepseek", model: "deepseek-chat" };
594
- sc(config);
595
- }
543
+ provider = config.llm?.provider ?? "deepseek";
544
+ model = config.llm?.model ?? getDefaultModel(provider);
596
545
  } catch {
597
546
  }
598
- console.log(JSON.stringify({ success: true, message: "LLM API key saved." }));
547
+ console.log(JSON.stringify({
548
+ provider,
549
+ model,
550
+ keysConfigured: listLLMKeyStatus()
551
+ }, null, 2));
552
+ });
553
+ llm.command("set").description("Set provider/model and store API key").requiredOption("--provider <provider>", "anthropic | openai | deepseek").option("--model <model>", "Model name (defaults by provider)").option("--key <key>", "API key").action(async (opts) => {
554
+ const provider = opts.provider;
555
+ if (!["anthropic", "openai", "deepseek"].includes(provider)) {
556
+ console.log(JSON.stringify({ error: "Provider must be anthropic, openai, or deepseek" }));
557
+ process.exit(1);
558
+ }
559
+ const { input } = await import("@inquirer/prompts");
560
+ const { loadConfig: lc, saveConfig: sc } = await import("./config-FL4VJVKZ.js");
561
+ const { setLLMApiKey, getDefaultModel } = await import("./llm-T33QTPVW.js");
562
+ const { ensureDirectories: ed } = await import("./paths-BYR6MEPR.js");
563
+ ed();
564
+ const model = opts.model ?? getDefaultModel(provider);
565
+ const apiKey = (opts.key ?? await input({ message: `Enter your ${provider} API key:` })).trim();
566
+ if (!apiKey) {
567
+ console.log(JSON.stringify({ error: "API key is required" }));
568
+ process.exit(1);
569
+ }
570
+ setLLMApiKey(provider, apiKey);
571
+ const config = lc();
572
+ config.llm = { provider, model };
573
+ sc(config);
574
+ console.log(JSON.stringify({ success: true, provider, model }));
575
+ });
576
+ llm.command("test").description("Send a tiny test prompt to validate current LLM config").action(async () => {
577
+ try {
578
+ const { chat } = await import("./llm-T33QTPVW.js");
579
+ const response = await chat(
580
+ "You are a short diagnostic assistant. Reply with exactly: ok",
581
+ [{ role: "user", content: "health check" }]
582
+ );
583
+ console.log(JSON.stringify({ success: true, response: response.content.trim() }));
584
+ } catch (error) {
585
+ console.log(JSON.stringify({ success: false, error: error.message }));
586
+ process.exit(1);
587
+ }
599
588
  });
600
589
  program.command("agent-status").description("Check if the Spora agent is running").action(async () => {
601
- const { getRunningPid } = await import("./heartbeat-ZHRCEMF5.js");
590
+ const { getRunningPid } = await import("./heartbeat-TNEPE3ZP.js");
602
591
  const pid = getRunningPid();
603
- const { hasLLMKey } = await import("./llm-3LSNADSR.js");
592
+ const { hasLLMKey } = await import("./llm-T33QTPVW.js");
604
593
  console.log(JSON.stringify({
605
594
  agentRunning: pid !== null,
606
595
  pid,
@@ -609,6 +598,52 @@ program.command("agent-status").description("Check if the Spora agent is running
609
598
  hasCredentials: hasXCredentials()
610
599
  }));
611
600
  });
601
+ program.command("agent-metrics").description("Show recent heartbeat metrics for autonomy quality").option("-n, --count <n>", "Number of entries", "20").action(async (opts) => {
602
+ const { existsSync, readFileSync: readFileSync2 } = await import("fs");
603
+ const { paths } = await import("./paths-BYR6MEPR.js");
604
+ const count = Math.max(1, parseInt(opts.count, 10) || 20);
605
+ if (!existsSync(paths.runtimeMetrics)) {
606
+ console.log(JSON.stringify({ message: "No metrics recorded yet." }));
607
+ return;
608
+ }
609
+ const lines = readFileSync2(paths.runtimeMetrics, "utf-8").split("\n").filter(Boolean).slice(-count);
610
+ const entries = lines.map((line) => JSON.parse(line));
611
+ console.log(JSON.stringify(entries, null, 2));
612
+ });
613
+ program.command("doctor").description("Run diagnostics for X API, LLM provider, and local config").action(async () => {
614
+ const checks = [];
615
+ try {
616
+ const config = loadConfig();
617
+ checks.push({ check: "config", ok: true, detail: `provider=${config.llm?.provider ?? "deepseek"}, model=${config.llm?.model ?? "default"}` });
618
+ } catch (error) {
619
+ checks.push({ check: "config", ok: false, detail: error.message });
620
+ }
621
+ try {
622
+ const { hasLLMKey, chat } = await import("./llm-T33QTPVW.js");
623
+ if (!hasLLMKey()) {
624
+ checks.push({ check: "llm_key", ok: false, detail: "No key configured for current provider" });
625
+ } else {
626
+ const resp = await chat(
627
+ "Reply with exactly 'ok'.",
628
+ [{ role: "user", content: "health check" }]
629
+ );
630
+ checks.push({ check: "llm_call", ok: resp.content.toLowerCase().includes("ok"), detail: `response=${resp.content.trim().slice(0, 32)}` });
631
+ }
632
+ } catch (error) {
633
+ checks.push({ check: "llm_call", ok: false, detail: error.message });
634
+ }
635
+ try {
636
+ const { getXClient } = await import("./x-client-GY6XSPK6.js");
637
+ const client = await getXClient();
638
+ const timeline = await client.getTimeline({ count: 3 });
639
+ checks.push({ check: "x_api_timeline", ok: true, detail: `timeline_count=${timeline.length}` });
640
+ } catch (error) {
641
+ checks.push({ check: "x_api_timeline", ok: false, detail: error.message });
642
+ }
643
+ const allOk = checks.every((c) => c.ok);
644
+ console.log(JSON.stringify({ ok: allOk, checks }, null, 2));
645
+ if (!allOk) process.exit(1);
646
+ });
612
647
  program.command("ui").description("Open the Spora web UI for setup and management").option("-p, --port <port>", "Port to run on", "3000").action(async (opts) => {
613
648
  const { resolve } = await import("path");
614
649
  const { existsSync: fsExists } = await import("fs");