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.
- package/LICENSE +190 -0
- package/README.md +392 -0
- package/dist/bin/freeturtle.d.ts +2 -0
- package/dist/bin/freeturtle.js +119 -0
- package/dist/bin/freeturtle.js.map +1 -0
- package/dist/src/approval.d.ts +38 -0
- package/dist/src/approval.js +140 -0
- package/dist/src/approval.js.map +1 -0
- package/dist/src/audit.d.ts +33 -0
- package/dist/src/audit.js +36 -0
- package/dist/src/audit.js.map +1 -0
- package/dist/src/channels/telegram.d.ts +10 -0
- package/dist/src/channels/telegram.js +41 -0
- package/dist/src/channels/telegram.js.map +1 -0
- package/dist/src/channels/terminal.d.ts +9 -0
- package/dist/src/channels/terminal.js +52 -0
- package/dist/src/channels/terminal.js.map +1 -0
- package/dist/src/channels/types.d.ts +6 -0
- package/dist/src/channels/types.js +2 -0
- package/dist/src/channels/types.js.map +1 -0
- package/dist/src/cli/approvals.d.ts +3 -0
- package/dist/src/cli/approvals.js +33 -0
- package/dist/src/cli/approvals.js.map +1 -0
- package/dist/src/cli/connect-farcaster.d.ts +5 -0
- package/dist/src/cli/connect-farcaster.js +265 -0
- package/dist/src/cli/connect-farcaster.js.map +1 -0
- package/dist/src/cli/connection-tests.d.ts +16 -0
- package/dist/src/cli/connection-tests.js +65 -0
- package/dist/src/cli/connection-tests.js.map +1 -0
- package/dist/src/cli/init.d.ts +1 -0
- package/dist/src/cli/init.js +729 -0
- package/dist/src/cli/init.js.map +1 -0
- package/dist/src/cli/install-service.d.ts +1 -0
- package/dist/src/cli/install-service.js +57 -0
- package/dist/src/cli/install-service.js.map +1 -0
- package/dist/src/cli/intake.d.ts +23 -0
- package/dist/src/cli/intake.js +68 -0
- package/dist/src/cli/intake.js.map +1 -0
- package/dist/src/cli/send.d.ts +1 -0
- package/dist/src/cli/send.js +16 -0
- package/dist/src/cli/send.js.map +1 -0
- package/dist/src/cli/start.d.ts +3 -0
- package/dist/src/cli/start.js +25 -0
- package/dist/src/cli/start.js.map +1 -0
- package/dist/src/cli/status.d.ts +2 -0
- package/dist/src/cli/status.js +54 -0
- package/dist/src/cli/status.js.map +1 -0
- package/dist/src/cli/update.d.ts +1 -0
- package/dist/src/cli/update.js +39 -0
- package/dist/src/cli/update.js.map +1 -0
- package/dist/src/config.d.ts +31 -0
- package/dist/src/config.js +93 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/daemon.d.ts +18 -0
- package/dist/src/daemon.js +272 -0
- package/dist/src/daemon.js.map +1 -0
- package/dist/src/heartbeat.d.ts +17 -0
- package/dist/src/heartbeat.js +60 -0
- package/dist/src/heartbeat.js.map +1 -0
- package/dist/src/llm.d.ts +29 -0
- package/dist/src/llm.js +225 -0
- package/dist/src/llm.js.map +1 -0
- package/dist/src/logger.d.ts +8 -0
- package/dist/src/logger.js +45 -0
- package/dist/src/logger.js.map +1 -0
- package/dist/src/memory.d.ts +3 -0
- package/dist/src/memory.js +36 -0
- package/dist/src/memory.js.map +1 -0
- package/dist/src/modules/database/client.d.ts +18 -0
- package/dist/src/modules/database/client.js +50 -0
- package/dist/src/modules/database/client.js.map +1 -0
- package/dist/src/modules/database/index.d.ts +9 -0
- package/dist/src/modules/database/index.js +32 -0
- package/dist/src/modules/database/index.js.map +1 -0
- package/dist/src/modules/database/tools.d.ts +2 -0
- package/dist/src/modules/database/tools.js +26 -0
- package/dist/src/modules/database/tools.js.map +1 -0
- package/dist/src/modules/farcaster/client.d.ts +43 -0
- package/dist/src/modules/farcaster/client.js +87 -0
- package/dist/src/modules/farcaster/client.js.map +1 -0
- package/dist/src/modules/farcaster/index.d.ts +14 -0
- package/dist/src/modules/farcaster/index.js +71 -0
- package/dist/src/modules/farcaster/index.js.map +1 -0
- package/dist/src/modules/farcaster/tools.d.ts +2 -0
- package/dist/src/modules/farcaster/tools.js +90 -0
- package/dist/src/modules/farcaster/tools.js.map +1 -0
- package/dist/src/modules/github/client.d.ts +21 -0
- package/dist/src/modules/github/client.js +80 -0
- package/dist/src/modules/github/client.js.map +1 -0
- package/dist/src/modules/github/index.d.ts +13 -0
- package/dist/src/modules/github/index.js +45 -0
- package/dist/src/modules/github/index.js.map +1 -0
- package/dist/src/modules/github/tools.d.ts +2 -0
- package/dist/src/modules/github/tools.js +74 -0
- package/dist/src/modules/github/tools.js.map +1 -0
- package/dist/src/modules/loader.d.ts +5 -0
- package/dist/src/modules/loader.js +35 -0
- package/dist/src/modules/loader.js.map +1 -0
- package/dist/src/modules/onchain/client.d.ts +8 -0
- package/dist/src/modules/onchain/client.js +46 -0
- package/dist/src/modules/onchain/client.js.map +1 -0
- package/dist/src/modules/onchain/index.d.ts +13 -0
- package/dist/src/modules/onchain/index.js +40 -0
- package/dist/src/modules/onchain/index.js.map +1 -0
- package/dist/src/modules/onchain/tools.d.ts +2 -0
- package/dist/src/modules/onchain/tools.js +61 -0
- package/dist/src/modules/onchain/tools.js.map +1 -0
- package/dist/src/modules/types.d.ts +24 -0
- package/dist/src/modules/types.js +2 -0
- package/dist/src/modules/types.js.map +1 -0
- package/dist/src/modules/xmtp/index.d.ts +8 -0
- package/dist/src/modules/xmtp/index.js +14 -0
- package/dist/src/modules/xmtp/index.js.map +1 -0
- package/dist/src/policy.d.ts +45 -0
- package/dist/src/policy.js +164 -0
- package/dist/src/policy.js.map +1 -0
- package/dist/src/redaction.d.ts +13 -0
- package/dist/src/redaction.js +75 -0
- package/dist/src/redaction.js.map +1 -0
- package/dist/src/reliability.d.ts +16 -0
- package/dist/src/reliability.js +124 -0
- package/dist/src/reliability.js.map +1 -0
- package/dist/src/runner.d.ts +37 -0
- package/dist/src/runner.js +257 -0
- package/dist/src/runner.js.map +1 -0
- package/dist/src/scheduler.d.ts +22 -0
- package/dist/src/scheduler.js +61 -0
- package/dist/src/scheduler.js.map +1 -0
- package/dist/src/setup.d.ts +8 -0
- package/dist/src/setup.js +179 -0
- package/dist/src/setup.js.map +1 -0
- package/dist/src/soul.d.ts +1 -0
- package/dist/src/soul.js +15 -0
- package/dist/src/soul.js.map +1 -0
- package/package.json +56 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { Command } from "commander";
|
|
5
|
+
import { runInit } from "../src/cli/init.js";
|
|
6
|
+
import { runStart } from "../src/cli/start.js";
|
|
7
|
+
import { runStatus } from "../src/cli/status.js";
|
|
8
|
+
import { runSend } from "../src/cli/send.js";
|
|
9
|
+
import { runSetup } from "../src/setup.js";
|
|
10
|
+
import { connectFarcaster } from "../src/cli/connect-farcaster.js";
|
|
11
|
+
import { runInstallService } from "../src/cli/install-service.js";
|
|
12
|
+
import { runUpdate } from "../src/cli/update.js";
|
|
13
|
+
import { runApprove, runReject, runListApprovals, } from "../src/cli/approvals.js";
|
|
14
|
+
const DEFAULT_DIR = join(homedir(), ".freeturtle");
|
|
15
|
+
const program = new Command();
|
|
16
|
+
program
|
|
17
|
+
.name("freeturtle")
|
|
18
|
+
.description("An open-source framework for deploying autonomous AI CEOs that run onchain businesses.")
|
|
19
|
+
.version("0.1.0");
|
|
20
|
+
program
|
|
21
|
+
.command("hello")
|
|
22
|
+
.description("Verify the CLI is working")
|
|
23
|
+
.action(() => {
|
|
24
|
+
console.log(" \x1b[38;2;94;255;164m _____ ____\x1b[0m");
|
|
25
|
+
console.log(" \x1b[38;2;94;255;164m/ \\ | o |\x1b[0m");
|
|
26
|
+
console.log(" \x1b[38;2;94;255;164m| |/ ___\\|\x1b[0m FreeTurtle v0.1");
|
|
27
|
+
console.log(" \x1b[38;2;94;255;164m|_________/\x1b[0m");
|
|
28
|
+
console.log(" \x1b[38;2;94;255;164m|_|_| |_|_|\x1b[0m");
|
|
29
|
+
});
|
|
30
|
+
program
|
|
31
|
+
.command("init")
|
|
32
|
+
.description("Set up a new AI CEO")
|
|
33
|
+
.option("--dir <path>", "Workspace directory", DEFAULT_DIR)
|
|
34
|
+
.action(async (opts) => {
|
|
35
|
+
await runInit(opts.dir);
|
|
36
|
+
});
|
|
37
|
+
program
|
|
38
|
+
.command("setup")
|
|
39
|
+
.description("Configure your LLM provider and API key")
|
|
40
|
+
.option("--dir <path>", "Workspace directory", DEFAULT_DIR)
|
|
41
|
+
.action(async (opts) => {
|
|
42
|
+
await runSetup(opts.dir);
|
|
43
|
+
});
|
|
44
|
+
program
|
|
45
|
+
.command("start")
|
|
46
|
+
.description("Start the FreeTurtle daemon")
|
|
47
|
+
.option("--dir <path>", "Workspace directory", DEFAULT_DIR)
|
|
48
|
+
.option("--chat", "Open interactive terminal chat", false)
|
|
49
|
+
.action(async (opts) => {
|
|
50
|
+
await runStart(opts.dir, { chat: opts.chat });
|
|
51
|
+
});
|
|
52
|
+
program
|
|
53
|
+
.command("status")
|
|
54
|
+
.description("Show daemon status")
|
|
55
|
+
.option("--dir <path>", "Workspace directory", DEFAULT_DIR)
|
|
56
|
+
.action(async (opts) => {
|
|
57
|
+
try {
|
|
58
|
+
await runStatus(opts.dir);
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
if (err instanceof Error)
|
|
62
|
+
console.error(err.message);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
program
|
|
67
|
+
.command("send <message>")
|
|
68
|
+
.description("Send a message to the running CEO")
|
|
69
|
+
.option("--dir <path>", "Workspace directory", DEFAULT_DIR)
|
|
70
|
+
.action(async (message, opts) => {
|
|
71
|
+
await runSend(opts.dir, message);
|
|
72
|
+
});
|
|
73
|
+
program
|
|
74
|
+
.command("update")
|
|
75
|
+
.description("Update FreeTurtle to the latest version")
|
|
76
|
+
.action(async () => {
|
|
77
|
+
await runUpdate();
|
|
78
|
+
});
|
|
79
|
+
program
|
|
80
|
+
.command("install-service")
|
|
81
|
+
.description("Install FreeTurtle as a systemd user service (Linux)")
|
|
82
|
+
.option("--dir <path>", "Workspace directory", DEFAULT_DIR)
|
|
83
|
+
.action(async (opts) => {
|
|
84
|
+
await runInstallService(opts.dir);
|
|
85
|
+
});
|
|
86
|
+
program
|
|
87
|
+
.command("approve <id>")
|
|
88
|
+
.description("Approve a pending action")
|
|
89
|
+
.option("--dir <path>", "Workspace directory", DEFAULT_DIR)
|
|
90
|
+
.action(async (id, opts) => {
|
|
91
|
+
await runApprove(opts.dir, id);
|
|
92
|
+
});
|
|
93
|
+
program
|
|
94
|
+
.command("reject <id>")
|
|
95
|
+
.description("Reject a pending action")
|
|
96
|
+
.option("--dir <path>", "Workspace directory", DEFAULT_DIR)
|
|
97
|
+
.option("--reason <reason>", "Rejection reason")
|
|
98
|
+
.action(async (id, opts) => {
|
|
99
|
+
await runReject(opts.dir, id, opts.reason);
|
|
100
|
+
});
|
|
101
|
+
program
|
|
102
|
+
.command("approvals")
|
|
103
|
+
.description("List pending approval requests")
|
|
104
|
+
.option("--dir <path>", "Workspace directory", DEFAULT_DIR)
|
|
105
|
+
.action(async (opts) => {
|
|
106
|
+
await runListApprovals(opts.dir);
|
|
107
|
+
});
|
|
108
|
+
const connect = program
|
|
109
|
+
.command("connect")
|
|
110
|
+
.description("Connect external services");
|
|
111
|
+
connect
|
|
112
|
+
.command("farcaster")
|
|
113
|
+
.description("Set up Farcaster signer with QR code approval")
|
|
114
|
+
.option("--dir <path>", "Workspace directory", DEFAULT_DIR)
|
|
115
|
+
.action(async (opts) => {
|
|
116
|
+
await connectFarcaster(opts.dir);
|
|
117
|
+
});
|
|
118
|
+
program.parse();
|
|
119
|
+
//# sourceMappingURL=freeturtle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"freeturtle.js","sourceRoot":"","sources":["../../bin/freeturtle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export type ApprovalStatus = "pending" | "approved" | "rejected" | "expired";
|
|
2
|
+
export interface ApprovalRequest {
|
|
3
|
+
id: string;
|
|
4
|
+
runId: string;
|
|
5
|
+
toolName: string;
|
|
6
|
+
reason: string;
|
|
7
|
+
input: Record<string, unknown>;
|
|
8
|
+
status: ApprovalStatus;
|
|
9
|
+
createdAt: string;
|
|
10
|
+
decidedAt?: string;
|
|
11
|
+
decidedBy?: string;
|
|
12
|
+
rejectReason?: string;
|
|
13
|
+
expiresAt: string;
|
|
14
|
+
}
|
|
15
|
+
export declare class ApprovalManager {
|
|
16
|
+
private dir;
|
|
17
|
+
constructor(dir: string);
|
|
18
|
+
createRequest(opts: {
|
|
19
|
+
runId: string;
|
|
20
|
+
toolName: string;
|
|
21
|
+
reason: string;
|
|
22
|
+
input: Record<string, unknown>;
|
|
23
|
+
timeoutSeconds: number;
|
|
24
|
+
}): Promise<ApprovalRequest>;
|
|
25
|
+
/**
|
|
26
|
+
* Polls the approval file until the status changes from "pending" or the
|
|
27
|
+
* timeout elapses. Returns the final state of the approval request.
|
|
28
|
+
*/
|
|
29
|
+
waitForDecision(id: string, timeoutMs: number): Promise<ApprovalRequest>;
|
|
30
|
+
approve(id: string, decidedBy?: string): Promise<ApprovalRequest>;
|
|
31
|
+
reject(id: string, reason?: string, decidedBy?: string): Promise<ApprovalRequest>;
|
|
32
|
+
expire(id: string): Promise<ApprovalRequest>;
|
|
33
|
+
list(status?: ApprovalStatus): Promise<ApprovalRequest[]>;
|
|
34
|
+
get(id: string): Promise<ApprovalRequest | null>;
|
|
35
|
+
private save;
|
|
36
|
+
private load;
|
|
37
|
+
private approvalPath;
|
|
38
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile, readdir } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
4
|
+
const POLL_INTERVAL_MS = 2000;
|
|
5
|
+
export class ApprovalManager {
|
|
6
|
+
dir; // workspace/approvals/
|
|
7
|
+
constructor(dir) {
|
|
8
|
+
this.dir = join(dir, "workspace", "approvals");
|
|
9
|
+
}
|
|
10
|
+
async createRequest(opts) {
|
|
11
|
+
const now = new Date();
|
|
12
|
+
const expiresAt = new Date(now.getTime() + opts.timeoutSeconds * 1000);
|
|
13
|
+
const req = {
|
|
14
|
+
id: randomUUID(),
|
|
15
|
+
runId: opts.runId,
|
|
16
|
+
toolName: opts.toolName,
|
|
17
|
+
reason: opts.reason,
|
|
18
|
+
input: opts.input,
|
|
19
|
+
status: "pending",
|
|
20
|
+
createdAt: now.toISOString(),
|
|
21
|
+
expiresAt: expiresAt.toISOString(),
|
|
22
|
+
};
|
|
23
|
+
await this.save(req);
|
|
24
|
+
return req;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Polls the approval file until the status changes from "pending" or the
|
|
28
|
+
* timeout elapses. Returns the final state of the approval request.
|
|
29
|
+
*/
|
|
30
|
+
async waitForDecision(id, timeoutMs) {
|
|
31
|
+
const deadline = Date.now() + timeoutMs;
|
|
32
|
+
while (Date.now() < deadline) {
|
|
33
|
+
const req = await this.load(id);
|
|
34
|
+
if (!req) {
|
|
35
|
+
throw new Error(`Approval request ${id} not found`);
|
|
36
|
+
}
|
|
37
|
+
// Check if expired by time
|
|
38
|
+
if (new Date(req.expiresAt).getTime() <= Date.now() && req.status === "pending") {
|
|
39
|
+
return this.expire(id);
|
|
40
|
+
}
|
|
41
|
+
if (req.status !== "pending") {
|
|
42
|
+
return req;
|
|
43
|
+
}
|
|
44
|
+
// Wait before next poll
|
|
45
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
46
|
+
}
|
|
47
|
+
// Timed out waiting — expire the request
|
|
48
|
+
return this.expire(id);
|
|
49
|
+
}
|
|
50
|
+
async approve(id, decidedBy) {
|
|
51
|
+
const req = await this.load(id);
|
|
52
|
+
if (!req)
|
|
53
|
+
throw new Error(`Approval request ${id} not found`);
|
|
54
|
+
if (req.status !== "pending") {
|
|
55
|
+
throw new Error(`Approval request ${id} is already ${req.status}`);
|
|
56
|
+
}
|
|
57
|
+
req.status = "approved";
|
|
58
|
+
req.decidedAt = new Date().toISOString();
|
|
59
|
+
if (decidedBy)
|
|
60
|
+
req.decidedBy = decidedBy;
|
|
61
|
+
await this.save(req);
|
|
62
|
+
return req;
|
|
63
|
+
}
|
|
64
|
+
async reject(id, reason, decidedBy) {
|
|
65
|
+
const req = await this.load(id);
|
|
66
|
+
if (!req)
|
|
67
|
+
throw new Error(`Approval request ${id} not found`);
|
|
68
|
+
if (req.status !== "pending") {
|
|
69
|
+
throw new Error(`Approval request ${id} is already ${req.status}`);
|
|
70
|
+
}
|
|
71
|
+
req.status = "rejected";
|
|
72
|
+
req.decidedAt = new Date().toISOString();
|
|
73
|
+
if (reason)
|
|
74
|
+
req.rejectReason = reason;
|
|
75
|
+
if (decidedBy)
|
|
76
|
+
req.decidedBy = decidedBy;
|
|
77
|
+
await this.save(req);
|
|
78
|
+
return req;
|
|
79
|
+
}
|
|
80
|
+
async expire(id) {
|
|
81
|
+
const req = await this.load(id);
|
|
82
|
+
if (!req)
|
|
83
|
+
throw new Error(`Approval request ${id} not found`);
|
|
84
|
+
if (req.status !== "pending") {
|
|
85
|
+
// Already decided, just return as-is
|
|
86
|
+
return req;
|
|
87
|
+
}
|
|
88
|
+
req.status = "expired";
|
|
89
|
+
req.decidedAt = new Date().toISOString();
|
|
90
|
+
await this.save(req);
|
|
91
|
+
return req;
|
|
92
|
+
}
|
|
93
|
+
async list(status) {
|
|
94
|
+
await mkdir(this.dir, { recursive: true });
|
|
95
|
+
let files;
|
|
96
|
+
try {
|
|
97
|
+
files = await readdir(this.dir);
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return [];
|
|
101
|
+
}
|
|
102
|
+
const results = [];
|
|
103
|
+
for (const file of files) {
|
|
104
|
+
if (!file.endsWith(".json"))
|
|
105
|
+
continue;
|
|
106
|
+
const id = file.replace(".json", "");
|
|
107
|
+
const req = await this.load(id);
|
|
108
|
+
if (!req)
|
|
109
|
+
continue;
|
|
110
|
+
if (status && req.status !== status)
|
|
111
|
+
continue;
|
|
112
|
+
results.push(req);
|
|
113
|
+
}
|
|
114
|
+
// Sort by creation time descending
|
|
115
|
+
results.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
|
|
116
|
+
return results;
|
|
117
|
+
}
|
|
118
|
+
async get(id) {
|
|
119
|
+
return this.load(id);
|
|
120
|
+
}
|
|
121
|
+
async save(req) {
|
|
122
|
+
await mkdir(this.dir, { recursive: true });
|
|
123
|
+
const filePath = this.approvalPath(req.id);
|
|
124
|
+
await writeFile(filePath, JSON.stringify(req, null, 2), "utf-8");
|
|
125
|
+
}
|
|
126
|
+
async load(id) {
|
|
127
|
+
const filePath = this.approvalPath(id);
|
|
128
|
+
try {
|
|
129
|
+
const data = await readFile(filePath, "utf-8");
|
|
130
|
+
return JSON.parse(data);
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
approvalPath(id) {
|
|
137
|
+
return join(this.dir, `${id}.json`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=approval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval.js","sourceRoot":"","sources":["../../src/approval.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export interface AuditToolCall {
|
|
2
|
+
name: string;
|
|
3
|
+
input: Record<string, unknown>;
|
|
4
|
+
output?: string;
|
|
5
|
+
error?: string;
|
|
6
|
+
durationMs: number;
|
|
7
|
+
retries: number;
|
|
8
|
+
approvalId?: string;
|
|
9
|
+
approvalStatus?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface AuditRecord {
|
|
12
|
+
runId: string;
|
|
13
|
+
taskName: string;
|
|
14
|
+
startedAt: string;
|
|
15
|
+
completedAt: string;
|
|
16
|
+
status: "success" | "error";
|
|
17
|
+
promptPreview: string;
|
|
18
|
+
toolCalls: AuditToolCall[];
|
|
19
|
+
totalDurationMs: number;
|
|
20
|
+
error?: string;
|
|
21
|
+
}
|
|
22
|
+
export declare class AuditLogger {
|
|
23
|
+
private dir;
|
|
24
|
+
constructor(dir: string);
|
|
25
|
+
/**
|
|
26
|
+
* Writes an audit record to workspace/audit/YYYY-MM-DD/{runId}.json
|
|
27
|
+
*/
|
|
28
|
+
writeRecord(record: AuditRecord): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* Extracts YYYY-MM-DD from an ISO date string.
|
|
31
|
+
*/
|
|
32
|
+
private extractDate;
|
|
33
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
export class AuditLogger {
|
|
4
|
+
dir;
|
|
5
|
+
constructor(dir) {
|
|
6
|
+
this.dir = dir;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Writes an audit record to workspace/audit/YYYY-MM-DD/{runId}.json
|
|
10
|
+
*/
|
|
11
|
+
async writeRecord(record) {
|
|
12
|
+
// Derive the date folder from completedAt (or startedAt as fallback)
|
|
13
|
+
const dateStr = this.extractDate(record.completedAt || record.startedAt);
|
|
14
|
+
const dayDir = join(this.dir, "workspace", "audit", dateStr);
|
|
15
|
+
await mkdir(dayDir, { recursive: true });
|
|
16
|
+
const filePath = join(dayDir, `${record.runId}.json`);
|
|
17
|
+
await writeFile(filePath, JSON.stringify(record, null, 2), "utf-8");
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Extracts YYYY-MM-DD from an ISO date string.
|
|
21
|
+
*/
|
|
22
|
+
extractDate(isoString) {
|
|
23
|
+
try {
|
|
24
|
+
const date = new Date(isoString);
|
|
25
|
+
const year = date.getFullYear();
|
|
26
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
27
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
28
|
+
return `${year}-${month}-${day}`;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// Fallback: try to parse the first 10 chars directly
|
|
32
|
+
return isoString.slice(0, 10);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/audit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAyBjC,MAAM,OAAO,WAAW;IACd,GAAG,CAAS;IAEpB,YAAY,GAAW;QACrB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW,CAAC,MAAmB;QACnC,qEAAqE;QACrE,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC;QACzE,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAE7D,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAEzC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,OAAO,CAAC,CAAC;QACtD,MAAM,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACtE,CAAC;IAED;;OAEG;IACK,WAAW,CAAC,SAAiB;QACnC,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC;YACjC,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;YAChC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;YAC3D,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;YACpD,OAAO,GAAG,IAAI,IAAI,KAAK,IAAI,GAAG,EAAE,CAAC;QACnC,CAAC;QAAC,MAAM,CAAC;YACP,qDAAqD;YACrD,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Channel } from "./types.js";
|
|
2
|
+
export declare class TelegramChannel implements Channel {
|
|
3
|
+
name: string;
|
|
4
|
+
private bot;
|
|
5
|
+
private ownerId;
|
|
6
|
+
constructor(token: string, ownerId: number);
|
|
7
|
+
start(onMessage: (text: string) => Promise<string>): Promise<void>;
|
|
8
|
+
send(text: string): Promise<void>;
|
|
9
|
+
stop(): Promise<void>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Bot } from "grammy";
|
|
2
|
+
export class TelegramChannel {
|
|
3
|
+
name = "telegram";
|
|
4
|
+
bot;
|
|
5
|
+
ownerId;
|
|
6
|
+
constructor(token, ownerId) {
|
|
7
|
+
this.bot = new Bot(token);
|
|
8
|
+
this.ownerId = ownerId;
|
|
9
|
+
}
|
|
10
|
+
async start(onMessage) {
|
|
11
|
+
this.bot.on("message:text", async (ctx) => {
|
|
12
|
+
const senderId = ctx.from?.id;
|
|
13
|
+
if (senderId !== this.ownerId) {
|
|
14
|
+
await ctx.reply("Sorry, I only talk to my founder.");
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const text = ctx.message.text;
|
|
18
|
+
try {
|
|
19
|
+
const response = await onMessage(text);
|
|
20
|
+
await ctx.reply(response);
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
const msg = err instanceof Error ? err.message : "Unknown error";
|
|
24
|
+
await ctx.reply(`Error: ${msg}`);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
this.bot.catch((err) => {
|
|
28
|
+
console.error(`[telegram] ${err.message}`);
|
|
29
|
+
});
|
|
30
|
+
this.bot.start().catch((err) => {
|
|
31
|
+
console.error(`[telegram] Failed to start: ${err.message}`);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
async send(text) {
|
|
35
|
+
await this.bot.api.sendMessage(this.ownerId, text);
|
|
36
|
+
}
|
|
37
|
+
async stop() {
|
|
38
|
+
await this.bot.stop();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=telegram.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telegram.js","sourceRoot":"","sources":["../../../src/channels/telegram.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAG7B,MAAM,OAAO,eAAe;IAC1B,IAAI,GAAG,UAAU,CAAC;IACV,GAAG,CAAM;IACT,OAAO,CAAS;IAExB,YAAY,KAAa,EAAE,OAAe;QACxC,IAAI,CAAC,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;QAC1B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,SAA4C;QACtD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,cAAc,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YACxC,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;YAC9B,IAAI,QAAQ,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;gBAC9B,MAAM,GAAG,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;gBACrD,OAAO;YACT,CAAC;YAED,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;YAC9B,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,CAAC;gBACvC,MAAM,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YAC5B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;gBACjE,MAAM,GAAG,CAAC,KAAK,CAAC,UAAU,GAAG,EAAE,CAAC,CAAC;YACnC,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACrB,OAAO,CAAC,KAAK,CAAC,cAAc,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YAC7B,OAAO,CAAC,KAAK,CAAC,+BAA+B,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,IAAY;QACrB,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACrD,CAAC;IAED,KAAK,CAAC,IAAI;QACR,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;IACxB,CAAC;CACF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Channel } from "./types.js";
|
|
2
|
+
export declare class TerminalChannel implements Channel {
|
|
3
|
+
name: string;
|
|
4
|
+
private rl;
|
|
5
|
+
private processing;
|
|
6
|
+
start(onMessage: (text: string) => Promise<string>): Promise<void>;
|
|
7
|
+
send(text: string): Promise<void>;
|
|
8
|
+
stop(): Promise<void>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as readline from "node:readline";
|
|
2
|
+
import { stdin, stdout } from "node:process";
|
|
3
|
+
export class TerminalChannel {
|
|
4
|
+
name = "terminal";
|
|
5
|
+
rl = null;
|
|
6
|
+
processing = false;
|
|
7
|
+
async start(onMessage) {
|
|
8
|
+
this.rl = readline.createInterface({ input: stdin, output: stdout });
|
|
9
|
+
console.log("\n Terminal channel active. Type a message or Ctrl+C to exit.\n");
|
|
10
|
+
const prompt = () => {
|
|
11
|
+
if (!this.rl)
|
|
12
|
+
return;
|
|
13
|
+
this.rl.question("you> ", async (input) => {
|
|
14
|
+
const text = input.trim();
|
|
15
|
+
if (!text) {
|
|
16
|
+
prompt();
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
this.processing = true;
|
|
20
|
+
try {
|
|
21
|
+
const response = await onMessage(text);
|
|
22
|
+
console.log(`\nceo> ${response}\n`);
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
const msg = err instanceof Error ? err.message : "Unknown error";
|
|
26
|
+
console.log(`\n[error] ${msg}\n`);
|
|
27
|
+
}
|
|
28
|
+
finally {
|
|
29
|
+
this.processing = false;
|
|
30
|
+
prompt();
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
this.rl.on("close", () => {
|
|
35
|
+
if (!this.processing) {
|
|
36
|
+
console.log("\nGoodbye!");
|
|
37
|
+
process.exit(0);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
prompt();
|
|
41
|
+
}
|
|
42
|
+
async send(text) {
|
|
43
|
+
console.log(`\nceo> ${text}\n`);
|
|
44
|
+
}
|
|
45
|
+
async stop() {
|
|
46
|
+
if (this.rl) {
|
|
47
|
+
this.rl.close();
|
|
48
|
+
this.rl = null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=terminal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal.js","sourceRoot":"","sources":["../../../src/channels/terminal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAG7C,MAAM,OAAO,eAAe;IAC1B,IAAI,GAAG,UAAU,CAAC;IACV,EAAE,GAA8B,IAAI,CAAC;IACrC,UAAU,GAAG,KAAK,CAAC;IAE3B,KAAK,CAAC,KAAK,CAAC,SAA4C;QACtD,IAAI,CAAC,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QAErE,OAAO,CAAC,GAAG,CAAC,kEAAkE,CAAC,CAAC;QAEhF,MAAM,MAAM,GAAG,GAAG,EAAE;YAClB,IAAI,CAAC,IAAI,CAAC,EAAE;gBAAE,OAAO;YACrB,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;gBACxC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;gBAC1B,IAAI,CAAC,IAAI,EAAE,CAAC;oBACV,MAAM,EAAE,CAAC;oBACT,OAAO;gBACT,CAAC;gBAED,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;gBACvB,IAAI,CAAC;oBACH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,CAAC;oBACvC,OAAO,CAAC,GAAG,CAAC,UAAU,QAAQ,IAAI,CAAC,CAAC;gBACtC,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;oBACjE,OAAO,CAAC,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;gBACpC,CAAC;wBAAS,CAAC;oBACT,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;oBACxB,MAAM,EAAE,CAAC;gBACX,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC,CAAC;QAEF,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACvB,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;gBACrB,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;gBAC1B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,EAAE,CAAC;IACX,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,IAAY;QACrB,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,IAAI,CAAC,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;YACZ,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;YAChB,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC;QACjB,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/channels/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import net from "node:net";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
async function sendIpc(dir, command) {
|
|
4
|
+
const sockPath = join(dir, "daemon.sock");
|
|
5
|
+
return new Promise((resolve, reject) => {
|
|
6
|
+
const client = net.createConnection(sockPath, () => {
|
|
7
|
+
client.write(command);
|
|
8
|
+
client.end();
|
|
9
|
+
});
|
|
10
|
+
let data = "";
|
|
11
|
+
client.on("data", (chunk) => {
|
|
12
|
+
data += chunk.toString();
|
|
13
|
+
});
|
|
14
|
+
client.on("end", () => resolve(data));
|
|
15
|
+
client.on("error", (err) => {
|
|
16
|
+
reject(new Error(`Cannot connect to daemon. Is FreeTurtle running?\n${err.message}`));
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
export async function runApprove(dir, id) {
|
|
21
|
+
const response = await sendIpc(dir, `approve ${id}`);
|
|
22
|
+
console.log(response);
|
|
23
|
+
}
|
|
24
|
+
export async function runReject(dir, id, reason) {
|
|
25
|
+
const cmd = reason ? `reject ${id} ${reason}` : `reject ${id}`;
|
|
26
|
+
const response = await sendIpc(dir, cmd);
|
|
27
|
+
console.log(response);
|
|
28
|
+
}
|
|
29
|
+
export async function runListApprovals(dir) {
|
|
30
|
+
const response = await sendIpc(dir, "approvals");
|
|
31
|
+
console.log(response);
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=approvals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approvals.js","sourceRoot":"","sources":["../../../src/cli/approvals.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,UAAU,CAAC;AAC3B,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,KAAK,UAAU,OAAO,CAAC,GAAW,EAAE,OAAe;IACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;IAE1C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAG,GAAG,CAAC,gBAAgB,CAAC,QAAQ,EAAE,GAAG,EAAE;YACjD,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACtB,MAAM,CAAC,GAAG,EAAE,CAAC;QACf,CAAC,CAAC,CAAC;QAEH,IAAI,IAAI,GAAG,EAAE,CAAC;QACd,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YAC1B,IAAI,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC3B,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACtC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACzB,MAAM,CACJ,IAAI,KAAK,CACP,qDAAqD,GAAG,CAAC,OAAO,EAAE,CACnE,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAW,EAAE,EAAU;IACtD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACxB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,GAAW,EACX,EAAU,EACV,MAAe;IAEf,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,UAAU,EAAE,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC;IAC/D,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACxB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,GAAW;IAChD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACxB,CAAC"}
|