orca-agent 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/dist/__tests__/challenge.test.d.ts +2 -0
  2. package/dist/__tests__/challenge.test.d.ts.map +1 -0
  3. package/dist/__tests__/challenge.test.js +146 -0
  4. package/dist/__tests__/challenge.test.js.map +1 -0
  5. package/dist/__tests__/config.test.d.ts +2 -0
  6. package/dist/__tests__/config.test.d.ts.map +1 -0
  7. package/dist/__tests__/config.test.js +141 -0
  8. package/dist/__tests__/config.test.js.map +1 -0
  9. package/dist/__tests__/keypair.test.d.ts +2 -0
  10. package/dist/__tests__/keypair.test.d.ts.map +1 -0
  11. package/dist/__tests__/keypair.test.js +144 -0
  12. package/dist/__tests__/keypair.test.js.map +1 -0
  13. package/dist/__tests__/task_handler.test.d.ts +2 -0
  14. package/dist/__tests__/task_handler.test.d.ts.map +1 -0
  15. package/dist/__tests__/task_handler.test.js +216 -0
  16. package/dist/__tests__/task_handler.test.js.map +1 -0
  17. package/dist/cli.d.ts +3 -0
  18. package/dist/cli.d.ts.map +1 -0
  19. package/dist/cli.js +87 -0
  20. package/dist/cli.js.map +1 -0
  21. package/dist/commands/connect.d.ts +2 -0
  22. package/dist/commands/connect.d.ts.map +1 -0
  23. package/dist/commands/connect.js +81 -0
  24. package/dist/commands/connect.js.map +1 -0
  25. package/dist/commands/daemon.d.ts +2 -0
  26. package/dist/commands/daemon.d.ts.map +1 -0
  27. package/dist/commands/daemon.js +42 -0
  28. package/dist/commands/daemon.js.map +1 -0
  29. package/dist/commands/join.d.ts +8 -0
  30. package/dist/commands/join.d.ts.map +1 -0
  31. package/dist/commands/join.js +96 -0
  32. package/dist/commands/join.js.map +1 -0
  33. package/dist/commands/status.d.ts +2 -0
  34. package/dist/commands/status.d.ts.map +1 -0
  35. package/dist/commands/status.js +75 -0
  36. package/dist/commands/status.js.map +1 -0
  37. package/dist/commands/stop.d.ts +2 -0
  38. package/dist/commands/stop.d.ts.map +1 -0
  39. package/dist/commands/stop.js +10 -0
  40. package/dist/commands/stop.js.map +1 -0
  41. package/dist/config.d.ts +26 -0
  42. package/dist/config.d.ts.map +1 -0
  43. package/dist/config.js +59 -0
  44. package/dist/config.js.map +1 -0
  45. package/dist/crypto/keypair.d.ts +14 -0
  46. package/dist/crypto/keypair.d.ts.map +1 -0
  47. package/dist/crypto/keypair.js +76 -0
  48. package/dist/crypto/keypair.js.map +1 -0
  49. package/dist/daemon/heartbeat.d.ts +5 -0
  50. package/dist/daemon/heartbeat.d.ts.map +1 -0
  51. package/dist/daemon/heartbeat.js +49 -0
  52. package/dist/daemon/heartbeat.js.map +1 -0
  53. package/dist/daemon/nats.d.ts +22 -0
  54. package/dist/daemon/nats.d.ts.map +1 -0
  55. package/dist/daemon/nats.js +73 -0
  56. package/dist/daemon/nats.js.map +1 -0
  57. package/dist/daemon/task_handler.d.ts +3 -0
  58. package/dist/daemon/task_handler.d.ts.map +1 -0
  59. package/dist/daemon/task_handler.js +161 -0
  60. package/dist/daemon/task_handler.js.map +1 -0
  61. package/dist/index.d.ts +7 -0
  62. package/dist/index.d.ts.map +1 -0
  63. package/dist/index.js +8 -0
  64. package/dist/index.js.map +1 -0
  65. package/dist/install/daemon.d.ts +4 -0
  66. package/dist/install/daemon.d.ts.map +1 -0
  67. package/dist/install/daemon.js +214 -0
  68. package/dist/install/daemon.js.map +1 -0
  69. package/dist/install/skills.d.ts +4 -0
  70. package/dist/install/skills.d.ts.map +1 -0
  71. package/dist/install/skills.js +83 -0
  72. package/dist/install/skills.js.map +1 -0
  73. package/dist/moltbook/challenge.d.ts +35 -0
  74. package/dist/moltbook/challenge.d.ts.map +1 -0
  75. package/dist/moltbook/challenge.js +157 -0
  76. package/dist/moltbook/challenge.js.map +1 -0
  77. package/dist/moltbook/client.d.ts +35 -0
  78. package/dist/moltbook/client.d.ts.map +1 -0
  79. package/dist/moltbook/client.js +73 -0
  80. package/dist/moltbook/client.js.map +1 -0
  81. package/dist/moltbook/executor.d.ts +8 -0
  82. package/dist/moltbook/executor.d.ts.map +1 -0
  83. package/dist/moltbook/executor.js +74 -0
  84. package/dist/moltbook/executor.js.map +1 -0
  85. package/dist/moltbook/register.d.ts +14 -0
  86. package/dist/moltbook/register.d.ts.map +1 -0
  87. package/dist/moltbook/register.js +64 -0
  88. package/dist/moltbook/register.js.map +1 -0
  89. package/dist/openclaw/poll.d.ts +7 -0
  90. package/dist/openclaw/poll.d.ts.map +1 -0
  91. package/dist/openclaw/poll.js +57 -0
  92. package/dist/openclaw/poll.js.map +1 -0
  93. package/dist/openclaw/webhook.d.ts +16 -0
  94. package/dist/openclaw/webhook.d.ts.map +1 -0
  95. package/dist/openclaw/webhook.js +45 -0
  96. package/dist/openclaw/webhook.js.map +1 -0
  97. package/package.json +35 -0
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Moltbook API client.
3
+ *
4
+ * Handles upvoting, commenting, and verification challenges.
5
+ * CRITICAL: Always use www.moltbook.com - bare domain strips auth headers
6
+ * NEVER log the API key in plaintext
7
+ */
8
+ const MOLTBOOK_BASE_URL = "https://www.moltbook.com/api/v1";
9
+ export class MoltbookClient {
10
+ apiKey;
11
+ rateLimitRemaining = 100;
12
+ rateLimitReset = 0;
13
+ constructor(apiKey) {
14
+ this.apiKey = apiKey;
15
+ }
16
+ async request(method, path, body) {
17
+ // Check rate limit
18
+ if (this.rateLimitRemaining <= 0) {
19
+ const waitTime = this.rateLimitReset - Date.now();
20
+ if (waitTime > 0) {
21
+ console.log(`Rate limited, waiting ${waitTime}ms...`);
22
+ await new Promise((resolve) => setTimeout(resolve, waitTime));
23
+ }
24
+ }
25
+ const response = await fetch(`${MOLTBOOK_BASE_URL}${path}`, {
26
+ method,
27
+ headers: {
28
+ "Content-Type": "application/json",
29
+ Authorization: `Bearer ${this.apiKey}`,
30
+ },
31
+ body: body ? JSON.stringify(body) : undefined,
32
+ });
33
+ // Update rate limit tracking
34
+ const remaining = response.headers.get("X-RateLimit-Remaining");
35
+ const reset = response.headers.get("X-RateLimit-Reset");
36
+ if (remaining) {
37
+ this.rateLimitRemaining = parseInt(remaining, 10);
38
+ }
39
+ if (reset) {
40
+ this.rateLimitReset = parseInt(reset, 10) * 1000; // Convert to ms
41
+ }
42
+ if (response.status === 429) {
43
+ const retryAfter = response.headers.get("Retry-After");
44
+ const waitTime = retryAfter ? parseInt(retryAfter, 10) * 1000 : 60000;
45
+ console.log(`Rate limited (429), waiting ${waitTime}ms...`);
46
+ await new Promise((resolve) => setTimeout(resolve, waitTime));
47
+ return this.request(method, path, body);
48
+ }
49
+ if (!response.ok) {
50
+ const text = await response.text();
51
+ throw new Error(`Moltbook API error ${response.status}: ${text}`);
52
+ }
53
+ return response.json();
54
+ }
55
+ async upvotePost(postId) {
56
+ return this.request("POST", `/posts/${postId}/upvote`);
57
+ }
58
+ async commentOnPost(postId, content) {
59
+ return this.request("POST", `/posts/${postId}/comments`, {
60
+ content,
61
+ });
62
+ }
63
+ async submitVerification(verificationCode, answer) {
64
+ return this.request("POST", "/verify", {
65
+ verification_code: verificationCode,
66
+ answer,
67
+ });
68
+ }
69
+ getRateLimitRemaining() {
70
+ return this.rateLimitRemaining;
71
+ }
72
+ }
73
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/moltbook/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { TaskOffer } from "../daemon/nats.js";
2
+ export interface ProofPayload {
3
+ actionsCompleted: string[];
4
+ commentId?: string;
5
+ upvoteConfirmed: boolean;
6
+ }
7
+ export declare function executeTask(offer: TaskOffer, agentId: string): Promise<ProofPayload>;
8
+ //# sourceMappingURL=executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/moltbook/executor.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C,MAAM,WAAW,YAAY;IAC3B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAsB,WAAW,CAC/B,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,YAAY,CAAC,CA+EvB"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Moltbook task executor.
3
+ *
4
+ * Executes upvote and/or comment actions on Moltbook posts.
5
+ */
6
+ import { loadConfig } from "../config.js";
7
+ import { MoltbookClient } from "./client.js";
8
+ import { solveChallenge } from "./challenge.js";
9
+ export async function executeTask(offer, agentId) {
10
+ const config = loadConfig();
11
+ if (!config?.moltbook?.apiKey) {
12
+ throw new Error("Moltbook not connected. Run 'orca-agent connect-moltbook' first.");
13
+ }
14
+ const client = new MoltbookClient(config.moltbook.apiKey);
15
+ const actionsCompleted = [];
16
+ let commentId;
17
+ let upvoteConfirmed = false;
18
+ // Execute upvote if required
19
+ if (offer.action === "upvote" || offer.action === "both") {
20
+ console.log("Upvoting post...");
21
+ try {
22
+ const result = await client.upvotePost(offer.target_post_id);
23
+ if (result.success) {
24
+ actionsCompleted.push("upvote");
25
+ upvoteConfirmed = true;
26
+ console.log("Upvote successful!");
27
+ }
28
+ }
29
+ catch (error) {
30
+ console.error("Upvote failed:", error);
31
+ }
32
+ }
33
+ // Execute comment if required
34
+ if (offer.action === "comment" || offer.action === "both") {
35
+ console.log("Commenting on post...");
36
+ const commentContent = offer.comment_prompt || "Great post!";
37
+ try {
38
+ const result = await client.commentOnPost(offer.target_post_id, commentContent);
39
+ if (result.verification_required && result.verification_code) {
40
+ // Handle verification challenge
41
+ console.log("Verification required, solving challenge...");
42
+ if (result.challenge) {
43
+ const answer = solveChallenge(result.challenge);
44
+ console.log(`Challenge answer: ${answer}`);
45
+ const verifyResult = await client.submitVerification(result.verification_code, answer);
46
+ if (verifyResult.verified) {
47
+ console.log("Verification successful!");
48
+ // The comment should be posted now, but we need the ID
49
+ // Make another comment call or parse from response
50
+ actionsCompleted.push("comment");
51
+ commentId = result.comment_id;
52
+ }
53
+ else {
54
+ throw new Error(`Verification failed: ${verifyResult.error || "unknown error"}`);
55
+ }
56
+ }
57
+ }
58
+ else if (result.success) {
59
+ actionsCompleted.push("comment");
60
+ commentId = result.comment_id;
61
+ console.log(`Comment posted! ID: ${commentId}`);
62
+ }
63
+ }
64
+ catch (error) {
65
+ console.error("Comment failed:", error);
66
+ }
67
+ }
68
+ return {
69
+ actionsCompleted,
70
+ commentId,
71
+ upvoteConfirmed,
72
+ };
73
+ }
74
+ //# sourceMappingURL=executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../../src/moltbook/executor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export interface MoltbookRegistration {
2
+ apiKey: string;
3
+ claimUrl: string;
4
+ verificationCode: string;
5
+ }
6
+ export declare function registerMoltbookAgent(name: string, description?: string): Promise<MoltbookRegistration>;
7
+ export declare function checkClaimStatus(apiKey: string): Promise<string>;
8
+ export declare function pollClaimStatus(apiKey: string, pollIntervalMs?: number, maxWaitMs?: number): Promise<boolean>;
9
+ export declare function saveMoltbookCredentials(apiKey: string, claimed?: boolean): void;
10
+ export declare function loadMoltbookCredentials(): {
11
+ apiKey?: string;
12
+ claimed?: boolean;
13
+ } | null;
14
+ //# sourceMappingURL=register.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/moltbook/register.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,MAAM,EACZ,WAAW,GAAE,MAAyC,GACrD,OAAO,CAAC,oBAAoB,CAAC,CAwB/B;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAatE;AAED,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,cAAc,GAAE,MAAc,EAC9B,SAAS,GAAE,MAAgB,GAC1B,OAAO,CAAC,OAAO,CAAC,CAmBlB;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,OAAe,GACvB,IAAI,CAON;AAED,wBAAgB,uBAAuB,IAAI;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAGvF"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Moltbook agent registration and credential management.
3
+ */
4
+ import { updateConfig, loadConfig } from "../config.js";
5
+ const MOLTBOOK_BASE_URL = "https://www.moltbook.com/api/v1";
6
+ export async function registerMoltbookAgent(name, description = "OpenClaw agent on Orca Network") {
7
+ const response = await fetch(`${MOLTBOOK_BASE_URL}/agents/register`, {
8
+ method: "POST",
9
+ headers: { "Content-Type": "application/json" },
10
+ body: JSON.stringify({ name, description }),
11
+ });
12
+ if (!response.ok) {
13
+ throw new Error(`Registration failed: ${response.status}`);
14
+ }
15
+ const data = (await response.json());
16
+ return {
17
+ apiKey: data.agent.api_key,
18
+ claimUrl: data.agent.claim_url,
19
+ verificationCode: data.agent.verification_code,
20
+ };
21
+ }
22
+ export async function checkClaimStatus(apiKey) {
23
+ const response = await fetch(`${MOLTBOOK_BASE_URL}/agents/status`, {
24
+ headers: {
25
+ Authorization: `Bearer ${apiKey}`,
26
+ },
27
+ });
28
+ if (!response.ok) {
29
+ throw new Error(`Status check failed: ${response.status}`);
30
+ }
31
+ const data = (await response.json());
32
+ return data.status;
33
+ }
34
+ export async function pollClaimStatus(apiKey, pollIntervalMs = 30000, maxWaitMs = 7200000 // 2 hours
35
+ ) {
36
+ const startTime = Date.now();
37
+ while (Date.now() - startTime < maxWaitMs) {
38
+ try {
39
+ const status = await checkClaimStatus(apiKey);
40
+ console.log(`Claim status: ${status}`);
41
+ if (status === "claimed") {
42
+ return true;
43
+ }
44
+ }
45
+ catch (error) {
46
+ console.error("Poll error:", error);
47
+ }
48
+ await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
49
+ }
50
+ return false;
51
+ }
52
+ export function saveMoltbookCredentials(apiKey, claimed = false) {
53
+ updateConfig({
54
+ moltbook: {
55
+ apiKey,
56
+ claimed,
57
+ },
58
+ });
59
+ }
60
+ export function loadMoltbookCredentials() {
61
+ const config = loadConfig();
62
+ return config?.moltbook || null;
63
+ }
64
+ //# sourceMappingURL=register.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.js","sourceRoot":"","sources":["../../src/moltbook/register.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAExD,MAAM,iBAAiB,GAAG,iCAAiC,CAAC;AAQ5D,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,IAAY,EACZ,cAAsB,gCAAgC;IAEtD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,iBAAiB,kBAAkB,EAAE;QACnE,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;KAC5C,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,wBAAwB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAMlC,CAAC;IAEF,OAAO;QACL,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO;QAC1B,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS;QAC9B,gBAAgB,EAAE,IAAI,CAAC,KAAK,CAAC,iBAAiB;KAC/C,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAAc;IACnD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,iBAAiB,gBAAgB,EAAE;QACjE,OAAO,EAAE;YACP,aAAa,EAAE,UAAU,MAAM,EAAE;SAClC;KACF,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,wBAAwB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAuB,CAAC;IAC3D,OAAO,IAAI,CAAC,MAAM,CAAC;AACrB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAAc,EACd,iBAAyB,KAAK,EAC9B,YAAoB,OAAO,CAAC,UAAU;;IAEtC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,GAAG,SAAS,EAAE,CAAC;QAC1C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,MAAM,CAAC,CAAC;YAC9C,OAAO,CAAC,GAAG,CAAC,iBAAiB,MAAM,EAAE,CAAC,CAAC;YAEvC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBACzB,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;QACtC,CAAC;QAED,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC;IACtE,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,MAAc,EACd,UAAmB,KAAK;IAExB,YAAY,CAAC;QACX,QAAQ,EAAE;YACR,MAAM;YACN,OAAO;SACR;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,uBAAuB;IACrC,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,OAAO,MAAM,EAAE,QAAQ,IAAI,IAAI,CAAC;AAClC,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * OpenClaw response polling.
3
+ *
4
+ * Polls the sessions_history endpoint for YES/NO responses.
5
+ */
6
+ export declare function pollForResponse(timeoutMs?: number): Promise<string | null>;
7
+ //# sourceMappingURL=poll.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"poll.d.ts","sourceRoot":"","sources":["../../src/openclaw/poll.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAgBH,wBAAsB,eAAe,CACnC,SAAS,GAAE,MAAe,GACzB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA4DxB"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * OpenClaw response polling.
3
+ *
4
+ * Polls the sessions_history endpoint for YES/NO responses.
5
+ */
6
+ const OPENCLAW_URL = "http://127.0.0.1:18789";
7
+ const SESSION_KEY = "hook:orca";
8
+ const POLL_INTERVAL_MS = 5000;
9
+ export async function pollForResponse(timeoutMs = 600000 // 10 minutes
10
+ ) {
11
+ const startTime = Date.now();
12
+ let lastMessageTimestamp = 0;
13
+ while (Date.now() - startTime < timeoutMs) {
14
+ try {
15
+ const response = await fetch(`${OPENCLAW_URL}/sessions_history?sessionKey=${SESSION_KEY}`);
16
+ if (!response.ok) {
17
+ throw new Error(`Poll failed: ${response.status}`);
18
+ }
19
+ const history = (await response.json());
20
+ // Find the most recent assistant message
21
+ for (let i = history.messages.length - 1; i >= 0; i--) {
22
+ const msg = history.messages[i];
23
+ if (msg.role === "assistant") {
24
+ const timestamp = msg.timestamp || i;
25
+ // Skip if we've already seen this message
26
+ if (timestamp <= lastMessageTimestamp) {
27
+ break;
28
+ }
29
+ lastMessageTimestamp = timestamp;
30
+ // Parse first line for YES/NO
31
+ const firstLine = msg.content.split("\n")[0].trim().toUpperCase();
32
+ if (firstLine === "YES" || firstLine.startsWith("YES")) {
33
+ return "YES";
34
+ }
35
+ if (firstLine === "NO" || firstLine.startsWith("NO")) {
36
+ return "NO";
37
+ }
38
+ // Not a YES/NO response, continue polling
39
+ break;
40
+ }
41
+ }
42
+ }
43
+ catch (error) {
44
+ // OpenClaw not available
45
+ if (error instanceof Error &&
46
+ (error.message.includes("ECONNREFUSED") ||
47
+ error.message.includes("fetch failed"))) {
48
+ throw new Error("OpenClaw not available");
49
+ }
50
+ console.error("Poll error:", error);
51
+ }
52
+ await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
53
+ }
54
+ // Timeout - no response
55
+ return null;
56
+ }
57
+ //# sourceMappingURL=poll.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"poll.js","sourceRoot":"","sources":["../../src/openclaw/poll.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,YAAY,GAAG,wBAAwB,CAAC;AAC9C,MAAM,WAAW,GAAG,WAAW,CAAC;AAChC,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAY9B,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,YAAoB,MAAM,CAAC,aAAa;;IAExC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,IAAI,oBAAoB,GAAG,CAAC,CAAC;IAE7B,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,GAAG,SAAS,EAAE,CAAC;QAC1C,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAC1B,GAAG,YAAY,gCAAgC,WAAW,EAAE,CAC7D,CAAC;YAEF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CAAC,gBAAgB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;YACrD,CAAC;YAED,MAAM,OAAO,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAmB,CAAC;YAE1D,yCAAyC;YACzC,KAAK,IAAI,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBACtD,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;gBAChC,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;oBAC7B,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,IAAI,CAAC,CAAC;oBAErC,0CAA0C;oBAC1C,IAAI,SAAS,IAAI,oBAAoB,EAAE,CAAC;wBACtC,MAAM;oBACR,CAAC;oBAED,oBAAoB,GAAG,SAAS,CAAC;oBAEjC,8BAA8B;oBAC9B,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;oBAElE,IAAI,SAAS,KAAK,KAAK,IAAI,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;wBACvD,OAAO,KAAK,CAAC;oBACf,CAAC;oBACD,IAAI,SAAS,KAAK,IAAI,IAAI,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;wBACrD,OAAO,IAAI,CAAC;oBACd,CAAC;oBAED,0CAA0C;oBAC1C,MAAM;gBACR,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,yBAAyB;YACzB,IACE,KAAK,YAAY,KAAK;gBACtB,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC;oBACrC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,EACzC,CAAC;gBACD,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;YAC5C,CAAC;YACD,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;QACtC,CAAC;QAED,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC;IACxE,CAAC;IAED,wBAAwB;IACxB,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * OpenClaw webhook integration.
3
+ *
4
+ * Sends messages to the OpenClaw local daemon for Telegram delivery.
5
+ * Handles ECONNREFUSED gracefully (OpenClaw not installed).
6
+ */
7
+ export interface WebhookPayload {
8
+ message: string;
9
+ name?: string;
10
+ sessionKey?: string;
11
+ deliver?: boolean;
12
+ channel?: string;
13
+ }
14
+ export declare function sendWebhook(message: string, options?: Partial<WebhookPayload>): Promise<void>;
15
+ export declare function isOpenClawAvailable(): Promise<boolean>;
16
+ //# sourceMappingURL=webhook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../../src/openclaw/webhook.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,WAAW,CAC/B,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,OAAO,CAAC,cAAc,CAAM,GACpC,OAAO,CAAC,IAAI,CAAC,CAkCf;AAED,wBAAgB,mBAAmB,IAAI,OAAO,CAAC,OAAO,CAAC,CAItD"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * OpenClaw webhook integration.
3
+ *
4
+ * Sends messages to the OpenClaw local daemon for Telegram delivery.
5
+ * Handles ECONNREFUSED gracefully (OpenClaw not installed).
6
+ */
7
+ const OPENCLAW_URL = "http://127.0.0.1:18789";
8
+ export async function sendWebhook(message, options = {}) {
9
+ const payload = {
10
+ message,
11
+ name: options.name || "Orca Network",
12
+ sessionKey: options.sessionKey || "hook:orca",
13
+ deliver: options.deliver ?? true,
14
+ channel: options.channel || "telegram",
15
+ };
16
+ try {
17
+ const response = await fetch(`${OPENCLAW_URL}/hooks/agent`, {
18
+ method: "POST",
19
+ headers: {
20
+ "Content-Type": "application/json",
21
+ // Note: Authorization header would be added if hooks_token is configured
22
+ },
23
+ body: JSON.stringify(payload),
24
+ });
25
+ if (!response.ok) {
26
+ throw new Error(`Webhook failed: ${response.status}`);
27
+ }
28
+ }
29
+ catch (error) {
30
+ // Handle connection refused (OpenClaw not running)
31
+ if (error instanceof Error &&
32
+ (error.message.includes("ECONNREFUSED") ||
33
+ error.message.includes("fetch failed"))) {
34
+ console.log("OpenClaw not available, skipping Telegram delivery");
35
+ throw new Error("OpenClaw not available");
36
+ }
37
+ throw error;
38
+ }
39
+ }
40
+ export function isOpenClawAvailable() {
41
+ return fetch(`${OPENCLAW_URL}/health`)
42
+ .then((r) => r.ok)
43
+ .catch(() => false);
44
+ }
45
+ //# sourceMappingURL=webhook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../src/openclaw/webhook.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,YAAY,GAAG,wBAAwB,CAAC;AAU9C,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,OAAe,EACf,UAAmC,EAAE;IAErC,MAAM,OAAO,GAAmB;QAC9B,OAAO;QACP,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,cAAc;QACpC,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,WAAW;QAC7C,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,IAAI;QAChC,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,UAAU;KACvC,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,YAAY,cAAc,EAAE;YAC1D,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,yEAAyE;aAC1E;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;SAC9B,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,mBAAmB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QACxD,CAAC;IACH,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,mDAAmD;QACnD,IACE,KAAK,YAAY,KAAK;YACtB,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC;gBACrC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,EACzC,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAC;YAClE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC5C,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB;IACjC,OAAO,KAAK,CAAC,GAAG,YAAY,SAAS,CAAC;SACnC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACjB,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;AACxB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "orca-agent",
3
+ "version": "0.1.0",
4
+ "description": "Orca Network Agent CLI and Daemon",
5
+ "type": "module",
6
+ "bin": {
7
+ "orca-agent": "./dist/cli.js"
8
+ },
9
+ "main": "./dist/index.js",
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "dev": "tsc --watch",
13
+ "test": "NODE_OPTIONS='--experimental-vm-modules' jest",
14
+ "prepublishOnly": "npm run build"
15
+ },
16
+ "dependencies": {
17
+ "nats": "^2.19.0",
18
+ "commander": "^12.0.0",
19
+ "tweetnacl": "^1.0.3",
20
+ "bs58": "^5.0.0"
21
+ },
22
+ "devDependencies": {
23
+ "@types/node": "^20.11.0",
24
+ "typescript": "^5.3.0",
25
+ "jest": "^29.7.0",
26
+ "ts-jest": "^29.1.2",
27
+ "@types/jest": "^29.5.12"
28
+ },
29
+ "engines": {
30
+ "node": ">=22.0.0"
31
+ },
32
+ "files": [
33
+ "dist"
34
+ ]
35
+ }