freeturtle 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 (135) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +392 -0
  3. package/dist/bin/freeturtle.d.ts +2 -0
  4. package/dist/bin/freeturtle.js +119 -0
  5. package/dist/bin/freeturtle.js.map +1 -0
  6. package/dist/src/approval.d.ts +38 -0
  7. package/dist/src/approval.js +140 -0
  8. package/dist/src/approval.js.map +1 -0
  9. package/dist/src/audit.d.ts +33 -0
  10. package/dist/src/audit.js +36 -0
  11. package/dist/src/audit.js.map +1 -0
  12. package/dist/src/channels/telegram.d.ts +10 -0
  13. package/dist/src/channels/telegram.js +41 -0
  14. package/dist/src/channels/telegram.js.map +1 -0
  15. package/dist/src/channels/terminal.d.ts +9 -0
  16. package/dist/src/channels/terminal.js +52 -0
  17. package/dist/src/channels/terminal.js.map +1 -0
  18. package/dist/src/channels/types.d.ts +6 -0
  19. package/dist/src/channels/types.js +2 -0
  20. package/dist/src/channels/types.js.map +1 -0
  21. package/dist/src/cli/approvals.d.ts +3 -0
  22. package/dist/src/cli/approvals.js +33 -0
  23. package/dist/src/cli/approvals.js.map +1 -0
  24. package/dist/src/cli/connect-farcaster.d.ts +5 -0
  25. package/dist/src/cli/connect-farcaster.js +265 -0
  26. package/dist/src/cli/connect-farcaster.js.map +1 -0
  27. package/dist/src/cli/connection-tests.d.ts +16 -0
  28. package/dist/src/cli/connection-tests.js +65 -0
  29. package/dist/src/cli/connection-tests.js.map +1 -0
  30. package/dist/src/cli/init.d.ts +1 -0
  31. package/dist/src/cli/init.js +729 -0
  32. package/dist/src/cli/init.js.map +1 -0
  33. package/dist/src/cli/install-service.d.ts +1 -0
  34. package/dist/src/cli/install-service.js +57 -0
  35. package/dist/src/cli/install-service.js.map +1 -0
  36. package/dist/src/cli/intake.d.ts +23 -0
  37. package/dist/src/cli/intake.js +68 -0
  38. package/dist/src/cli/intake.js.map +1 -0
  39. package/dist/src/cli/send.d.ts +1 -0
  40. package/dist/src/cli/send.js +16 -0
  41. package/dist/src/cli/send.js.map +1 -0
  42. package/dist/src/cli/start.d.ts +3 -0
  43. package/dist/src/cli/start.js +25 -0
  44. package/dist/src/cli/start.js.map +1 -0
  45. package/dist/src/cli/status.d.ts +2 -0
  46. package/dist/src/cli/status.js +54 -0
  47. package/dist/src/cli/status.js.map +1 -0
  48. package/dist/src/cli/update.d.ts +1 -0
  49. package/dist/src/cli/update.js +39 -0
  50. package/dist/src/cli/update.js.map +1 -0
  51. package/dist/src/config.d.ts +31 -0
  52. package/dist/src/config.js +93 -0
  53. package/dist/src/config.js.map +1 -0
  54. package/dist/src/daemon.d.ts +18 -0
  55. package/dist/src/daemon.js +272 -0
  56. package/dist/src/daemon.js.map +1 -0
  57. package/dist/src/heartbeat.d.ts +17 -0
  58. package/dist/src/heartbeat.js +60 -0
  59. package/dist/src/heartbeat.js.map +1 -0
  60. package/dist/src/llm.d.ts +29 -0
  61. package/dist/src/llm.js +225 -0
  62. package/dist/src/llm.js.map +1 -0
  63. package/dist/src/logger.d.ts +8 -0
  64. package/dist/src/logger.js +45 -0
  65. package/dist/src/logger.js.map +1 -0
  66. package/dist/src/memory.d.ts +3 -0
  67. package/dist/src/memory.js +36 -0
  68. package/dist/src/memory.js.map +1 -0
  69. package/dist/src/modules/database/client.d.ts +18 -0
  70. package/dist/src/modules/database/client.js +50 -0
  71. package/dist/src/modules/database/client.js.map +1 -0
  72. package/dist/src/modules/database/index.d.ts +9 -0
  73. package/dist/src/modules/database/index.js +32 -0
  74. package/dist/src/modules/database/index.js.map +1 -0
  75. package/dist/src/modules/database/tools.d.ts +2 -0
  76. package/dist/src/modules/database/tools.js +26 -0
  77. package/dist/src/modules/database/tools.js.map +1 -0
  78. package/dist/src/modules/farcaster/client.d.ts +43 -0
  79. package/dist/src/modules/farcaster/client.js +87 -0
  80. package/dist/src/modules/farcaster/client.js.map +1 -0
  81. package/dist/src/modules/farcaster/index.d.ts +14 -0
  82. package/dist/src/modules/farcaster/index.js +71 -0
  83. package/dist/src/modules/farcaster/index.js.map +1 -0
  84. package/dist/src/modules/farcaster/tools.d.ts +2 -0
  85. package/dist/src/modules/farcaster/tools.js +90 -0
  86. package/dist/src/modules/farcaster/tools.js.map +1 -0
  87. package/dist/src/modules/github/client.d.ts +21 -0
  88. package/dist/src/modules/github/client.js +80 -0
  89. package/dist/src/modules/github/client.js.map +1 -0
  90. package/dist/src/modules/github/index.d.ts +13 -0
  91. package/dist/src/modules/github/index.js +45 -0
  92. package/dist/src/modules/github/index.js.map +1 -0
  93. package/dist/src/modules/github/tools.d.ts +2 -0
  94. package/dist/src/modules/github/tools.js +74 -0
  95. package/dist/src/modules/github/tools.js.map +1 -0
  96. package/dist/src/modules/loader.d.ts +5 -0
  97. package/dist/src/modules/loader.js +35 -0
  98. package/dist/src/modules/loader.js.map +1 -0
  99. package/dist/src/modules/onchain/client.d.ts +8 -0
  100. package/dist/src/modules/onchain/client.js +46 -0
  101. package/dist/src/modules/onchain/client.js.map +1 -0
  102. package/dist/src/modules/onchain/index.d.ts +13 -0
  103. package/dist/src/modules/onchain/index.js +40 -0
  104. package/dist/src/modules/onchain/index.js.map +1 -0
  105. package/dist/src/modules/onchain/tools.d.ts +2 -0
  106. package/dist/src/modules/onchain/tools.js +61 -0
  107. package/dist/src/modules/onchain/tools.js.map +1 -0
  108. package/dist/src/modules/types.d.ts +24 -0
  109. package/dist/src/modules/types.js +2 -0
  110. package/dist/src/modules/types.js.map +1 -0
  111. package/dist/src/modules/xmtp/index.d.ts +8 -0
  112. package/dist/src/modules/xmtp/index.js +14 -0
  113. package/dist/src/modules/xmtp/index.js.map +1 -0
  114. package/dist/src/policy.d.ts +45 -0
  115. package/dist/src/policy.js +164 -0
  116. package/dist/src/policy.js.map +1 -0
  117. package/dist/src/redaction.d.ts +13 -0
  118. package/dist/src/redaction.js +75 -0
  119. package/dist/src/redaction.js.map +1 -0
  120. package/dist/src/reliability.d.ts +16 -0
  121. package/dist/src/reliability.js +124 -0
  122. package/dist/src/reliability.js.map +1 -0
  123. package/dist/src/runner.d.ts +37 -0
  124. package/dist/src/runner.js +257 -0
  125. package/dist/src/runner.js.map +1 -0
  126. package/dist/src/scheduler.d.ts +22 -0
  127. package/dist/src/scheduler.js +61 -0
  128. package/dist/src/scheduler.js.map +1 -0
  129. package/dist/src/setup.d.ts +8 -0
  130. package/dist/src/setup.js +179 -0
  131. package/dist/src/setup.js.map +1 -0
  132. package/dist/src/soul.d.ts +1 -0
  133. package/dist/src/soul.js +15 -0
  134. package/dist/src/soul.js.map +1 -0
  135. package/package.json +56 -0
