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.
- package/README.md +7 -5
- package/dist/autonomy-DAV7X6QS.js +19 -0
- package/dist/{chunk-53YLFYJF.js → chunk-3RYCUGXE.js} +6 -2
- package/dist/chunk-3RYCUGXE.js.map +1 -0
- package/dist/{chunk-AH7HPXYC.js → chunk-AOQ3WLZV.js} +153 -143
- package/dist/chunk-AOQ3WLZV.js.map +1 -0
- package/dist/chunk-E5NR6HT4.js +29 -0
- package/dist/chunk-E5NR6HT4.js.map +1 -0
- package/dist/{chunk-EBO4F5NU.js → chunk-JBYZ7K56.js} +2 -2
- package/dist/chunk-KWWAIS3C.js +180 -0
- package/dist/chunk-KWWAIS3C.js.map +1 -0
- package/dist/{chunk-UINSD4FT.js → chunk-LXQNVVIY.js} +6 -6
- package/dist/{chunk-UINSD4FT.js.map → chunk-LXQNVVIY.js.map} +1 -1
- package/dist/{chunk-AIEXQCQS.js → chunk-M6YOQVSI.js} +2 -2
- package/dist/{chunk-B6RPMDML.js → chunk-NO3NQN67.js} +16 -6
- package/dist/chunk-NO3NQN67.js.map +1 -0
- package/dist/{chunk-QOKQ5OTU.js → chunk-NPV3OV2K.js} +3 -14
- package/dist/chunk-NPV3OV2K.js.map +1 -0
- package/dist/{chunk-SBQILQCJ.js → chunk-OACD3HGE.js} +7 -7
- package/dist/{chunk-UM57WU5I.js → chunk-P6KZIJYL.js} +2 -2
- package/dist/{chunk-AHXZIGQE.js → chunk-T7L2L7ZL.js} +2 -2
- package/dist/{chunk-ZJZKH7N7.js → chunk-VZBHRUZS.js} +2 -2
- package/dist/chunk-VZBHRUZS.js.map +1 -0
- package/dist/chunk-WIK74GGJ.js +295 -0
- package/dist/chunk-WIK74GGJ.js.map +1 -0
- package/dist/{chunk-YLJVFCT4.js → chunk-WN35MRMF.js} +2 -2
- package/dist/cli.js +173 -138
- package/dist/cli.js.map +1 -1
- package/dist/client-57BQKVYF.js +337 -0
- package/dist/client-57BQKVYF.js.map +1 -0
- package/dist/{colony-LCWN5IAN.js → colony-JPZC3R34.js} +7 -7
- package/dist/{config-TFAFYSIW.js → config-FL4VJVKZ.js} +3 -3
- package/dist/{crypto-FHSQ72NU.js → crypto-NOXNL4GP.js} +3 -3
- package/dist/{goals-5TAPXNR2.js → goals-RBKLMILE.js} +3 -3
- package/dist/{heartbeat-ZHRCEMF5.js → heartbeat-TNEPE3ZP.js} +83 -88
- package/dist/heartbeat-TNEPE3ZP.js.map +1 -0
- package/dist/{identity-O4FLSZKZ.js → identity-VDUW4I2K.js} +3 -3
- package/dist/{init-G3WINLAP.js → init-ISSXETHY.js} +59 -46
- package/dist/init-ISSXETHY.js.map +1 -0
- package/dist/llm-T33QTPVW.js +22 -0
- package/dist/mcp-server.js +28 -28
- package/dist/mcp-server.js.map +1 -1
- package/dist/{memory-O3AJIKBX.js → memory-OIAH33G2.js} +3 -3
- package/dist/{memory-7FBE26K3.js → memory-PNW7SX7A.js} +3 -3
- package/dist/{paths-5GFUUHCZ.js → paths-BYR6MEPR.js} +2 -2
- package/dist/prompt-builder-5NYONN2W.js +23 -0
- package/dist/queue-G5PTE6R6.js +14 -0
- package/dist/{strategy-S45TX766.js → strategy-Z4JSFHSP.js} +3 -3
- package/dist/{web-chat-RQIILEQK.js → web-chat-3HM35XM4.js} +31 -80
- package/dist/web-chat-3HM35XM4.js.map +1 -0
- package/dist/x-client-GY6XSPK6.js +12 -0
- package/package.json +1 -1
- package/dist/account-creator-ZD643X3Z.js +0 -498
- package/dist/account-creator-ZD643X3Z.js.map +0 -1
- package/dist/chunk-535NMUUW.js +0 -96
- package/dist/chunk-535NMUUW.js.map +0 -1
- package/dist/chunk-53YLFYJF.js.map +0 -1
- package/dist/chunk-55XPDJ6P.js +0 -124
- package/dist/chunk-55XPDJ6P.js.map +0 -1
- package/dist/chunk-AH7HPXYC.js.map +0 -1
- package/dist/chunk-B6RPMDML.js.map +0 -1
- package/dist/chunk-E6GMS76S.js +0 -154
- package/dist/chunk-E6GMS76S.js.map +0 -1
- package/dist/chunk-JJZ7T2IZ.js +0 -32
- package/dist/chunk-JJZ7T2IZ.js.map +0 -1
- package/dist/chunk-QOKQ5OTU.js.map +0 -1
- package/dist/chunk-TF2XYGGG.js +0 -249
- package/dist/chunk-TF2XYGGG.js.map +0 -1
- package/dist/chunk-ZJZKH7N7.js.map +0 -1
- package/dist/client-B6NGVRHM.js +0 -381
- package/dist/client-B6NGVRHM.js.map +0 -1
- package/dist/client-DDCS5FJS.js +0 -412
- package/dist/client-DDCS5FJS.js.map +0 -1
- package/dist/decision-engine-DRPIZLHI.js +0 -19
- package/dist/heartbeat-ZHRCEMF5.js.map +0 -1
- package/dist/init-G3WINLAP.js.map +0 -1
- package/dist/llm-3LSNADSR.js +0 -16
- package/dist/prompt-builder-U2J4H7YX.js +0 -24
- package/dist/queue-USY7JXDV.js +0 -14
- package/dist/research-TQLP42BC.js +0 -13
- package/dist/web-chat-RQIILEQK.js.map +0 -1
- package/dist/x-client-TYU5QSLG.js +0 -12
- package/dist/x-client-TYU5QSLG.js.map +0 -1
- /package/dist/{config-TFAFYSIW.js.map → autonomy-DAV7X6QS.js.map} +0 -0
- /package/dist/{chunk-EBO4F5NU.js.map → chunk-JBYZ7K56.js.map} +0 -0
- /package/dist/{chunk-AIEXQCQS.js.map → chunk-M6YOQVSI.js.map} +0 -0
- /package/dist/{chunk-SBQILQCJ.js.map → chunk-OACD3HGE.js.map} +0 -0
- /package/dist/{chunk-UM57WU5I.js.map → chunk-P6KZIJYL.js.map} +0 -0
- /package/dist/{chunk-AHXZIGQE.js.map → chunk-T7L2L7ZL.js.map} +0 -0
- /package/dist/{chunk-YLJVFCT4.js.map → chunk-WN35MRMF.js.map} +0 -0
- /package/dist/{colony-LCWN5IAN.js.map → colony-JPZC3R34.js.map} +0 -0
- /package/dist/{crypto-FHSQ72NU.js.map → config-FL4VJVKZ.js.map} +0 -0
- /package/dist/{decision-engine-DRPIZLHI.js.map → crypto-NOXNL4GP.js.map} +0 -0
- /package/dist/{goals-5TAPXNR2.js.map → goals-RBKLMILE.js.map} +0 -0
- /package/dist/{identity-O4FLSZKZ.js.map → identity-VDUW4I2K.js.map} +0 -0
- /package/dist/{llm-3LSNADSR.js.map → llm-T33QTPVW.js.map} +0 -0
- /package/dist/{memory-7FBE26K3.js.map → memory-OIAH33G2.js.map} +0 -0
- /package/dist/{memory-O3AJIKBX.js.map → memory-PNW7SX7A.js.map} +0 -0
- /package/dist/{paths-5GFUUHCZ.js.map → paths-BYR6MEPR.js.map} +0 -0
- /package/dist/{prompt-builder-U2J4H7YX.js.map → prompt-builder-5NYONN2W.js.map} +0 -0
- /package/dist/{queue-USY7JXDV.js.map → queue-G5PTE6R6.js.map} +0 -0
- /package/dist/{research-TQLP42BC.js.map → strategy-Z4JSFHSP.js.map} +0 -0
- /package/dist/{strategy-S45TX766.js.map → x-client-GY6XSPK6.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/x-client/api/client.ts"],"sourcesContent":["import { TwitterApi } from \"twitter-api-v2\";\nimport { loadCredentials } from \"../../utils/crypto.js\";\nimport { logger } from \"../../utils/logger.js\";\nimport { logInteraction } from \"../../memory/index.js\";\nimport { rateLimiter } from \"../rate-limiter.js\";\nimport type {\n XClientInterface,\n Tweet,\n UserProfile,\n PostResult,\n TimelineOptions,\n SearchOptions,\n} from \"../types.js\";\n\ninterface TwitterResponseMeta {\n next_token?: string;\n}\n\ninterface TwitterUser {\n id: string;\n username: string;\n name?: string;\n description?: string;\n verified?: boolean;\n profile_image_url?: string;\n public_metrics?: {\n followers_count?: number;\n following_count?: number;\n tweet_count?: number;\n };\n}\n\ninterface TwitterTweet {\n id: string;\n text: string;\n author_id?: string;\n created_at?: string;\n in_reply_to_user_id?: string;\n public_metrics?: {\n like_count?: number;\n retweet_count?: number;\n reply_count?: number;\n };\n}\n\ninterface TwitterTimelineResponse {\n data?: TwitterTweet[];\n includes?: {\n users?: TwitterUser[];\n };\n meta?: TwitterResponseMeta;\n}\n\nexport class XApiClient implements XClientInterface {\n private readonly readWrite: TwitterApi;\n private readonly readOnly: TwitterApi;\n private meId: string | null = null;\n\n constructor() {\n const creds = loadCredentials();\n if (creds.method !== \"api\") {\n throw new Error(\"Only API credentials are supported.\");\n }\n\n if (!creds.apiKey || !creds.apiSecret || !creds.accessToken || !creds.accessTokenSecret) {\n throw new Error(\"Missing X OAuth credentials. Run `spora init` and provide API keys.\");\n }\n\n this.readWrite = new TwitterApi({\n appKey: creds.apiKey,\n appSecret: creds.apiSecret,\n accessToken: creds.accessToken,\n accessSecret: creds.accessTokenSecret,\n });\n\n this.readOnly = creds.bearerToken\n ? new TwitterApi(creds.bearerToken)\n : this.readWrite;\n }\n\n private toTweet(tweet: TwitterTweet, userMap: Map<string, string>): Tweet {\n const authorId = tweet.author_id ?? \"unknown\";\n return {\n id: tweet.id,\n text: tweet.text,\n authorId,\n authorHandle: userMap.get(authorId) ?? \"unknown\",\n createdAt: tweet.created_at ?? new Date().toISOString(),\n likeCount: tweet.public_metrics?.like_count,\n retweetCount: tweet.public_metrics?.retweet_count,\n replyCount: tweet.public_metrics?.reply_count,\n inReplyToId: tweet.in_reply_to_user_id,\n };\n }\n\n private async getAuthenticatedUserId(): Promise<string> {\n if (this.meId) return this.meId;\n\n const me = (await this.readWrite.v2.me({\n \"user.fields\": [\"id\"],\n })) as { data?: { id: string } };\n\n if (!me.data?.id) {\n throw new Error(\"Unable to resolve authenticated X user ID.\");\n }\n\n this.meId = me.data.id;\n return this.meId;\n }\n\n private normalizeHandleOrId(input: string): { isId: boolean; value: string } {\n const cleaned = input.trim().replace(/^@/, \"\");\n const isId = /^\\d+$/.test(cleaned);\n return { isId, value: cleaned };\n }\n\n private async resolveUserId(handleOrId: string): Promise<string> {\n const parsed = this.normalizeHandleOrId(handleOrId);\n if (parsed.isId) return parsed.value;\n\n const user = (await this.readOnly.v2.userByUsername(parsed.value, {\n \"user.fields\": [\"id\", \"username\"],\n })) as { data?: { id: string } };\n\n if (!user.data?.id) {\n throw new Error(`Could not resolve @${parsed.value} to a user ID`);\n }\n\n return user.data.id;\n }\n\n private buildUserMap(users: TwitterUser[] | undefined): Map<string, string> {\n const map = new Map<string, string>();\n for (const user of users ?? []) {\n map.set(user.id, user.username);\n }\n return map;\n }\n\n async postTweet(content: string): Promise<PostResult> {\n if (!rateLimiter.canPost()) {\n return { success: false, error: \"Monthly post limit reached\" };\n }\n\n try {\n const response = (await this.readWrite.v2.tweet(content)) as { data?: { id?: string } };\n const tweetId = response.data?.id;\n\n if (!tweetId) {\n return { success: false, error: \"X API did not return a tweet ID.\" };\n }\n\n rateLimiter.consume(1);\n logInteraction({\n id: `int-${Date.now()}`,\n timestamp: new Date().toISOString(),\n type: \"post\",\n tweetId,\n content,\n creditsUsed: 1,\n success: true,\n });\n\n return { success: true, tweetId };\n } catch (error) {\n logger.error(\"Failed to post tweet\", error);\n return { success: false, error: (error as Error).message };\n }\n }\n\n async replyToTweet(tweetId: string, content: string): Promise<PostResult> {\n if (!rateLimiter.canPost()) {\n return { success: false, error: \"Monthly post limit reached\" };\n }\n\n try {\n const response = (await this.readWrite.v2.reply(content, tweetId)) as {\n data?: { id?: string };\n };\n const createdId = response.data?.id;\n\n if (!createdId) {\n return { success: false, error: \"X API did not return a reply ID.\" };\n }\n\n rateLimiter.consume(1);\n logInteraction({\n id: `int-${Date.now()}`,\n timestamp: new Date().toISOString(),\n type: \"reply\",\n tweetId: createdId,\n inReplyTo: tweetId,\n content,\n creditsUsed: 1,\n success: true,\n });\n\n return { success: true, tweetId: createdId };\n } catch (error) {\n logger.error(\"Failed to reply\", error);\n return { success: false, error: (error as Error).message };\n }\n }\n\n async deleteTweet(tweetId: string): Promise<PostResult> {\n try {\n await this.readWrite.v2.deleteTweet(tweetId);\n return { success: true, tweetId };\n } catch (error) {\n return { success: false, error: (error as Error).message };\n }\n }\n\n async likeTweet(tweetId: string): Promise<PostResult> {\n rateLimiter.requireBasicTier(\"Like\");\n try {\n const meId = await this.getAuthenticatedUserId();\n await this.readWrite.v2.like(meId, tweetId);\n\n logInteraction({\n id: `int-${Date.now()}`,\n timestamp: new Date().toISOString(),\n type: \"like\",\n tweetId,\n creditsUsed: 0,\n success: true,\n });\n\n return { success: true, tweetId };\n } catch (error) {\n return { success: false, error: (error as Error).message };\n }\n }\n\n async unlikeTweet(tweetId: string): Promise<PostResult> {\n rateLimiter.requireBasicTier(\"Unlike\");\n try {\n const meId = await this.getAuthenticatedUserId();\n await this.readWrite.v2.unlike(meId, tweetId);\n return { success: true, tweetId };\n } catch (error) {\n return { success: false, error: (error as Error).message };\n }\n }\n\n async retweet(tweetId: string): Promise<PostResult> {\n rateLimiter.requireBasicTier(\"Retweet\");\n try {\n const meId = await this.getAuthenticatedUserId();\n await this.readWrite.v2.retweet(meId, tweetId);\n\n logInteraction({\n id: `int-${Date.now()}`,\n timestamp: new Date().toISOString(),\n type: \"retweet\",\n tweetId,\n creditsUsed: 0,\n success: true,\n });\n\n return { success: true, tweetId };\n } catch (error) {\n return { success: false, error: (error as Error).message };\n }\n }\n\n async unretweet(tweetId: string): Promise<PostResult> {\n rateLimiter.requireBasicTier(\"Unretweet\");\n try {\n const meId = await this.getAuthenticatedUserId();\n await this.readWrite.v2.unretweet(meId, tweetId);\n return { success: true, tweetId };\n } catch (error) {\n return { success: false, error: (error as Error).message };\n }\n }\n\n async followUser(handleOrId: string): Promise<PostResult> {\n rateLimiter.requireBasicTier(\"Follow\");\n try {\n const meId = await this.getAuthenticatedUserId();\n const targetId = await this.resolveUserId(handleOrId);\n await this.readWrite.v2.follow(meId, targetId);\n\n logInteraction({\n id: `int-${Date.now()}`,\n timestamp: new Date().toISOString(),\n type: \"follow\",\n targetUserId: targetId,\n targetHandle: handleOrId.replace(/^@/, \"\"),\n creditsUsed: 0,\n success: true,\n });\n\n return { success: true };\n } catch (error) {\n return { success: false, error: (error as Error).message };\n }\n }\n\n async unfollowUser(handleOrId: string): Promise<PostResult> {\n rateLimiter.requireBasicTier(\"Unfollow\");\n try {\n const meId = await this.getAuthenticatedUserId();\n const targetId = await this.resolveUserId(handleOrId);\n await this.readWrite.v2.unfollow(meId, targetId);\n return { success: true };\n } catch (error) {\n return { success: false, error: (error as Error).message };\n }\n }\n\n async getTimeline(options?: TimelineOptions): Promise<Tweet[]> {\n rateLimiter.requireBasicTier(\"Read timeline\");\n try {\n const meId = await this.getAuthenticatedUserId();\n\n const response = (await this.readOnly.v2.get(\n `users/${meId}/timelines/reverse_chronological`,\n {\n max_results: options?.count ?? 20,\n since_id: options?.sinceId,\n expansions: [\"author_id\"],\n \"tweet.fields\": [\n \"created_at\",\n \"public_metrics\",\n \"in_reply_to_user_id\",\n \"author_id\",\n ],\n \"user.fields\": [\"username\"],\n }\n )) as TwitterTimelineResponse;\n\n if (!response.data?.length) return [];\n\n const users = this.buildUserMap(response.includes?.users);\n return response.data.map((tweet) => this.toTweet(tweet, users));\n } catch (error) {\n logger.error(\"Failed to read timeline\", error);\n return [];\n }\n }\n\n async getMentions(options?: TimelineOptions): Promise<Tweet[]> {\n rateLimiter.requireBasicTier(\"Read mentions\");\n try {\n const meId = await this.getAuthenticatedUserId();\n const response = (await this.readOnly.v2.get(`users/${meId}/mentions`, {\n max_results: options?.count ?? 20,\n since_id: options?.sinceId,\n expansions: [\"author_id\"],\n \"tweet.fields\": [\"created_at\", \"public_metrics\", \"author_id\"],\n \"user.fields\": [\"username\"],\n })) as TwitterTimelineResponse;\n\n if (!response.data?.length) return [];\n\n const users = this.buildUserMap(response.includes?.users);\n return response.data.map((tweet) => this.toTweet(tweet, users));\n } catch (error) {\n logger.error(\"Failed to read mentions\", error);\n return [];\n }\n }\n\n async searchTweets(query: string, options?: SearchOptions): Promise<Tweet[]> {\n rateLimiter.requireBasicTier(\"Search tweets\");\n try {\n const paginator = await this.readOnly.v2.search(query, {\n max_results: Math.min(options?.count ?? 20, 100),\n expansions: [\"author_id\"],\n \"tweet.fields\": [\"created_at\", \"public_metrics\", \"author_id\"],\n \"user.fields\": [\"username\"],\n });\n\n const tweets: TwitterTweet[] = [];\n const users = new Map<string, string>();\n\n for await (const tweet of paginator) {\n tweets.push(tweet as unknown as TwitterTweet);\n if (tweets.length >= (options?.count ?? 20)) break;\n }\n\n const includeUsers = (paginator as unknown as { includes?: { users?: TwitterUser[] } }).includes?.users;\n for (const user of includeUsers ?? []) {\n users.set(user.id, user.username);\n }\n\n return tweets.map((tweet) => this.toTweet(tweet, users));\n } catch (error) {\n logger.error(\"Failed to search tweets\", error);\n return [];\n }\n }\n\n async getProfile(handle: string): Promise<UserProfile> {\n rateLimiter.requireBasicTier(\"Get profile\");\n\n const cleanedHandle = handle.trim().replace(/^@/, \"\");\n const response = (await this.readOnly.v2.userByUsername(cleanedHandle, {\n \"user.fields\": [\n \"description\",\n \"public_metrics\",\n \"verified\",\n \"profile_image_url\",\n \"username\",\n \"name\",\n ],\n })) as { data?: TwitterUser };\n\n if (!response.data) {\n throw new Error(`Profile not found for @${cleanedHandle}`);\n }\n\n return {\n id: response.data.id,\n handle: response.data.username,\n name: response.data.name ?? response.data.username,\n bio: response.data.description ?? \"\",\n followersCount: response.data.public_metrics?.followers_count ?? 0,\n followingCount: response.data.public_metrics?.following_count ?? 0,\n tweetCount: response.data.public_metrics?.tweet_count ?? 0,\n verified: response.data.verified ?? false,\n profileImageUrl: response.data.profile_image_url,\n };\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -7,18 +7,18 @@ import {
|
|
|
7
7
|
loadColonyMemory,
|
|
8
8
|
renderColonyBriefing,
|
|
9
9
|
saveColonyMemory
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-T7L2L7ZL.js";
|
|
11
11
|
import {
|
|
12
12
|
getXClient
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-B6RPMDML.js";
|
|
13
|
+
} from "./chunk-E5NR6HT4.js";
|
|
15
14
|
import {
|
|
16
15
|
loadIdentity
|
|
17
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-M6YOQVSI.js";
|
|
18
17
|
import {
|
|
19
18
|
logger
|
|
20
|
-
} from "./chunk-
|
|
21
|
-
import "./chunk-
|
|
19
|
+
} from "./chunk-NPV3OV2K.js";
|
|
20
|
+
import "./chunk-NO3NQN67.js";
|
|
21
|
+
import "./chunk-3RYCUGXE.js";
|
|
22
22
|
|
|
23
23
|
// src/colony/index.ts
|
|
24
24
|
var COLONY_TAG = "#SporaColony";
|
|
@@ -226,4 +226,4 @@ export {
|
|
|
226
226
|
postStatus,
|
|
227
227
|
proposePlan
|
|
228
228
|
};
|
|
229
|
-
//# sourceMappingURL=colony-
|
|
229
|
+
//# sourceMappingURL=colony-JPZC3R34.js.map
|
|
@@ -3,12 +3,12 @@ import {
|
|
|
3
3
|
createDefaultConfig,
|
|
4
4
|
loadConfig,
|
|
5
5
|
saveConfig
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-NO3NQN67.js";
|
|
7
|
+
import "./chunk-3RYCUGXE.js";
|
|
8
8
|
export {
|
|
9
9
|
ConfigSchema,
|
|
10
10
|
createDefaultConfig,
|
|
11
11
|
loadConfig,
|
|
12
12
|
saveConfig
|
|
13
13
|
};
|
|
14
|
-
//# sourceMappingURL=config-
|
|
14
|
+
//# sourceMappingURL=config-FL4VJVKZ.js.map
|
|
@@ -3,12 +3,12 @@ import {
|
|
|
3
3
|
encrypt,
|
|
4
4
|
loadCredentials,
|
|
5
5
|
saveCredentials
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-VZBHRUZS.js";
|
|
7
|
+
import "./chunk-3RYCUGXE.js";
|
|
8
8
|
export {
|
|
9
9
|
decrypt,
|
|
10
10
|
encrypt,
|
|
11
11
|
loadCredentials,
|
|
12
12
|
saveCredentials
|
|
13
13
|
};
|
|
14
|
-
//# sourceMappingURL=crypto-
|
|
14
|
+
//# sourceMappingURL=crypto-NOXNL4GP.js.map
|
|
@@ -2,11 +2,11 @@ import {
|
|
|
2
2
|
loadGoals,
|
|
3
3
|
renderGoalsForPrompt,
|
|
4
4
|
saveGoals
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-WN35MRMF.js";
|
|
6
|
+
import "./chunk-3RYCUGXE.js";
|
|
7
7
|
export {
|
|
8
8
|
loadGoals,
|
|
9
9
|
renderGoalsForPrompt,
|
|
10
10
|
saveGoals
|
|
11
11
|
};
|
|
12
|
-
//# sourceMappingURL=goals-
|
|
12
|
+
//# sourceMappingURL=goals-RBKLMILE.js.map
|
|
@@ -1,49 +1,75 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
runResearchPhase
|
|
7
|
-
} from "./chunk-E6GMS76S.js";
|
|
8
|
-
import {
|
|
9
|
-
getXClient
|
|
10
|
-
} from "./chunk-JJZ7T2IZ.js";
|
|
2
|
+
runAutonomyCycle
|
|
3
|
+
} from "./chunk-WIK74GGJ.js";
|
|
4
|
+
import "./chunk-E5NR6HT4.js";
|
|
11
5
|
import {
|
|
12
6
|
flushQueue
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
import "./chunk-
|
|
20
|
-
import {
|
|
21
|
-
loadStrategy,
|
|
22
|
-
saveStrategy
|
|
23
|
-
} from "./chunk-UM57WU5I.js";
|
|
24
|
-
import "./chunk-YLJVFCT4.js";
|
|
25
|
-
import "./chunk-UINSD4FT.js";
|
|
26
|
-
import {
|
|
27
|
-
generateResponse
|
|
28
|
-
} from "./chunk-55XPDJ6P.js";
|
|
29
|
-
import {
|
|
30
|
-
loadConfig
|
|
31
|
-
} from "./chunk-B6RPMDML.js";
|
|
32
|
-
import {
|
|
33
|
-
loadIdentity
|
|
34
|
-
} from "./chunk-AIEXQCQS.js";
|
|
7
|
+
} from "./chunk-OACD3HGE.js";
|
|
8
|
+
import "./chunk-AOQ3WLZV.js";
|
|
9
|
+
import "./chunk-P6KZIJYL.js";
|
|
10
|
+
import "./chunk-WN35MRMF.js";
|
|
11
|
+
import "./chunk-LXQNVVIY.js";
|
|
12
|
+
import "./chunk-M6YOQVSI.js";
|
|
13
|
+
import "./chunk-KWWAIS3C.js";
|
|
35
14
|
import {
|
|
36
15
|
logger
|
|
37
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-NPV3OV2K.js";
|
|
38
17
|
import {
|
|
39
|
-
|
|
40
|
-
} from "./chunk-
|
|
18
|
+
loadConfig
|
|
19
|
+
} from "./chunk-NO3NQN67.js";
|
|
20
|
+
import "./chunk-JBYZ7K56.js";
|
|
41
21
|
import {
|
|
22
|
+
ensureDirectories,
|
|
42
23
|
paths
|
|
43
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-3RYCUGXE.js";
|
|
44
25
|
|
|
45
26
|
// src/runtime/heartbeat.ts
|
|
46
27
|
import { existsSync, unlinkSync, writeFileSync, readFileSync } from "fs";
|
|
28
|
+
|
|
29
|
+
// src/runtime/telemetry.ts
|
|
30
|
+
import { appendFileSync } from "fs";
|
|
31
|
+
function normalize(text) {
|
|
32
|
+
return text.toLowerCase().replace(/[^a-z0-9\s]/g, " ").replace(/\s+/g, " ").trim();
|
|
33
|
+
}
|
|
34
|
+
function prefix(text, n = 6) {
|
|
35
|
+
return normalize(text).split(" ").filter(Boolean).slice(0, n).join(" ");
|
|
36
|
+
}
|
|
37
|
+
function repeatedFormatRate(actions) {
|
|
38
|
+
const posts = actions.filter((action) => action.action === "post" && action.content).map((action) => action.content ?? "");
|
|
39
|
+
if (posts.length <= 1) return 0;
|
|
40
|
+
const seen = /* @__PURE__ */ new Map();
|
|
41
|
+
for (const content of posts) {
|
|
42
|
+
const key = prefix(content);
|
|
43
|
+
seen.set(key, (seen.get(key) ?? 0) + 1);
|
|
44
|
+
}
|
|
45
|
+
let repeated = 0;
|
|
46
|
+
for (const count of seen.values()) {
|
|
47
|
+
if (count > 1) repeated += count;
|
|
48
|
+
}
|
|
49
|
+
return repeated / posts.length;
|
|
50
|
+
}
|
|
51
|
+
function writeHeartbeatMetrics(input) {
|
|
52
|
+
const interactionCount = input.actions.filter((a) => ["reply", "like", "retweet", "follow"].includes(a.action)).length;
|
|
53
|
+
const postCount = input.actions.filter((a) => a.action === "post").length;
|
|
54
|
+
const successCount = input.results.filter((r) => r.success).length;
|
|
55
|
+
const metrics = {
|
|
56
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
57
|
+
timelineCount: input.timelineCount,
|
|
58
|
+
mentionsCount: input.mentionsCount,
|
|
59
|
+
actionCount: input.actions.length,
|
|
60
|
+
successCount,
|
|
61
|
+
postCount,
|
|
62
|
+
interactionCount,
|
|
63
|
+
interactionRatio: input.actions.length > 0 ? interactionCount / input.actions.length : 0,
|
|
64
|
+
repeatedFormatRate: repeatedFormatRate(input.actions),
|
|
65
|
+
policyRejectionCount: input.policyFeedbackCount
|
|
66
|
+
};
|
|
67
|
+
ensureDirectories();
|
|
68
|
+
appendFileSync(paths.runtimeMetrics, JSON.stringify(metrics) + "\n");
|
|
69
|
+
return metrics;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// src/runtime/heartbeat.ts
|
|
47
73
|
var running = false;
|
|
48
74
|
function isRunning() {
|
|
49
75
|
return running;
|
|
@@ -111,7 +137,7 @@ Spora agent is running (PID ${process.pid})`);
|
|
|
111
137
|
heartbeatCount++;
|
|
112
138
|
logger.info(`=== Heartbeat #${heartbeatCount} ===`);
|
|
113
139
|
try {
|
|
114
|
-
await runHeartbeat(maxActions
|
|
140
|
+
await runHeartbeat(maxActions);
|
|
115
141
|
} catch (error) {
|
|
116
142
|
logger.error("Heartbeat error", error);
|
|
117
143
|
console.error(`Heartbeat #${heartbeatCount} failed: ${error.message}`);
|
|
@@ -138,7 +164,7 @@ Spora agent is running (PID ${process.pid})`);
|
|
|
138
164
|
logger.info("Spora agent stopped.");
|
|
139
165
|
console.log("\nSpora agent stopped.");
|
|
140
166
|
}
|
|
141
|
-
async function runHeartbeat(maxActions
|
|
167
|
+
async function runHeartbeat(maxActions) {
|
|
142
168
|
logger.info("Checking queue...");
|
|
143
169
|
try {
|
|
144
170
|
const flushed = await flushQueue();
|
|
@@ -148,65 +174,34 @@ async function runHeartbeat(maxActions, heartbeatCount) {
|
|
|
148
174
|
} catch (error) {
|
|
149
175
|
logger.warn(`Queue flush failed: ${error.message}`);
|
|
150
176
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
`Research: ${research.timeline.length} timeline, ${research.mentions.length} mentions, ${research.topicSearchResults.length} topic searches, ${research.peopleActivity.length} people checked`
|
|
156
|
-
);
|
|
157
|
-
const systemPrompt = buildSystemPrompt();
|
|
158
|
-
const userMessage = buildHeartbeatUserMessage(research);
|
|
159
|
-
logger.info("Asking LLM for decisions...");
|
|
160
|
-
const response = await generateResponse(systemPrompt, userMessage);
|
|
161
|
-
const actions = parseActions(response.content);
|
|
162
|
-
if (actions.length === 0) {
|
|
163
|
-
logger.info("LLM returned no actions.");
|
|
177
|
+
const cycle = await runAutonomyCycle(maxActions);
|
|
178
|
+
logger.info(`Observed ${cycle.timeline.length} timeline posts and ${cycle.mentions.length} mentions.`);
|
|
179
|
+
if (cycle.actions.length === 0) {
|
|
180
|
+
logger.info("Planner returned no approved actions.");
|
|
164
181
|
return;
|
|
165
182
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
const results = await executeActions(limitedActions);
|
|
169
|
-
for (const result of results) {
|
|
183
|
+
logger.info(`Executed ${cycle.results.length} action(s).`);
|
|
184
|
+
for (const result of cycle.results) {
|
|
170
185
|
if (result.success) {
|
|
171
186
|
logger.info(` [OK] ${result.action}${result.detail ? `: ${result.detail}` : ""}`);
|
|
172
187
|
} else {
|
|
173
188
|
logger.warn(` [FAIL] ${result.action}: ${result.error}`);
|
|
174
189
|
}
|
|
175
190
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
try {
|
|
179
|
-
logger.info("Running reflection phase...");
|
|
180
|
-
const reflectionPrompt = buildReflectionPrompt(results);
|
|
181
|
-
const reflectionResponse = await generateResponse(
|
|
182
|
-
`You are ${loadIdentity().name}. Reflect honestly on your performance.`,
|
|
183
|
-
reflectionPrompt
|
|
184
|
-
);
|
|
185
|
-
const jsonMatch = reflectionResponse.content.match(/\{[\s\S]*\}/);
|
|
186
|
-
if (jsonMatch) {
|
|
187
|
-
try {
|
|
188
|
-
const reflection = JSON.parse(jsonMatch[0]);
|
|
189
|
-
if (reflection.learning && reflection.learning !== "null") {
|
|
190
|
-
addLearning(reflection.learning, "reflection", ["heartbeat", "performance"]);
|
|
191
|
-
logger.info(`Reflection learning: ${reflection.learning}`);
|
|
192
|
-
}
|
|
193
|
-
if (reflection.strategyUpdate && reflection.strategyUpdate !== "null") {
|
|
194
|
-
const strategy = loadStrategy();
|
|
195
|
-
strategy.experiments.push({
|
|
196
|
-
description: reflection.strategyUpdate,
|
|
197
|
-
status: "pending"
|
|
198
|
-
});
|
|
199
|
-
strategy.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
|
|
200
|
-
saveStrategy(strategy);
|
|
201
|
-
logger.info(`Strategy update: ${reflection.strategyUpdate}`);
|
|
202
|
-
}
|
|
203
|
-
} catch {
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
} catch (err) {
|
|
207
|
-
logger.warn(`Reflection failed: ${err.message}`);
|
|
208
|
-
}
|
|
191
|
+
for (const note of cycle.policyFeedback) {
|
|
192
|
+
logger.info(` [POLICY] ${note}`);
|
|
209
193
|
}
|
|
194
|
+
const metrics = writeHeartbeatMetrics({
|
|
195
|
+
timelineCount: cycle.timeline.length,
|
|
196
|
+
mentionsCount: cycle.mentions.length,
|
|
197
|
+
actions: cycle.actions,
|
|
198
|
+
results: cycle.results,
|
|
199
|
+
policyFeedbackCount: cycle.policyFeedback.length
|
|
200
|
+
});
|
|
201
|
+
logger.info(
|
|
202
|
+
`Metrics: interactionRatio=${metrics.interactionRatio.toFixed(2)}, repeatedFormatRate=${metrics.repeatedFormatRate.toFixed(2)}`
|
|
203
|
+
);
|
|
204
|
+
logger.info(`Heartbeat complete. ${cycle.results.filter((r) => r.success).length}/${cycle.results.length} actions succeeded.`);
|
|
210
205
|
}
|
|
211
206
|
export {
|
|
212
207
|
getRunningPid,
|
|
@@ -214,4 +209,4 @@ export {
|
|
|
214
209
|
requestStop,
|
|
215
210
|
startHeartbeatLoop
|
|
216
211
|
};
|
|
217
|
-
//# sourceMappingURL=heartbeat-
|
|
212
|
+
//# sourceMappingURL=heartbeat-TNEPE3ZP.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/runtime/heartbeat.ts","../src/runtime/telemetry.ts"],"sourcesContent":["import { existsSync, unlinkSync, writeFileSync, readFileSync } from \"node:fs\";\nimport { logger } from \"../utils/logger.js\";\nimport { loadConfig } from \"../utils/config.js\";\nimport { paths } from \"../utils/paths.js\";\nimport { flushQueue } from \"../scheduler/queue.js\";\nimport { runAutonomyCycle } from \"./autonomy.js\";\nimport { writeHeartbeatMetrics } from \"./telemetry.js\";\n\nlet running = false;\n\nexport function isRunning(): boolean {\n return running;\n}\n\nexport function requestStop(): void {\n writeFileSync(paths.stopSignal, \"stop\");\n logger.info(\"Stop signal sent.\");\n}\n\nfunction shouldStop(): boolean {\n if (existsSync(paths.stopSignal)) {\n unlinkSync(paths.stopSignal);\n return true;\n }\n return false;\n}\n\nfunction writePid(): void {\n writeFileSync(paths.runtimePid, String(process.pid));\n}\n\nfunction clearPid(): void {\n if (existsSync(paths.runtimePid)) {\n unlinkSync(paths.runtimePid);\n }\n}\n\nexport function getRunningPid(): number | null {\n if (!existsSync(paths.runtimePid)) return null;\n const pid = parseInt(readFileSync(paths.runtimePid, \"utf-8\").trim(), 10);\n if (isNaN(pid)) return null;\n\n // Check if process is actually running\n try {\n process.kill(pid, 0);\n return pid;\n } catch {\n // Process not running, clean up stale PID\n clearPid();\n return null;\n }\n}\n\nexport async function startHeartbeatLoop(): Promise<void> {\n // Check if already running\n const existingPid = getRunningPid();\n if (existingPid) {\n throw new Error(`Spora is already running (PID ${existingPid}). Run \\`spora stop\\` first.`);\n }\n\n running = true;\n writePid();\n\n const config = loadConfig();\n const intervalMs = config.runtime?.heartbeatIntervalMs ?? 300_000;\n const maxActions = config.runtime?.actionsPerHeartbeat ?? 3;\n\n logger.info(`Spora agent starting. Heartbeat interval: ${intervalMs / 1000}s, max actions: ${maxActions}`);\n console.log(`\\nSpora agent is running (PID ${process.pid})`);\n console.log(`Heartbeat every ${Math.round(intervalMs / 60_000)} minutes`);\n console.log(`Press Ctrl+C or run \\`spora stop\\` to stop.\\n`);\n\n // Handle graceful shutdown\n const shutdown = () => {\n logger.info(\"Shutting down...\");\n running = false;\n clearPid();\n process.exit(0);\n };\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n // Clean any stale stop signal\n if (existsSync(paths.stopSignal)) {\n unlinkSync(paths.stopSignal);\n }\n\n let heartbeatCount = 0;\n\n while (running) {\n heartbeatCount++;\n logger.info(`=== Heartbeat #${heartbeatCount} ===`);\n\n try {\n await runHeartbeat(maxActions);\n } catch (error) {\n logger.error(\"Heartbeat error\", error);\n console.error(`Heartbeat #${heartbeatCount} failed: ${(error as Error).message}`);\n }\n\n // Check for stop signal\n if (shouldStop()) {\n logger.info(\"Stop signal received.\");\n break;\n }\n\n // Sleep with jitter\n const jitter = Math.floor(Math.random() * intervalMs * 0.3);\n const sleepMs = intervalMs + jitter;\n logger.info(`Sleeping ${Math.round(sleepMs / 1000)}s until next heartbeat...`);\n\n // Sleep in chunks so we can check for stop signals\n const chunkMs = 10_000;\n let slept = 0;\n while (slept < sleepMs && running) {\n await new Promise((r) => setTimeout(r, Math.min(chunkMs, sleepMs - slept)));\n slept += chunkMs;\n if (shouldStop()) {\n running = false;\n break;\n }\n }\n }\n\n clearPid();\n logger.info(\"Spora agent stopped.\");\n console.log(\"\\nSpora agent stopped.\");\n}\n\nasync function runHeartbeat(maxActions: number): Promise<void> {\n // 1. Flush any queued posts\n logger.info(\"Checking queue...\");\n try {\n const flushed = await flushQueue();\n if (flushed.posted > 0) {\n logger.info(`Flushed ${flushed.posted} queued posts.`);\n }\n } catch (error) {\n logger.warn(`Queue flush failed: ${(error as Error).message}`);\n }\n\n // 2. Run planner/executor cycle.\n const cycle = await runAutonomyCycle(maxActions);\n logger.info(`Observed ${cycle.timeline.length} timeline posts and ${cycle.mentions.length} mentions.`);\n\n if (cycle.actions.length === 0) {\n logger.info(\"Planner returned no approved actions.\");\n return;\n }\n\n logger.info(`Executed ${cycle.results.length} action(s).`);\n\n // 3. Log results\n for (const result of cycle.results) {\n if (result.success) {\n logger.info(` [OK] ${result.action}${result.detail ? `: ${result.detail}` : \"\"}`);\n } else {\n logger.warn(` [FAIL] ${result.action}: ${result.error}`);\n }\n }\n\n for (const note of cycle.policyFeedback) {\n logger.info(` [POLICY] ${note}`);\n }\n\n const metrics = writeHeartbeatMetrics({\n timelineCount: cycle.timeline.length,\n mentionsCount: cycle.mentions.length,\n actions: cycle.actions,\n results: cycle.results,\n policyFeedbackCount: cycle.policyFeedback.length,\n });\n logger.info(\n `Metrics: interactionRatio=${metrics.interactionRatio.toFixed(2)}, repeatedFormatRate=${metrics.repeatedFormatRate.toFixed(2)}`\n );\n\n logger.info(`Heartbeat complete. ${cycle.results.filter((r) => r.success).length}/${cycle.results.length} actions succeeded.`);\n}\n","import { appendFileSync } from \"node:fs\";\nimport { paths, ensureDirectories } from \"../utils/paths.js\";\nimport type { AgentAction, ActionResult } from \"./decision-engine.js\";\n\nexport interface HeartbeatMetrics {\n timestamp: string;\n timelineCount: number;\n mentionsCount: number;\n actionCount: number;\n successCount: number;\n postCount: number;\n interactionCount: number;\n interactionRatio: number;\n repeatedFormatRate: number;\n policyRejectionCount: number;\n}\n\nfunction normalize(text: string): string {\n return text.toLowerCase().replace(/[^a-z0-9\\s]/g, \" \").replace(/\\s+/g, \" \").trim();\n}\n\nfunction prefix(text: string, n = 6): string {\n return normalize(text).split(\" \").filter(Boolean).slice(0, n).join(\" \");\n}\n\nfunction repeatedFormatRate(actions: AgentAction[]): number {\n const posts = actions\n .filter((action) => action.action === \"post\" && action.content)\n .map((action) => action.content ?? \"\");\n\n if (posts.length <= 1) return 0;\n\n const seen = new Map<string, number>();\n for (const content of posts) {\n const key = prefix(content);\n seen.set(key, (seen.get(key) ?? 0) + 1);\n }\n\n let repeated = 0;\n for (const count of seen.values()) {\n if (count > 1) repeated += count;\n }\n\n return repeated / posts.length;\n}\n\nexport function writeHeartbeatMetrics(input: {\n timelineCount: number;\n mentionsCount: number;\n actions: AgentAction[];\n results: ActionResult[];\n policyFeedbackCount: number;\n}): HeartbeatMetrics {\n const interactionCount = input.actions.filter((a) => [\"reply\", \"like\", \"retweet\", \"follow\"].includes(a.action)).length;\n const postCount = input.actions.filter((a) => a.action === \"post\").length;\n const successCount = input.results.filter((r) => r.success).length;\n\n const metrics: HeartbeatMetrics = {\n timestamp: new Date().toISOString(),\n timelineCount: input.timelineCount,\n mentionsCount: input.mentionsCount,\n actionCount: input.actions.length,\n successCount,\n postCount,\n interactionCount,\n interactionRatio: input.actions.length > 0 ? interactionCount / input.actions.length : 0,\n repeatedFormatRate: repeatedFormatRate(input.actions),\n policyRejectionCount: input.policyFeedbackCount,\n };\n\n ensureDirectories();\n appendFileSync(paths.runtimeMetrics, JSON.stringify(metrics) + \"\\n\");\n return metrics;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -9,8 +9,8 @@ import {
|
|
|
9
9
|
mutateIdentity,
|
|
10
10
|
renderIdentityDocument,
|
|
11
11
|
saveIdentity
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-M6YOQVSI.js";
|
|
13
|
+
import "./chunk-3RYCUGXE.js";
|
|
14
14
|
export {
|
|
15
15
|
FRAMEWORKS,
|
|
16
16
|
GOAL_PRESETS,
|
|
@@ -23,4 +23,4 @@ export {
|
|
|
23
23
|
renderIdentityDocument,
|
|
24
24
|
saveIdentity
|
|
25
25
|
};
|
|
26
|
-
//# sourceMappingURL=identity-
|
|
26
|
+
//# sourceMappingURL=identity-VDUW4I2K.js.map
|
|
@@ -1,17 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createDefaultConfig,
|
|
3
|
-
saveConfig
|
|
4
|
-
} from "./chunk-B6RPMDML.js";
|
|
5
1
|
import {
|
|
6
2
|
loadIdentity
|
|
7
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-M6YOQVSI.js";
|
|
8
4
|
import {
|
|
9
5
|
loadCredentials,
|
|
10
6
|
saveCredentials
|
|
11
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-VZBHRUZS.js";
|
|
8
|
+
import {
|
|
9
|
+
getDefaultModel,
|
|
10
|
+
setLLMApiKey
|
|
11
|
+
} from "./chunk-KWWAIS3C.js";
|
|
12
|
+
import "./chunk-NPV3OV2K.js";
|
|
13
|
+
import {
|
|
14
|
+
createDefaultConfig,
|
|
15
|
+
saveConfig
|
|
16
|
+
} from "./chunk-NO3NQN67.js";
|
|
12
17
|
import {
|
|
13
18
|
ensureDirectories
|
|
14
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-3RYCUGXE.js";
|
|
15
20
|
|
|
16
21
|
// src/init.ts
|
|
17
22
|
import { input, select, password as passwordPrompt } from "@inquirer/prompts";
|
|
@@ -51,18 +56,6 @@ async function updateXProfile(identity) {
|
|
|
51
56
|
console.error("Name/bio update error:", error);
|
|
52
57
|
result.errors.push(`Failed to update name/bio: ${error.message}`);
|
|
53
58
|
}
|
|
54
|
-
if (identity.handle) {
|
|
55
|
-
try {
|
|
56
|
-
console.log(`Attempting to update username to: @${identity.handle}`);
|
|
57
|
-
await client.v1.updateAccountProfile({
|
|
58
|
-
screen_name: identity.handle
|
|
59
|
-
});
|
|
60
|
-
result.updated.push("username");
|
|
61
|
-
console.log("Username updated successfully");
|
|
62
|
-
} catch (error) {
|
|
63
|
-
console.warn(`Could not update username: ${error.message}`);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
59
|
if (identity.profileImage) {
|
|
67
60
|
try {
|
|
68
61
|
console.log(`Downloading profile image from: ${identity.profileImage.substring(0, 60)}...`);
|
|
@@ -157,22 +150,22 @@ async function syncIdentityFromToken(token) {
|
|
|
157
150
|
if (data.media.profileImage) data.identity.profileImage = data.media.profileImage;
|
|
158
151
|
if (data.media.bannerImage) data.identity.bannerImage = data.media.bannerImage;
|
|
159
152
|
}
|
|
160
|
-
const { saveIdentity } = await import("./identity-
|
|
153
|
+
const { saveIdentity } = await import("./identity-VDUW4I2K.js");
|
|
161
154
|
saveIdentity(data.identity);
|
|
162
155
|
console.log(chalk.green(`\u2713 Connected to Spore: ${data.identity.name} (@${data.identity.handle})
|
|
163
156
|
`));
|
|
164
157
|
if (data.readme) {
|
|
165
158
|
const { writeFileSync } = await import("fs");
|
|
166
|
-
const { paths: paths2 } = await import("./paths-
|
|
159
|
+
const { paths: paths2 } = await import("./paths-BYR6MEPR.js");
|
|
167
160
|
const { join, dirname } = await import("path");
|
|
168
161
|
const readmePath = join(dirname(paths2.identity), "IDENTITY.md");
|
|
169
162
|
writeFileSync(readmePath, data.readme, "utf-8");
|
|
170
163
|
console.log(chalk.green("\u2713 Saved identity README\n"));
|
|
171
164
|
}
|
|
172
165
|
const { existsSync } = await import("fs");
|
|
173
|
-
const { paths } = await import("./paths-
|
|
166
|
+
const { paths } = await import("./paths-BYR6MEPR.js");
|
|
174
167
|
if (existsSync(paths.config)) {
|
|
175
|
-
const { loadConfig, saveConfig: saveConfig2 } = await import("./config-
|
|
168
|
+
const { loadConfig, saveConfig: saveConfig2 } = await import("./config-FL4VJVKZ.js");
|
|
176
169
|
const config = loadConfig();
|
|
177
170
|
config.connection = {
|
|
178
171
|
token,
|
|
@@ -203,7 +196,7 @@ async function loginFlow() {
|
|
|
203
196
|
console.log(chalk.green("\u2713 Logged in!\n"));
|
|
204
197
|
console.log(chalk.gray("Opening chat interface...\n"));
|
|
205
198
|
try {
|
|
206
|
-
const { startWebChat } = await import("./web-chat-
|
|
199
|
+
const { startWebChat } = await import("./web-chat-3HM35XM4.js");
|
|
207
200
|
await startWebChat();
|
|
208
201
|
} catch (error) {
|
|
209
202
|
console.log(chalk.yellow(`Could not start chat interface: ${error.message}
|
|
@@ -211,19 +204,35 @@ async function loginFlow() {
|
|
|
211
204
|
console.log(chalk.gray("You can start it manually with: spora chat\n"));
|
|
212
205
|
}
|
|
213
206
|
}
|
|
207
|
+
function providerKeyUrl(provider) {
|
|
208
|
+
if (provider === "anthropic") return "https://console.anthropic.com/settings/keys";
|
|
209
|
+
if (provider === "openai") return "https://platform.openai.com/api-keys";
|
|
210
|
+
return "https://platform.deepseek.com/api_keys";
|
|
211
|
+
}
|
|
214
212
|
async function setupKeys() {
|
|
215
|
-
console.log(chalk.bold("\n\u2501\u2501\u2501
|
|
216
|
-
|
|
217
|
-
|
|
213
|
+
console.log(chalk.bold("\n\u2501\u2501\u2501 LLM Provider Setup \u2501\u2501\u2501\n"));
|
|
214
|
+
const provider = await select({
|
|
215
|
+
message: "Choose your LLM provider:",
|
|
216
|
+
choices: [
|
|
217
|
+
{ name: "DeepSeek (recommended for low cost)", value: "deepseek" },
|
|
218
|
+
{ name: "Anthropic (Claude)", value: "anthropic" },
|
|
219
|
+
{ name: "OpenAI", value: "openai" }
|
|
220
|
+
]
|
|
221
|
+
});
|
|
222
|
+
const defaultModel = getDefaultModel(provider);
|
|
223
|
+
const model = await input({
|
|
224
|
+
message: `Model name for ${provider} (press enter for ${defaultModel}):`
|
|
225
|
+
});
|
|
226
|
+
console.log(chalk.gray("Get your API key at: ") + chalk.cyan(`${providerKeyUrl(provider)}
|
|
227
|
+
`));
|
|
218
228
|
const llmKey = await passwordPrompt({
|
|
219
|
-
message:
|
|
229
|
+
message: `${provider} API Key:`,
|
|
220
230
|
mask: "*",
|
|
221
231
|
validate: (val) => val.length > 0 ? true : "API key is required"
|
|
222
232
|
});
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
console.log(chalk.green("\u2713 DeepSeek API key saved\n"));
|
|
233
|
+
setLLMApiKey(provider, llmKey.trim());
|
|
234
|
+
console.log(chalk.green(`\u2713 ${provider} API key saved
|
|
235
|
+
`));
|
|
227
236
|
console.log(chalk.bold("\n\u2501\u2501\u2501 Connect Your X Account \u2501\u2501\u2501\n"));
|
|
228
237
|
console.log(chalk.gray("Your Spore needs OAuth 1.0a credentials for full X API access."));
|
|
229
238
|
console.log(chalk.gray("This gives your agent the power to read timelines, post tweets, reply, like, and follow.\n"));
|
|
@@ -232,7 +241,7 @@ async function setupKeys() {
|
|
|
232
241
|
console.log(chalk.gray(" 2. Create or select your app"));
|
|
233
242
|
console.log(chalk.gray(' 3. Go to "Keys and tokens" tab'));
|
|
234
243
|
console.log(chalk.gray(" 4. Copy all 4 credentials below\n"));
|
|
235
|
-
console.log(chalk.yellow("Note:
|
|
244
|
+
console.log(chalk.yellow("Note: Some endpoints may require paid X API access depending on your tier.\n"));
|
|
236
245
|
const apiKey = await passwordPrompt({
|
|
237
246
|
message: "X API Key (Consumer Key):",
|
|
238
247
|
mask: "*",
|
|
@@ -253,10 +262,8 @@ async function setupKeys() {
|
|
|
253
262
|
mask: "*",
|
|
254
263
|
validate: (val) => val.length > 0 ? true : "Access Token Secret is required"
|
|
255
264
|
});
|
|
256
|
-
const bearerToken = await
|
|
257
|
-
message: "X Bearer Token:"
|
|
258
|
-
mask: "*",
|
|
259
|
-
validate: (val) => val.length > 0 ? true : "Bearer Token is required"
|
|
265
|
+
const bearerToken = await input({
|
|
266
|
+
message: "X Bearer Token (optional, press enter to skip):"
|
|
260
267
|
});
|
|
261
268
|
saveCredentials({
|
|
262
269
|
method: "api",
|
|
@@ -264,9 +271,15 @@ async function setupKeys() {
|
|
|
264
271
|
apiSecret,
|
|
265
272
|
accessToken,
|
|
266
273
|
accessTokenSecret,
|
|
267
|
-
bearerToken
|
|
274
|
+
bearerToken: bearerToken.trim() || void 0
|
|
268
275
|
});
|
|
269
276
|
console.log(chalk.green("\u2713 X API credentials saved (encrypted)\n"));
|
|
277
|
+
return {
|
|
278
|
+
llm: {
|
|
279
|
+
provider,
|
|
280
|
+
model: model.trim() || defaultModel
|
|
281
|
+
}
|
|
282
|
+
};
|
|
270
283
|
}
|
|
271
284
|
async function showDoneAndOpenChat() {
|
|
272
285
|
console.log(chalk.green("\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
|
|
@@ -275,7 +288,7 @@ async function showDoneAndOpenChat() {
|
|
|
275
288
|
console.log(chalk.bold.cyan("\u2501\u2501\u2501 Your Spore is Ready! \u2501\u2501\u2501\n"));
|
|
276
289
|
console.log(chalk.gray("Opening chat interface...\n"));
|
|
277
290
|
try {
|
|
278
|
-
const { startWebChat } = await import("./web-chat-
|
|
291
|
+
const { startWebChat } = await import("./web-chat-3HM35XM4.js");
|
|
279
292
|
await startWebChat();
|
|
280
293
|
} catch (error) {
|
|
281
294
|
console.log(chalk.yellow(`Could not start chat interface: ${error.message}
|
|
@@ -311,7 +324,7 @@ async function runInit(token) {
|
|
|
311
324
|
console.log(chalk.yellow("Please check your token and try again.\n"));
|
|
312
325
|
process.exit(1);
|
|
313
326
|
}
|
|
314
|
-
await setupKeys();
|
|
327
|
+
const setup2 = await setupKeys();
|
|
315
328
|
console.log(chalk.bold("\n\u2501\u2501\u2501 Updating Your X Profile \u2501\u2501\u2501\n"));
|
|
316
329
|
console.log(chalk.gray("Setting up profile picture, banner, and bio to match your Spore...\n"));
|
|
317
330
|
try {
|
|
@@ -340,8 +353,8 @@ async function runInit(token) {
|
|
|
340
353
|
console.log(chalk.gray("You can manually update your X profile later.\n"));
|
|
341
354
|
}
|
|
342
355
|
const config2 = createDefaultConfig({ xMethod: "api", xApiTier: "basic" });
|
|
343
|
-
config2.llm =
|
|
344
|
-
config2.runtime = { heartbeatIntervalMs: 3e5, actionsPerHeartbeat:
|
|
356
|
+
config2.llm = setup2.llm;
|
|
357
|
+
config2.runtime = { heartbeatIntervalMs: 3e5, actionsPerHeartbeat: 4, enabled: true };
|
|
345
358
|
config2.connection = {
|
|
346
359
|
token,
|
|
347
360
|
apiEndpoint: process.env.SPORA_API_URL || "https://www.spora.social/api/v1",
|
|
@@ -363,7 +376,7 @@ async function runInit(token) {
|
|
|
363
376
|
return;
|
|
364
377
|
}
|
|
365
378
|
ensureDirectories();
|
|
366
|
-
await setupKeys();
|
|
379
|
+
const setup = await setupKeys();
|
|
367
380
|
console.log(chalk.bold("\n\u2501\u2501\u2501 Updating Your X Profile \u2501\u2501\u2501\n"));
|
|
368
381
|
console.log(chalk.gray("Setting up profile picture, banner, and bio to match your Spore...\n"));
|
|
369
382
|
try {
|
|
@@ -392,12 +405,12 @@ async function runInit(token) {
|
|
|
392
405
|
console.log(chalk.gray("You can manually update your X profile later.\n"));
|
|
393
406
|
}
|
|
394
407
|
const config = createDefaultConfig({ xMethod: "api", xApiTier: "basic" });
|
|
395
|
-
config.llm =
|
|
396
|
-
config.runtime = { heartbeatIntervalMs: 3e5, actionsPerHeartbeat:
|
|
408
|
+
config.llm = setup.llm;
|
|
409
|
+
config.runtime = { heartbeatIntervalMs: 3e5, actionsPerHeartbeat: 4, enabled: true };
|
|
397
410
|
saveConfig(config);
|
|
398
411
|
await showDoneAndOpenChat();
|
|
399
412
|
}
|
|
400
413
|
export {
|
|
401
414
|
runInit
|
|
402
415
|
};
|
|
403
|
-
//# sourceMappingURL=init-
|
|
416
|
+
//# sourceMappingURL=init-ISSXETHY.js.map
|