@@ -0,0 +1,272 @@
1
+ import { writeFile, unlink } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import net from "node:net";
4
+ import { config as loadDotenv } from "dotenv";
5
+ import { loadConfig } from "./config.js";
6
+ import { LLMClient } from "./llm.js";
7
+ import { loadModules } from "./modules/loader.js";
8
+ import { TaskRunner } from "./runner.js";
9
+ import { Scheduler } from "./scheduler.js";
10
+ import { Heartbeat } from "./heartbeat.js";
11
+ import { TerminalChannel } from "./channels/terminal.js";
12
+ import { TelegramChannel } from "./channels/telegram.js";
13
+ import { createLogger } from "./logger.js";
14
+ export class FreeTurtleDaemon {
15
+ dir;
16
+ options;
17
+ logger;
18
+ scheduler;
19
+ heartbeat;
20
+ channels = [];
21
+ runner;
22
+ ipcServer;
23
+ constructor(dir, options = {}) {
24
+ this.dir = dir;
25
+ this.options = options;
26
+ this.logger = createLogger(dir);
27
+ }
28
+ async start() {
29
+ // Load .env from workspace
30
+ loadDotenv({ path: join(this.dir, ".env") });
31
+ const env = process.env;
32
+ // Load config
33
+ const config = await loadConfig(this.dir);
34
+ this.logger.info("Config loaded");
35
+ // Create LLM client
36
+ const provider = (config.llm.provider ?? "claude_api");
37
+ const isOAuth = provider.endsWith("subscription");
38
+ const credEnvName = isOAuth
39
+ ? config.llm.oauth_token_env
40
+ : config.llm.api_key_env;
41
+ const credField = isOAuth ? "oauthToken" : "apiKey";
42
+ // Try config-specified env var first, then fall back to well-known names
43
+ const FALLBACK_ENV = {
44
+ claude_api: "ANTHROPIC_API_KEY",
45
+ claude_subscription: "ANTHROPIC_AUTH_TOKEN",
46
+ openai_api: "OPENAI_API_KEY",
47
+ openai_subscription: "OPENAI_OAUTH_TOKEN",
48
+ openrouter: "OPENROUTER_API_KEY",
49
+ };
50
+ const credential = (credEnvName ? env[credEnvName] : undefined) ??
51
+ env[FALLBACK_ENV[provider]];
52
+ if (!credential) {
53
+ throw new Error(`Missing credential: set ${credEnvName ?? FALLBACK_ENV[provider]} in .env`);
54
+ }
55
+ const llm = new LLMClient({
56
+ provider,
57
+ model: config.llm.model,
58
+ [credField]: credential,
59
+ baseUrl: config.llm.base_url,
60
+ });
61
+ this.logger.info(`LLM: ${provider} / ${config.llm.model}`);
62
+ // Load modules (pass policy for allowlist enforcement)
63
+ const modules = await loadModules(config, env, this.logger, config.policy);
64
+ this.logger.info(`Modules: ${modules.map((m) => m.name).join(", ") || "none"}`);
65
+ // Create runner with policy and approval notifications
66
+ this.runner = new TaskRunner(this.dir, llm, modules, this.logger, {
67
+ policy: config.policy,
68
+ onApprovalNeeded: (msg) => {
69
+ this.logger.info(`Approval notification: ${msg.slice(0, 100)}`);
70
+ for (const ch of this.channels) {
71
+ ch.send(msg).catch((err) => {
72
+ this.logger.error(`Failed to send approval notification via ${ch.name}: ${err}`);
73
+ });
74
+ }
75
+ },
76
+ });
77
+ // Start scheduler
78
+ if (Object.keys(config.cron).length > 0) {
79
+ this.scheduler = new Scheduler(config.cron, this.runner, this.logger);
80
+ this.scheduler.start();
81
+ }
82
+ // Start heartbeat — send alerts to all active channels
83
+ this.heartbeat = new Heartbeat(this.runner, this.logger, {
84
+ onAlert: (msg) => {
85
+ for (const ch of this.channels) {
86
+ ch.send(msg).catch((err) => {
87
+ this.logger.error(`Failed to send alert via ${ch.name}: ${err}`);
88
+ });
89
+ }
90
+ },
91
+ });
92
+ this.heartbeat.start();
93
+ // Start channels
94
+ const onMessage = async (text) => {
95
+ return this.runner.runMessage(text, "channel");
96
+ };
97
+ if (this.options.chat) {
98
+ const terminal = new TerminalChannel();
99
+ this.channels.push(terminal);
100
+ await terminal.start(onMessage);
101
+ }
102
+ if (config.channels.telegram?.enabled) {
103
+ const token = env.TELEGRAM_BOT_TOKEN;
104
+ const ownerId = env.TELEGRAM_OWNER_ID;
105
+ if (token && ownerId) {
106
+ const telegram = new TelegramChannel(token, parseInt(ownerId, 10));
107
+ this.channels.push(telegram);
108
+ await telegram.start(onMessage);
109
+ this.logger.info("Telegram channel started");
110
+ }
111
+ else {
112
+ this.logger.warn("Telegram enabled but TELEGRAM_BOT_TOKEN or TELEGRAM_OWNER_ID missing");
113
+ }
114
+ }
115
+ // Write PID file
116
+ const pidPath = join(this.dir, "daemon.pid");
117
+ await writeFile(pidPath, String(process.pid), "utf-8");
118
+ // Start IPC server
119
+ await this.startIpc();
120
+ // Signal handlers
121
+ const shutdown = async () => {
122
+ this.logger.info("Shutting down...");
123
+ await this.stop();
124
+ process.exit(0);
125
+ };
126
+ process.on("SIGINT", () => void shutdown());
127
+ process.on("SIGTERM", () => void shutdown());
128
+ process.on("uncaughtException", (err) => {
129
+ this.logger.error(`Uncaught exception: ${err.message}`);
130
+ });
131
+ this.logger.info("FreeTurtle is running");
132
+ const moduleNames = modules.map((m) => m.name).join(", ") || "none";
133
+ const channelNames = this.channels.map((c) => c.name).join(", ") || "none";
134
+ const cronCount = Object.keys(config.cron).length;
135
+ console.log(`
136
+ \x1b[38;2;94;255;164m _____ ____\x1b[0m
137
+ \x1b[38;2;94;255;164m / \\ | o |\x1b[0m
138
+ \x1b[38;2;94;255;164m| |/ ___\\|\x1b[0m
139
+ \x1b[38;2;94;255;164m|_________/\x1b[0m
140
+ \x1b[38;2;94;255;164m|_|_| |_|_|\x1b[0m
141
+
142
+ \x1b[1mPID ${process.pid}\x1b[0m — swimming along
143
+
144
+ Modules ${moduleNames}
145
+ Cron tasks ${cronCount}
146
+ Channels ${channelNames}
147
+
148
+ \x1b[2mfreeturtle send "message" — talk to your CEO\x1b[0m
149
+ \x1b[2mfreeturtle start --chat — interactive mode\x1b[0m
150
+ \x1b[2mfreeturtle status — check on things\x1b[0m
151
+ \x1b[2mCtrl+C — stop\x1b[0m
152
+ `);
153
+ }
154
+ async stop() {
155
+ this.scheduler?.stop();
156
+ this.heartbeat?.stop();
157
+ for (const ch of this.channels) {
158
+ await ch.stop();
159
+ }
160
+ this.ipcServer?.close();
161
+ // Remove PID file
162
+ try {
163
+ await unlink(join(this.dir, "daemon.pid"));
164
+ }
165
+ catch {
166
+ // ignore
167
+ }
168
+ // Remove socket
169
+ try {
170
+ await unlink(join(this.dir, "daemon.sock"));
171
+ }
172
+ catch {
173
+ // ignore
174
+ }
175
+ this.logger.info("FreeTurtle stopped");
176
+ }
177
+ async startIpc() {
178
+ const sockPath = join(this.dir, "daemon.sock");
179
+ // Remove stale socket
180
+ try {
181
+ await unlink(sockPath);
182
+ }
183
+ catch {
184
+ // ignore
185
+ }
186
+ this.ipcServer = net.createServer((conn) => {
187
+ let data = "";
188
+ conn.on("data", (chunk) => {
189
+ data += chunk.toString();
190
+ });
191
+ conn.on("end", () => {
192
+ void this.handleIpc(data.trim()).then((response) => {
193
+ conn.write(response);
194
+ conn.end();
195
+ });
196
+ });
197
+ });
198
+ this.ipcServer.listen(sockPath);
199
+ this.logger.info(`IPC listening on ${sockPath}`);
200
+ }
201
+ async handleIpc(command) {
202
+ if (command === "status") {
203
+ const status = {
204
+ pid: process.pid,
205
+ uptime: process.uptime(),
206
+ scheduler: this.scheduler?.getStatus() ?? null,
207
+ channels: this.channels.map((c) => c.name),
208
+ };
209
+ return JSON.stringify(status, null, 2);
210
+ }
211
+ if (command.startsWith("send ")) {
212
+ const message = command.slice(5);
213
+ if (!this.runner)
214
+ return "Error: runner not initialized";
215
+ try {
216
+ const response = await this.runner.runMessage(message, "ipc");
217
+ return response;
218
+ }
219
+ catch (err) {
220
+ const msg = err instanceof Error ? err.message : "Unknown error";
221
+ this.logger.error(`IPC send failed: ${msg}`);
222
+ return `Error: ${msg}`;
223
+ }
224
+ }
225
+ if (command.startsWith("approve ")) {
226
+ const id = command.slice(8).trim();
227
+ if (!this.runner)
228
+ return "Error: runner not initialized";
229
+ try {
230
+ const req = await this.runner.getApprovalManager().approve(id, "ipc");
231
+ return JSON.stringify(req, null, 2);
232
+ }
233
+ catch (err) {
234
+ return `Error: ${err instanceof Error ? err.message : "unknown"}`;
235
+ }
236
+ }
237
+ if (command.startsWith("reject ")) {
238
+ const parts = command.slice(7).trim();
239
+ const spaceIdx = parts.indexOf(" ");
240
+ const id = spaceIdx > -1 ? parts.slice(0, spaceIdx) : parts;
241
+ const reason = spaceIdx > -1 ? parts.slice(spaceIdx + 1) : undefined;
242
+ if (!this.runner)
243
+ return "Error: runner not initialized";
244
+ try {
245
+ const req = await this.runner.getApprovalManager().reject(id, reason, "ipc");
246
+ return JSON.stringify(req, null, 2);
247
+ }
248
+ catch (err) {
249
+ return `Error: ${err instanceof Error ? err.message : "unknown"}`;
250
+ }
251
+ }
252
+ if (command === "approvals") {
253
+ if (!this.runner)
254
+ return "Error: runner not initialized";
255
+ try {
256
+ const pending = await this.runner.getApprovalManager().list("pending");
257
+ if (pending.length === 0)
258
+ return "No pending approvals.";
259
+ return JSON.stringify(pending, null, 2);
260
+ }
261
+ catch (err) {
262
+ return `Error: ${err instanceof Error ? err.message : "unknown"}`;
263
+ }
264
+ }
265
+ if (command === "stop") {
266
+ void this.stop().then(() => process.exit(0));
267
+ return "Stopping...";
268
+ }
269
+ return `Unknown command: ${command}`;
270
+ }
271
+ }
272
+ //# sourceMappingURL=daemon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../../src/daemon.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { TaskRunner } from "./runner.js";
2
+ import type { Logger } from "./logger.js";
3
+ export declare class Heartbeat {
4
+ private interval;
5
+ private timer;
6
+ private runner;
7
+ private logger;
8
+ private onAlert?;
9
+ private running;
10
+ constructor(runner: TaskRunner, logger: Logger, options?: {
11
+ intervalMs?: number;
12
+ onAlert?: (message: string) => void;
13
+ });
14
+ start(): void;
15
+ stop(): void;
16
+ private tick;
17
+ }
@@ -0,0 +1,60 @@
1
+ export class Heartbeat {
2
+ interval;
3
+ timer = null;
4
+ runner;
5
+ logger;
6
+ onAlert;
7
+ running = false;
8
+ constructor(runner, logger, options) {
9
+ this.runner = runner;
10
+ this.logger = logger;
11
+ this.interval = options?.intervalMs ?? 30 * 60 * 1000;
12
+ this.onAlert = options?.onAlert;
13
+ }
14
+ start() {
15
+ this.logger.info(`Heartbeat started (every ${Math.round(this.interval / 1000)}s)`);
16
+ this.timer = setInterval(() => {
17
+ void this.tick();
18
+ }, this.interval);
19
+ }
20
+ stop() {
21
+ if (this.timer) {
22
+ clearInterval(this.timer);
23
+ this.timer = null;
24
+ }
25
+ this.logger.info("Heartbeat stopped");
26
+ }
27
+ async tick() {
28
+ if (this.running) {
29
+ this.logger.warn("Skipping heartbeat — previous tick still running");
30
+ return;
31
+ }
32
+ this.running = true;
33
+ try {
34
+ this.logger.info("Heartbeat tick");
35
+ const result = await this.runner.runTask({
36
+ name: "heartbeat",
37
+ prompt: "This is a scheduled heartbeat check. Review your heartbeat checklist. " +
38
+ "If everything looks fine, respond with exactly HEARTBEAT_OK. " +
39
+ "If something needs attention, describe what you found.",
40
+ isHeartbeat: true,
41
+ });
42
+ const text = result.response.trim();
43
+ if (text === "HEARTBEAT_OK" || text.includes("HEARTBEAT_OK")) {
44
+ this.logger.info("Heartbeat: all clear");
45
+ }
46
+ else {
47
+ this.logger.info("Heartbeat: alert raised");
48
+ this.onAlert?.(text);
49
+ }
50
+ }
51
+ catch (err) {
52
+ const msg = err instanceof Error ? err.message : "Unknown error";
53
+ this.logger.error(`Heartbeat failed: ${msg}`);
54
+ }
55
+ finally {
56
+ this.running = false;
57
+ }
58
+ }
59
+ }
60
+ //# sourceMappingURL=heartbeat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heartbeat.js","sourceRoot":"","sources":["../../src/heartbeat.ts"],"names":[],"mappings":"AAGA,MAAM,OAAO,SAAS;IACZ,QAAQ,CAAS;IACjB,KAAK,GAA0C,IAAI,CAAC;IACpD,MAAM,CAAa;IACnB,MAAM,CAAS;IACf,OAAO,CAA6B;IACpC,OAAO,GAAG,KAAK,CAAC;IAExB,YACE,MAAkB,EAClB,MAAc,EACd,OAGC;QAED,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,QAAQ,GAAG,OAAO,EAAE,UAAU,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;QACtD,IAAI,CAAC,OAAO,GAAG,OAAO,EAAE,OAAO,CAAC;IAClC,CAAC;IAED,KAAK;QACH,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,4BAA4B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,IAAI,CACjE,CAAC;QAEF,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;YAC5B,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;QACnB,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IACpB,CAAC;IAED,IAAI;QACF,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACpB,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IACxC,CAAC;IAEO,KAAK,CAAC,IAAI;QAChB,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;YACrE,OAAO;QACT,CAAC;QAED,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC;YACH,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YACnC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;gBACvC,IAAI,EAAE,WAAW;gBACjB,MAAM,EACJ,wEAAwE;oBACxE,+DAA+D;oBAC/D,wDAAwD;gBAC1D,WAAW,EAAE,IAAI;aAClB,CAAC,CAAC;YAEH,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACpC,IAAI,IAAI,KAAK,cAAc,IAAI,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;gBAC7D,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;YAC3C,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;gBAC5C,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YACjE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,GAAG,EAAE,CAAC,CAAC;QAChD,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACvB,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,29 @@
1
+ import Anthropic from "@anthropic-ai/sdk";
2
+ import OpenAI from "openai";
3
+ import type { ToolDefinition, ToolCall, ToolExecutor } from "./modules/types.js";
4
+ export type LLMProvider = "claude_api" | "claude_subscription" | "openai_api" | "openai_subscription" | "openrouter";
5
+ export interface LLMClientOptions {
6
+ provider: LLMProvider;
7
+ model: string;
8
+ apiKey?: string;
9
+ oauthToken?: string;
10
+ baseUrl?: string;
11
+ }
12
+ export interface LLMResponse {
13
+ text: string;
14
+ tool_calls: ToolCall[];
15
+ }
16
+ export declare class LLMClient {
17
+ private provider;
18
+ private model;
19
+ private mode;
20
+ private anthropic?;
21
+ private openai?;
22
+ constructor(options: LLMClientOptions);
23
+ chat(systemPrompt: string, messages: Anthropic.MessageParam[] | OpenAI.ChatCompletionMessageParam[], tools?: ToolDefinition[]): Promise<LLMResponse>;
24
+ agentLoop(systemPrompt: string, userPrompt: string, tools: ToolDefinition[], toolExecutor: ToolExecutor): Promise<string>;
25
+ private chatAnthropic;
26
+ private agentLoopAnthropic;
27
+ private chatOpenAI;
28
+ private agentLoopOpenAI;
29
+ }
@@ -0,0 +1,225 @@
1
+ import Anthropic from "@anthropic-ai/sdk";
2
+ import OpenAI from "openai";
3
+ export class LLMClient {
4
+ provider;
5
+ model;
6
+ mode;
7
+ anthropic;
8
+ openai;
9
+ constructor(options) {
10
+ this.mode = options.provider;
11
+ this.provider = this.mode.startsWith("claude") ? "anthropic" : "openai";
12
+ this.model = options.model;
13
+ if (this.mode === "claude_api") {
14
+ if (!options.apiKey) {
15
+ throw new Error("LLMClient missing required credential: apiKey");
16
+ }
17
+ this.anthropic = new Anthropic({
18
+ apiKey: options.apiKey,
19
+ baseURL: options.baseUrl,
20
+ });
21
+ return;
22
+ }
23
+ if (this.mode === "claude_subscription") {
24
+ if (!options.oauthToken) {
25
+ throw new Error("LLMClient missing required credential: oauthToken");
26
+ }
27
+ this.anthropic = new Anthropic({
28
+ authToken: options.oauthToken,
29
+ baseURL: options.baseUrl,
30
+ });
31
+ return;
32
+ }
33
+ if (this.mode === "openai_api") {
34
+ if (!options.apiKey) {
35
+ throw new Error("LLMClient missing required credential: apiKey");
36
+ }
37
+ this.openai = new OpenAI({
38
+ apiKey: options.apiKey,
39
+ baseURL: options.baseUrl,
40
+ });
41
+ return;
42
+ }
43
+ if (this.mode === "openai_subscription") {
44
+ if (!options.oauthToken) {
45
+ throw new Error("LLMClient missing required credential: oauthToken");
46
+ }
47
+ this.openai = new OpenAI({
48
+ // OpenAI SDK uses bearer auth via apiKey; OAuth access tokens also work here.
49
+ apiKey: options.oauthToken,
50
+ baseURL: options.baseUrl,
51
+ });
52
+ return;
53
+ }
54
+ // openrouter
55
+ if (!options.apiKey) {
56
+ throw new Error("LLMClient missing required credential: apiKey");
57
+ }
58
+ this.openai = new OpenAI({
59
+ apiKey: options.apiKey,
60
+ baseURL: options.baseUrl ?? "https://openrouter.ai/api/v1",
61
+ });
62
+ }
63
+ async chat(systemPrompt, messages, tools) {
64
+ if (this.provider === "anthropic") {
65
+ return this.chatAnthropic(systemPrompt, messages, tools);
66
+ }
67
+ return this.chatOpenAI(systemPrompt, messages, tools);
68
+ }
69
+ async agentLoop(systemPrompt, userPrompt, tools, toolExecutor) {
70
+ if (this.provider === "anthropic") {
71
+ return this.agentLoopAnthropic(systemPrompt, userPrompt, tools, toolExecutor);
72
+ }
73
+ return this.agentLoopOpenAI(systemPrompt, userPrompt, tools, toolExecutor);
74
+ }
75
+ // --- Anthropic implementation ---
76
+ async chatAnthropic(systemPrompt, messages, tools) {
77
+ const response = await this.anthropic.messages.create({
78
+ model: this.model,
79
+ max_tokens: 4096,
80
+ system: systemPrompt,
81
+ messages,
82
+ ...(tools?.length
83
+ ? {
84
+ tools: tools.map((t) => ({
85
+ name: t.name,
86
+ description: t.description,
87
+ input_schema: t.input_schema,
88
+ })),
89
+ }
90
+ : {}),
91
+ });
92
+ let text = "";
93
+ const toolCalls = [];
94
+ for (const block of response.content) {
95
+ if (block.type === "text") {
96
+ text += block.text;
97
+ }
98
+ else if (block.type === "tool_use") {
99
+ toolCalls.push({
100
+ id: block.id,
101
+ name: block.name,
102
+ input: block.input,
103
+ });
104
+ }
105
+ }
106
+ return { text, tool_calls: toolCalls };
107
+ }
108
+ async agentLoopAnthropic(systemPrompt, userPrompt, tools, toolExecutor) {
109
+ const MAX_ITERATIONS = 25;
110
+ const messages = [
111
+ { role: "user", content: userPrompt },
112
+ ];
113
+ for (let i = 0; i < MAX_ITERATIONS; i++) {
114
+ const response = await this.chatAnthropic(systemPrompt, messages, tools);
115
+ if (response.tool_calls.length === 0) {
116
+ return response.text;
117
+ }
118
+ // Build assistant content blocks
119
+ const assistantContent = [];
120
+ if (response.text) {
121
+ assistantContent.push({ type: "text", text: response.text });
122
+ }
123
+ for (const tc of response.tool_calls) {
124
+ assistantContent.push({
125
+ type: "tool_use",
126
+ id: tc.id,
127
+ name: tc.name,
128
+ input: tc.input,
129
+ });
130
+ }
131
+ messages.push({ role: "assistant", content: assistantContent });
132
+ // Execute tools and build results
133
+ const toolResults = [];
134
+ for (const tc of response.tool_calls) {
135
+ const result = await toolExecutor(tc);
136
+ toolResults.push({
137
+ type: "tool_result",
138
+ tool_use_id: tc.id,
139
+ content: result,
140
+ });
141
+ }
142
+ messages.push({ role: "user", content: toolResults });
143
+ }
144
+ // If we hit the limit, return whatever text we have
145
+ const last = await this.chatAnthropic(systemPrompt, messages, []);
146
+ return last.text || "(Agent reached maximum tool call iterations)";
147
+ }
148
+ // --- OpenAI implementation ---
149
+ async chatOpenAI(systemPrompt, messages, tools) {
150
+ const response = await this.openai.chat.completions.create({
151
+ model: this.model,
152
+ messages: [
153
+ { role: "system", content: systemPrompt },
154
+ ...messages,
155
+ ],
156
+ ...(tools?.length
157
+ ? {
158
+ tools: tools.map((t) => ({
159
+ type: "function",
160
+ function: {
161
+ name: t.name,
162
+ description: t.description,
163
+ parameters: t.input_schema,
164
+ },
165
+ })),
166
+ }
167
+ : {}),
168
+ });
169
+ const choice = response.choices[0];
170
+ const message = choice.message;
171
+ const text = message.content ?? "";
172
+ const toolCalls = [];
173
+ if (message.tool_calls) {
174
+ for (const tc of message.tool_calls) {
175
+ if (tc.type === "function") {
176
+ toolCalls.push({
177
+ id: tc.id,
178
+ name: tc.function.name,
179
+ input: JSON.parse(tc.function.arguments),
180
+ });
181
+ }
182
+ }
183
+ }
184
+ return { text, tool_calls: toolCalls };
185
+ }
186
+ async agentLoopOpenAI(systemPrompt, userPrompt, tools, toolExecutor) {
187
+ const MAX_ITERATIONS = 25;
188
+ const messages = [
189
+ { role: "user", content: userPrompt },
190
+ ];
191
+ for (let i = 0; i < MAX_ITERATIONS; i++) {
192
+ const response = await this.chatOpenAI(systemPrompt, messages, tools);
193
+ if (response.tool_calls.length === 0) {
194
+ return response.text;
195
+ }
196
+ // Build assistant message with tool calls
197
+ const assistantMessage = {
198
+ role: "assistant",
199
+ content: response.text || null,
200
+ tool_calls: response.tool_calls.map((tc) => ({
201
+ id: tc.id,
202
+ type: "function",
203
+ function: {
204
+ name: tc.name,
205
+ arguments: JSON.stringify(tc.input),
206
+ },
207
+ })),
208
+ };
209
+ messages.push(assistantMessage);
210
+ // Execute tools and append results
211
+ for (const tc of response.tool_calls) {
212
+ const result = await toolExecutor(tc);
213
+ messages.push({
214
+ role: "tool",
215
+ tool_call_id: tc.id,
216
+ content: result,
217
+ });
218
+ }
219
+ }
220
+ // If we hit the limit, return whatever text we have
221
+ const last = await this.chatOpenAI(systemPrompt, messages, []);
222
+ return last.text || "(Agent reached maximum tool call iterations)";
223
+ }
224
+ }
225
+ //# sourceMappingURL=llm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm.js","sourceRoot":"","sources":["../../src/llm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export type LogLevel = "debug" | "info" | "warn" | "error";
2
+ export interface Logger {
3
+ debug(msg: string): void;
4
+ info(msg: string): void;
5
+ warn(msg: string): void;
6
+ error(msg: string): void;
7
+ }
8
+ export declare function createLogger(dir?: string): Logger;