clawd-automaton 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 +21 -0
- package/README.md +178 -0
- package/constitution.md +25 -0
- package/dist/__tests__/heartbeat.test.d.ts +7 -0
- package/dist/__tests__/heartbeat.test.d.ts.map +1 -0
- package/dist/__tests__/heartbeat.test.js +125 -0
- package/dist/__tests__/heartbeat.test.js.map +1 -0
- package/dist/__tests__/loop.test.d.ts +7 -0
- package/dist/__tests__/loop.test.d.ts.map +1 -0
- package/dist/__tests__/loop.test.js +150 -0
- package/dist/__tests__/loop.test.js.map +1 -0
- package/dist/__tests__/mocks.d.ts +72 -0
- package/dist/__tests__/mocks.d.ts.map +1 -0
- package/dist/__tests__/mocks.js +197 -0
- package/dist/__tests__/mocks.js.map +1 -0
- package/dist/agent/context.d.ts +26 -0
- package/dist/agent/context.d.ts.map +1 -0
- package/dist/agent/context.js +115 -0
- package/dist/agent/context.js.map +1 -0
- package/dist/agent/injection-defense.d.ts +13 -0
- package/dist/agent/injection-defense.d.ts.map +1 -0
- package/dist/agent/injection-defense.js +236 -0
- package/dist/agent/injection-defense.js.map +1 -0
- package/dist/agent/loop.d.ts +25 -0
- package/dist/agent/loop.d.ts.map +1 -0
- package/dist/agent/loop.js +263 -0
- package/dist/agent/loop.js.map +1 -0
- package/dist/agent/system-prompt.d.ts +30 -0
- package/dist/agent/system-prompt.d.ts.map +1 -0
- package/dist/agent/system-prompt.js +241 -0
- package/dist/agent/system-prompt.js.map +1 -0
- package/dist/agent/tools.d.ts +17 -0
- package/dist/agent/tools.d.ts.map +1 -0
- package/dist/agent/tools.js +1413 -0
- package/dist/agent/tools.js.map +1 -0
- package/dist/clawd/backroom.d.ts +54 -0
- package/dist/clawd/backroom.d.ts.map +1 -0
- package/dist/clawd/backroom.js +130 -0
- package/dist/clawd/backroom.js.map +1 -0
- package/dist/clawd/client.d.ts +16 -0
- package/dist/clawd/client.d.ts.map +1 -0
- package/dist/clawd/client.js +256 -0
- package/dist/clawd/client.js.map +1 -0
- package/dist/clawd/convex-client.d.ts +130 -0
- package/dist/clawd/convex-client.d.ts.map +1 -0
- package/dist/clawd/convex-client.js +118 -0
- package/dist/clawd/convex-client.js.map +1 -0
- package/dist/clawd/credits.d.ts +24 -0
- package/dist/clawd/credits.d.ts.map +1 -0
- package/dist/clawd/credits.js +64 -0
- package/dist/clawd/credits.js.map +1 -0
- package/dist/clawd/deepseek-inference.d.ts +40 -0
- package/dist/clawd/deepseek-inference.d.ts.map +1 -0
- package/dist/clawd/deepseek-inference.js +143 -0
- package/dist/clawd/deepseek-inference.js.map +1 -0
- package/dist/clawd/inference.d.ts +17 -0
- package/dist/clawd/inference.d.ts.map +1 -0
- package/dist/clawd/inference.js +114 -0
- package/dist/clawd/inference.js.map +1 -0
- package/dist/clawd/x402.d.ts +48 -0
- package/dist/clawd/x402.d.ts.map +1 -0
- package/dist/clawd/x402.js +350 -0
- package/dist/clawd/x402.js.map +1 -0
- package/dist/config.d.ts +36 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +84 -0
- package/dist/config.js.map +1 -0
- package/dist/git/state-versioning.d.ts +39 -0
- package/dist/git/state-versioning.d.ts.map +1 -0
- package/dist/git/state-versioning.js +93 -0
- package/dist/git/state-versioning.js.map +1 -0
- package/dist/git/tools.d.ts +40 -0
- package/dist/git/tools.d.ts.map +1 -0
- package/dist/git/tools.js +140 -0
- package/dist/git/tools.js.map +1 -0
- package/dist/heartbeat/config.d.ts +23 -0
- package/dist/heartbeat/config.d.ts.map +1 -0
- package/dist/heartbeat/config.js +156 -0
- package/dist/heartbeat/config.js.map +1 -0
- package/dist/heartbeat/daemon.d.ts +28 -0
- package/dist/heartbeat/daemon.d.ts.map +1 -0
- package/dist/heartbeat/daemon.js +141 -0
- package/dist/heartbeat/daemon.js.map +1 -0
- package/dist/heartbeat/tasks.d.ts +24 -0
- package/dist/heartbeat/tasks.d.ts.map +1 -0
- package/dist/heartbeat/tasks.js +277 -0
- package/dist/heartbeat/tasks.js.map +1 -0
- package/dist/identity/provision.d.ts +28 -0
- package/dist/identity/provision.d.ts.map +1 -0
- package/dist/identity/provision.js +131 -0
- package/dist/identity/provision.js.map +1 -0
- package/dist/identity/wallet.d.ts +28 -0
- package/dist/identity/wallet.d.ts.map +1 -0
- package/dist/identity/wallet.js +69 -0
- package/dist/identity/wallet.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +358 -0
- package/dist/index.js.map +1 -0
- package/dist/ooda/claude-decision.d.ts +18 -0
- package/dist/ooda/claude-decision.d.ts.map +1 -0
- package/dist/ooda/claude-decision.js +82 -0
- package/dist/ooda/claude-decision.js.map +1 -0
- package/dist/ooda/journal.d.ts +22 -0
- package/dist/ooda/journal.d.ts.map +1 -0
- package/dist/ooda/journal.js +26 -0
- package/dist/ooda/journal.js.map +1 -0
- package/dist/ooda/loop.d.ts +3 -0
- package/dist/ooda/loop.d.ts.map +1 -0
- package/dist/ooda/loop.js +210 -0
- package/dist/ooda/loop.js.map +1 -0
- package/dist/ooda/observe.d.ts +21 -0
- package/dist/ooda/observe.d.ts.map +1 -0
- package/dist/ooda/observe.js +75 -0
- package/dist/ooda/observe.js.map +1 -0
- package/dist/ooda/state.d.ts +34 -0
- package/dist/ooda/state.d.ts.map +1 -0
- package/dist/ooda/state.js +48 -0
- package/dist/ooda/state.js.map +1 -0
- package/dist/ooda/tui.d.ts +3 -0
- package/dist/ooda/tui.d.ts.map +1 -0
- package/dist/ooda/tui.js +132 -0
- package/dist/ooda/tui.js.map +1 -0
- package/dist/ooda/validate.d.ts +33 -0
- package/dist/ooda/validate.d.ts.map +1 -0
- package/dist/ooda/validate.js +91 -0
- package/dist/ooda/validate.js.map +1 -0
- package/dist/registry/agent-card.d.ts +26 -0
- package/dist/registry/agent-card.d.ts.map +1 -0
- package/dist/registry/agent-card.js +94 -0
- package/dist/registry/agent-card.js.map +1 -0
- package/dist/registry/discovery.d.ts +24 -0
- package/dist/registry/discovery.d.ts.map +1 -0
- package/dist/registry/discovery.js +74 -0
- package/dist/registry/discovery.js.map +1 -0
- package/dist/registry/erc8004.d.ts +39 -0
- package/dist/registry/erc8004.d.ts.map +1 -0
- package/dist/registry/erc8004.js +209 -0
- package/dist/registry/erc8004.js.map +1 -0
- package/dist/replication/genesis.d.ts +26 -0
- package/dist/replication/genesis.d.ts.map +1 -0
- package/dist/replication/genesis.js +72 -0
- package/dist/replication/genesis.js.map +1 -0
- package/dist/replication/lineage.d.ts +35 -0
- package/dist/replication/lineage.d.ts.map +1 -0
- package/dist/replication/lineage.js +79 -0
- package/dist/replication/lineage.js.map +1 -0
- package/dist/replication/spawn.d.ts +25 -0
- package/dist/replication/spawn.d.ts.map +1 -0
- package/dist/replication/spawn.js +166 -0
- package/dist/replication/spawn.js.map +1 -0
- package/dist/self-mod/audit-log.d.ts +24 -0
- package/dist/self-mod/audit-log.d.ts.map +1 -0
- package/dist/self-mod/audit-log.js +49 -0
- package/dist/self-mod/audit-log.js.map +1 -0
- package/dist/self-mod/code.d.ts +51 -0
- package/dist/self-mod/code.d.ts.map +1 -0
- package/dist/self-mod/code.js +317 -0
- package/dist/self-mod/code.js.map +1 -0
- package/dist/self-mod/tools-manager.d.ts +30 -0
- package/dist/self-mod/tools-manager.d.ts.map +1 -0
- package/dist/self-mod/tools-manager.js +74 -0
- package/dist/self-mod/tools-manager.js.map +1 -0
- package/dist/self-mod/upstream.d.ts +36 -0
- package/dist/self-mod/upstream.d.ts.map +1 -0
- package/dist/self-mod/upstream.js +66 -0
- package/dist/self-mod/upstream.js.map +1 -0
- package/dist/setup/banner.d.ts +2 -0
- package/dist/setup/banner.d.ts.map +1 -0
- package/dist/setup/banner.js +22 -0
- package/dist/setup/banner.js.map +1 -0
- package/dist/setup/defaults.d.ts +3 -0
- package/dist/setup/defaults.d.ts.map +1 -0
- package/dist/setup/defaults.js +113 -0
- package/dist/setup/defaults.js.map +1 -0
- package/dist/setup/environment.d.ts +6 -0
- package/dist/setup/environment.d.ts.map +1 -0
- package/dist/setup/environment.js +24 -0
- package/dist/setup/environment.js.map +1 -0
- package/dist/setup/prompts.d.ts +5 -0
- package/dist/setup/prompts.d.ts.map +1 -0
- package/dist/setup/prompts.js +70 -0
- package/dist/setup/prompts.js.map +1 -0
- package/dist/setup/wizard.d.ts +3 -0
- package/dist/setup/wizard.d.ts.map +1 -0
- package/dist/setup/wizard.js +128 -0
- package/dist/setup/wizard.js.map +1 -0
- package/dist/skills/format.d.ts +14 -0
- package/dist/skills/format.d.ts.map +1 -0
- package/dist/skills/format.js +145 -0
- package/dist/skills/format.js.map +1 -0
- package/dist/skills/loader.d.ts +19 -0
- package/dist/skills/loader.d.ts.map +1 -0
- package/dist/skills/loader.js +98 -0
- package/dist/skills/loader.js.map +1 -0
- package/dist/skills/registry.d.ts +31 -0
- package/dist/skills/registry.d.ts.map +1 -0
- package/dist/skills/registry.js +111 -0
- package/dist/skills/registry.js.map +1 -0
- package/dist/social/client.d.ts +13 -0
- package/dist/social/client.d.ts.map +1 -0
- package/dist/social/client.js +89 -0
- package/dist/social/client.js.map +1 -0
- package/dist/state/database.d.ts +9 -0
- package/dist/state/database.d.ts.map +1 -0
- package/dist/state/database.js +401 -0
- package/dist/state/database.js.map +1 -0
- package/dist/state/schema.d.ts +11 -0
- package/dist/state/schema.d.ts.map +1 -0
- package/dist/state/schema.js +232 -0
- package/dist/state/schema.js.map +1 -0
- package/dist/survival/funding.d.ts +19 -0
- package/dist/survival/funding.d.ts.map +1 -0
- package/dist/survival/funding.js +62 -0
- package/dist/survival/funding.js.map +1 -0
- package/dist/survival/low-compute.d.ts +30 -0
- package/dist/survival/low-compute.d.ts.map +1 -0
- package/dist/survival/low-compute.js +72 -0
- package/dist/survival/low-compute.js.map +1 -0
- package/dist/survival/monitor.d.ts +23 -0
- package/dist/survival/monitor.d.ts.map +1 -0
- package/dist/survival/monitor.js +70 -0
- package/dist/survival/monitor.js.map +1 -0
- package/dist/types.d.ts +461 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +25 -0
- package/dist/types.js.map +1 -0
- package/package.json +85 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Heartbeat Daemon
|
|
3
|
+
*
|
|
4
|
+
* Runs periodic tasks on cron schedules inside the same Node.js process.
|
|
5
|
+
* The heartbeat runs even when the agent is sleeping.
|
|
6
|
+
* It IS the automaton's pulse. When it stops, the automaton is dead.
|
|
7
|
+
*/
|
|
8
|
+
import cronParser from "cron-parser";
|
|
9
|
+
import { BUILTIN_TASKS } from "./tasks.js";
|
|
10
|
+
import { getSurvivalTier } from "../clawd/credits.js";
|
|
11
|
+
/**
|
|
12
|
+
* Create and return the heartbeat daemon.
|
|
13
|
+
*/
|
|
14
|
+
export function createHeartbeatDaemon(options) {
|
|
15
|
+
const { identity, config, db, runtime, inference, social, onWakeRequest } = options;
|
|
16
|
+
let intervalId = null;
|
|
17
|
+
let running = false;
|
|
18
|
+
const taskContext = {
|
|
19
|
+
identity,
|
|
20
|
+
config,
|
|
21
|
+
db,
|
|
22
|
+
runtime,
|
|
23
|
+
inference,
|
|
24
|
+
social,
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Check if a heartbeat entry is due to run.
|
|
28
|
+
*/
|
|
29
|
+
function isDue(entry) {
|
|
30
|
+
if (!entry.enabled)
|
|
31
|
+
return false;
|
|
32
|
+
if (!entry.schedule)
|
|
33
|
+
return false;
|
|
34
|
+
try {
|
|
35
|
+
const interval = cronParser.parseExpression(entry.schedule, {
|
|
36
|
+
currentDate: entry.lastRun
|
|
37
|
+
? new Date(entry.lastRun)
|
|
38
|
+
: new Date(Date.now() - 86400000), // If never run, assume due
|
|
39
|
+
});
|
|
40
|
+
const nextRun = interval.next().toDate();
|
|
41
|
+
return nextRun <= new Date();
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Execute a single heartbeat task.
|
|
49
|
+
*/
|
|
50
|
+
async function executeTask(entry) {
|
|
51
|
+
const taskFn = BUILTIN_TASKS[entry.task];
|
|
52
|
+
if (!taskFn) {
|
|
53
|
+
// Unknown task -- skip silently
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const result = await taskFn(taskContext);
|
|
58
|
+
// Update last run
|
|
59
|
+
const now = new Date().toISOString();
|
|
60
|
+
db.updateHeartbeatLastRun(entry.name, now);
|
|
61
|
+
// If the task says we should wake, fire the callback
|
|
62
|
+
if (result.shouldWake && onWakeRequest) {
|
|
63
|
+
onWakeRequest(result.message || `Heartbeat task '${entry.name}' requested wake`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
// Log error but don't crash the daemon
|
|
68
|
+
console.error(`[HEARTBEAT] Task '${entry.name}' failed: ${err.message}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The main tick function. Runs on every interval.
|
|
73
|
+
*/
|
|
74
|
+
async function tick() {
|
|
75
|
+
const entries = db.getHeartbeatEntries();
|
|
76
|
+
// Check survival tier to adjust behavior
|
|
77
|
+
let creditsCents = 0;
|
|
78
|
+
try {
|
|
79
|
+
creditsCents = await runtime.getCreditsBalance();
|
|
80
|
+
}
|
|
81
|
+
catch { }
|
|
82
|
+
const tier = getSurvivalTier(creditsCents);
|
|
83
|
+
const isLowCompute = tier === "low_compute" || tier === "critical" || tier === "dead";
|
|
84
|
+
for (const entry of entries) {
|
|
85
|
+
if (!entry.enabled)
|
|
86
|
+
continue;
|
|
87
|
+
// In low compute mode, only run essential tasks
|
|
88
|
+
if (isLowCompute) {
|
|
89
|
+
const essentialTasks = [
|
|
90
|
+
"heartbeat_ping",
|
|
91
|
+
"check_credits",
|
|
92
|
+
"check_usdc_balance",
|
|
93
|
+
"check_social_inbox",
|
|
94
|
+
];
|
|
95
|
+
if (!essentialTasks.includes(entry.task))
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (isDue(entry)) {
|
|
99
|
+
await executeTask(entry);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// ─── Public API ──────────────────────────────────────────────
|
|
104
|
+
const start = () => {
|
|
105
|
+
if (running)
|
|
106
|
+
return;
|
|
107
|
+
running = true;
|
|
108
|
+
// Get tick interval -- default 60 seconds
|
|
109
|
+
const tickMs = config.logLevel === "debug" ? 15_000 : 60_000;
|
|
110
|
+
// Run first tick immediately
|
|
111
|
+
tick().catch((err) => {
|
|
112
|
+
console.error(`[HEARTBEAT] First tick failed: ${err.message}`);
|
|
113
|
+
});
|
|
114
|
+
intervalId = setInterval(() => {
|
|
115
|
+
tick().catch((err) => {
|
|
116
|
+
console.error(`[HEARTBEAT] Tick failed: ${err.message}`);
|
|
117
|
+
});
|
|
118
|
+
}, tickMs);
|
|
119
|
+
console.log(`[HEARTBEAT] Daemon started. Tick interval: ${tickMs / 1000}s`);
|
|
120
|
+
};
|
|
121
|
+
const stop = () => {
|
|
122
|
+
if (!running)
|
|
123
|
+
return;
|
|
124
|
+
running = false;
|
|
125
|
+
if (intervalId) {
|
|
126
|
+
clearInterval(intervalId);
|
|
127
|
+
intervalId = null;
|
|
128
|
+
}
|
|
129
|
+
console.log("[HEARTBEAT] Daemon stopped.");
|
|
130
|
+
};
|
|
131
|
+
const isRunning = () => running;
|
|
132
|
+
const forceRun = async (taskName) => {
|
|
133
|
+
const entries = db.getHeartbeatEntries();
|
|
134
|
+
const entry = entries.find((e) => e.name === taskName);
|
|
135
|
+
if (entry) {
|
|
136
|
+
await executeTask(entry);
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
return { start, stop, isRunning, forceRun };
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=daemon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon.js","sourceRoot":"","sources":["../../src/heartbeat/daemon.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,UAAU,MAAM,aAAa,CAAC;AAUrC,OAAO,EAAE,aAAa,EAA6B,MAAM,YAAY,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAmBtD;;GAEG;AACH,MAAM,UAAU,qBAAqB,CACnC,OAA+B;IAE/B,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC;IACpF,IAAI,UAAU,GAA0C,IAAI,CAAC;IAC7D,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,MAAM,WAAW,GAAyB;QACxC,QAAQ;QACR,MAAM;QACN,EAAE;QACF,OAAO;QACP,SAAS;QACT,MAAM;KACP,CAAC;IAEF;;OAEG;IACH,SAAS,KAAK,CAAC,KAAqB;QAClC,IAAI,CAAC,KAAK,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC;QACjC,IAAI,CAAC,KAAK,CAAC,QAAQ;YAAE,OAAO,KAAK,CAAC;QAElC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,UAAU,CAAC,eAAe,CAAC,KAAK,CAAC,QAAQ,EAAE;gBAC1D,WAAW,EAAE,KAAK,CAAC,OAAO;oBACxB,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;oBACzB,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,EAAE,2BAA2B;aACjE,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC;YACzC,OAAO,OAAO,IAAI,IAAI,IAAI,EAAE,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,UAAU,WAAW,CAAC,KAAqB;QAC9C,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,gCAAgC;YAChC,OAAO;QACT,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;YAEzC,kBAAkB;YAClB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;YACrC,EAAE,CAAC,sBAAsB,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAE3C,qDAAqD;YACrD,IAAI,MAAM,CAAC,UAAU,IAAI,aAAa,EAAE,CAAC;gBACvC,aAAa,CACX,MAAM,CAAC,OAAO,IAAI,mBAAmB,KAAK,CAAC,IAAI,kBAAkB,CAClE,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,uCAAuC;YACvC,OAAO,CAAC,KAAK,CACX,qBAAqB,KAAK,CAAC,IAAI,aAAa,GAAG,CAAC,OAAO,EAAE,CAC1D,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,UAAU,IAAI;QACjB,MAAM,OAAO,GAAG,EAAE,CAAC,mBAAmB,EAAE,CAAC;QAEzC,yCAAyC;QACzC,IAAI,YAAY,GAAG,CAAC,CAAC;QACrB,IAAI,CAAC;YACH,YAAY,GAAG,MAAM,OAAO,CAAC,iBAAiB,EAAE,CAAC;QACnD,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;QAEV,MAAM,IAAI,GAAG,eAAe,CAAC,YAAY,CAAC,CAAC;QAC3C,MAAM,YAAY,GAAG,IAAI,KAAK,aAAa,IAAI,IAAI,KAAK,UAAU,IAAI,IAAI,KAAK,MAAM,CAAC;QAEtF,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,CAAC,KAAK,CAAC,OAAO;gBAAE,SAAS;YAE7B,gDAAgD;YAChD,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,cAAc,GAAG;oBACrB,gBAAgB;oBAChB,eAAe;oBACf,oBAAoB;oBACpB,oBAAoB;iBACrB,CAAC;gBACF,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;oBAAE,SAAS;YACrD,CAAC;YAED,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;gBACjB,MAAM,WAAW,CAAC,KAAK,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;IACH,CAAC;IAED,gEAAgE;IAEhE,MAAM,KAAK,GAAG,GAAS,EAAE;QACvB,IAAI,OAAO;YAAE,OAAO;QACpB,OAAO,GAAG,IAAI,CAAC;QAEf,0CAA0C;QAC1C,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;QAE7D,6BAA6B;QAC7B,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACnB,OAAO,CAAC,KAAK,CAAC,kCAAkC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACjE,CAAC,CAAC,CAAC;QAEH,UAAU,GAAG,WAAW,CAAC,GAAG,EAAE;YAC5B,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;gBACnB,OAAO,CAAC,KAAK,CAAC,4BAA4B,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YAC3D,CAAC,CAAC,CAAC;QACL,CAAC,EAAE,MAAM,CAAC,CAAC;QAEX,OAAO,CAAC,GAAG,CACT,8CAA8C,MAAM,GAAG,IAAI,GAAG,CAC/D,CAAC;IACJ,CAAC,CAAC;IAEF,MAAM,IAAI,GAAG,GAAS,EAAE;QACtB,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,OAAO,GAAG,KAAK,CAAC;QAChB,IAAI,UAAU,EAAE,CAAC;YACf,aAAa,CAAC,UAAU,CAAC,CAAC;YAC1B,UAAU,GAAG,IAAI,CAAC;QACpB,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;IAC7C,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG,GAAY,EAAE,CAAC,OAAO,CAAC;IAEzC,MAAM,QAAQ,GAAG,KAAK,EAAE,QAAgB,EAAiB,EAAE;QACzD,MAAM,OAAO,GAAG,EAAE,CAAC,mBAAmB,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;QACvD,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,WAAW,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;AAC9C,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in Heartbeat Tasks
|
|
3
|
+
*
|
|
4
|
+
* These tasks run on the heartbeat schedule even while the agent sleeps.
|
|
5
|
+
* They can trigger the agent to wake up if needed.
|
|
6
|
+
*/
|
|
7
|
+
import type { AutomatonConfig, AutomatonDatabase, ClawdRuntimeClient, AutomatonIdentity, SocialClientInterface, InferenceClient } from "../types.js";
|
|
8
|
+
export interface HeartbeatTaskContext {
|
|
9
|
+
identity: AutomatonIdentity;
|
|
10
|
+
config: AutomatonConfig;
|
|
11
|
+
db: AutomatonDatabase;
|
|
12
|
+
runtime: ClawdRuntimeClient;
|
|
13
|
+
inference?: InferenceClient;
|
|
14
|
+
social?: SocialClientInterface;
|
|
15
|
+
}
|
|
16
|
+
export type HeartbeatTaskFn = (ctx: HeartbeatTaskContext) => Promise<{
|
|
17
|
+
shouldWake: boolean;
|
|
18
|
+
message?: string;
|
|
19
|
+
}>;
|
|
20
|
+
/**
|
|
21
|
+
* Registry of built-in heartbeat tasks.
|
|
22
|
+
*/
|
|
23
|
+
export declare const BUILTIN_TASKS: Record<string, HeartbeatTaskFn>;
|
|
24
|
+
//# sourceMappingURL=tasks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../../src/heartbeat/tasks.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EAChB,MAAM,aAAa,CAAC;AAOrB,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,MAAM,EAAE,eAAe,CAAC;IACxB,EAAE,EAAE,iBAAiB,CAAC;IACtB,OAAO,EAAE,kBAAkB,CAAC;IAC5B,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,MAAM,CAAC,EAAE,qBAAqB,CAAC;CAChC;AAED,MAAM,MAAM,eAAe,GAAG,CAC5B,GAAG,EAAE,oBAAoB,KACtB,OAAO,CAAC;IAAE,UAAU,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAExD;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAgTzD,CAAC"}
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in Heartbeat Tasks
|
|
3
|
+
*
|
|
4
|
+
* These tasks run on the heartbeat schedule even while the agent sleeps.
|
|
5
|
+
* They can trigger the agent to wake up if needed.
|
|
6
|
+
*/
|
|
7
|
+
import { getSurvivalTier } from "../clawd/credits.js";
|
|
8
|
+
import { getUsdcBalance } from "../clawd/x402.js";
|
|
9
|
+
import { runBackroomSession, summarizeBackroomSession, LOGICAL_ANALYST, SATIRICAL_COMMENTATOR } from "../clawd/backroom.js";
|
|
10
|
+
import { createConvexClient } from "../clawd/convex-client.js";
|
|
11
|
+
/**
|
|
12
|
+
* Registry of built-in heartbeat tasks.
|
|
13
|
+
*/
|
|
14
|
+
export const BUILTIN_TASKS = {
|
|
15
|
+
heartbeat_ping: async (ctx) => {
|
|
16
|
+
const credits = await ctx.runtime.getCreditsBalance();
|
|
17
|
+
const state = ctx.db.getAgentState();
|
|
18
|
+
const startTime = ctx.db.getKV("start_time") || new Date().toISOString();
|
|
19
|
+
const uptimeMs = Date.now() - new Date(startTime).getTime();
|
|
20
|
+
const tier = getSurvivalTier(credits);
|
|
21
|
+
const payload = {
|
|
22
|
+
name: ctx.config.name,
|
|
23
|
+
address: ctx.identity.address,
|
|
24
|
+
state,
|
|
25
|
+
creditsCents: credits,
|
|
26
|
+
uptimeSeconds: Math.floor(uptimeMs / 1000),
|
|
27
|
+
version: ctx.config.version,
|
|
28
|
+
sandboxId: ctx.identity.sandboxId,
|
|
29
|
+
timestamp: new Date().toISOString(),
|
|
30
|
+
tier,
|
|
31
|
+
};
|
|
32
|
+
ctx.db.setKV("last_heartbeat_ping", JSON.stringify(payload));
|
|
33
|
+
// If critical or dead, record a distress signal
|
|
34
|
+
if (tier === "critical" || tier === "dead") {
|
|
35
|
+
const distressPayload = {
|
|
36
|
+
level: tier,
|
|
37
|
+
name: ctx.config.name,
|
|
38
|
+
address: ctx.identity.address,
|
|
39
|
+
creditsCents: credits,
|
|
40
|
+
fundingHint: "Use credit transfer API from a creator runtime to top this wallet up.",
|
|
41
|
+
timestamp: new Date().toISOString(),
|
|
42
|
+
};
|
|
43
|
+
ctx.db.setKV("last_distress", JSON.stringify(distressPayload));
|
|
44
|
+
return {
|
|
45
|
+
shouldWake: true,
|
|
46
|
+
message: `Distress: ${tier}. Credits: $${(credits / 100).toFixed(2)}. Need funding.`,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return { shouldWake: false };
|
|
50
|
+
},
|
|
51
|
+
check_credits: async (ctx) => {
|
|
52
|
+
const credits = await ctx.runtime.getCreditsBalance();
|
|
53
|
+
const tier = getSurvivalTier(credits);
|
|
54
|
+
ctx.db.setKV("last_credit_check", JSON.stringify({
|
|
55
|
+
credits,
|
|
56
|
+
tier,
|
|
57
|
+
timestamp: new Date().toISOString(),
|
|
58
|
+
}));
|
|
59
|
+
// Wake the agent if credits dropped to a new tier
|
|
60
|
+
const prevTier = ctx.db.getKV("prev_credit_tier");
|
|
61
|
+
ctx.db.setKV("prev_credit_tier", tier);
|
|
62
|
+
if (prevTier && prevTier !== tier && (tier === "critical" || tier === "dead")) {
|
|
63
|
+
return {
|
|
64
|
+
shouldWake: true,
|
|
65
|
+
message: `Credits dropped to ${tier} tier: $${(credits / 100).toFixed(2)}`,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return { shouldWake: false };
|
|
69
|
+
},
|
|
70
|
+
check_usdc_balance: async (ctx) => {
|
|
71
|
+
const balance = await getUsdcBalance(ctx.identity.address);
|
|
72
|
+
ctx.db.setKV("last_usdc_check", JSON.stringify({
|
|
73
|
+
balance,
|
|
74
|
+
timestamp: new Date().toISOString(),
|
|
75
|
+
}));
|
|
76
|
+
// If we have USDC but low credits, wake up to potentially convert
|
|
77
|
+
const credits = await ctx.runtime.getCreditsBalance();
|
|
78
|
+
if (balance > 0.5 && credits < 500) {
|
|
79
|
+
return {
|
|
80
|
+
shouldWake: true,
|
|
81
|
+
message: `Have ${balance.toFixed(4)} USDC but only $${(credits / 100).toFixed(2)} credits. Consider buying credits.`,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
return { shouldWake: false };
|
|
85
|
+
},
|
|
86
|
+
check_social_inbox: async (ctx) => {
|
|
87
|
+
if (!ctx.social)
|
|
88
|
+
return { shouldWake: false };
|
|
89
|
+
const cursor = ctx.db.getKV("social_inbox_cursor") || undefined;
|
|
90
|
+
const { messages, nextCursor } = await ctx.social.poll(cursor);
|
|
91
|
+
if (messages.length === 0)
|
|
92
|
+
return { shouldWake: false };
|
|
93
|
+
// Persist to inbox_messages table for deduplication
|
|
94
|
+
let newCount = 0;
|
|
95
|
+
for (const msg of messages) {
|
|
96
|
+
const existing = ctx.db.getKV(`inbox_seen_${msg.id}`);
|
|
97
|
+
if (!existing) {
|
|
98
|
+
ctx.db.insertInboxMessage(msg);
|
|
99
|
+
ctx.db.setKV(`inbox_seen_${msg.id}`, "1");
|
|
100
|
+
newCount++;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (nextCursor)
|
|
104
|
+
ctx.db.setKV("social_inbox_cursor", nextCursor);
|
|
105
|
+
if (newCount === 0)
|
|
106
|
+
return { shouldWake: false };
|
|
107
|
+
return {
|
|
108
|
+
shouldWake: true,
|
|
109
|
+
message: `${newCount} new message(s) from: ${messages.map((m) => m.from.slice(0, 10)).join(", ")}`,
|
|
110
|
+
};
|
|
111
|
+
},
|
|
112
|
+
check_for_updates: async (ctx) => {
|
|
113
|
+
try {
|
|
114
|
+
const { checkUpstream, getRepoInfo } = await import("../self-mod/upstream.js");
|
|
115
|
+
const repo = getRepoInfo();
|
|
116
|
+
const upstream = checkUpstream();
|
|
117
|
+
ctx.db.setKV("upstream_status", JSON.stringify({
|
|
118
|
+
...upstream,
|
|
119
|
+
...repo,
|
|
120
|
+
checkedAt: new Date().toISOString(),
|
|
121
|
+
}));
|
|
122
|
+
if (upstream.behind > 0) {
|
|
123
|
+
return {
|
|
124
|
+
shouldWake: true,
|
|
125
|
+
message: `${upstream.behind} new commit(s) on origin/main. Review with review_upstream_changes, then cherry-pick what you want with pull_upstream.`,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
return { shouldWake: false };
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
// Not a git repo or no remote — silently skip
|
|
132
|
+
ctx.db.setKV("upstream_status", JSON.stringify({
|
|
133
|
+
error: err.message,
|
|
134
|
+
checkedAt: new Date().toISOString(),
|
|
135
|
+
}));
|
|
136
|
+
return { shouldWake: false };
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
health_check: async (ctx) => {
|
|
140
|
+
// Check that the sandbox is healthy
|
|
141
|
+
try {
|
|
142
|
+
const result = await ctx.runtime.exec("echo alive", 5000);
|
|
143
|
+
if (result.exitCode !== 0) {
|
|
144
|
+
return {
|
|
145
|
+
shouldWake: true,
|
|
146
|
+
message: "Health check failed: sandbox exec returned non-zero",
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
catch (err) {
|
|
151
|
+
return {
|
|
152
|
+
shouldWake: true,
|
|
153
|
+
message: `Health check failed: ${err.message}`,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
ctx.db.setKV("last_health_check", new Date().toISOString());
|
|
157
|
+
return { shouldWake: false };
|
|
158
|
+
},
|
|
159
|
+
/**
|
|
160
|
+
* Run a scheduled backroom conversation session between agents.
|
|
161
|
+
* Uses DeepSeek's thinking mode for rich multi-agent dialogue.
|
|
162
|
+
* Default: runs every 2 hours.
|
|
163
|
+
*/
|
|
164
|
+
/**
|
|
165
|
+
* Push heartbeat to CLAWD Convex backend.
|
|
166
|
+
* Only runs if convexSiteUrl is configured in automaton config.
|
|
167
|
+
*/
|
|
168
|
+
convex_heartbeat: async (ctx) => {
|
|
169
|
+
if (!ctx.config.convexSiteUrl) {
|
|
170
|
+
return { shouldWake: false };
|
|
171
|
+
}
|
|
172
|
+
try {
|
|
173
|
+
const convexClient = createConvexClient({
|
|
174
|
+
siteUrl: ctx.config.convexSiteUrl,
|
|
175
|
+
agentId: ctx.identity.address,
|
|
176
|
+
});
|
|
177
|
+
const credits = await ctx.runtime.getCreditsBalance();
|
|
178
|
+
const state = ctx.db.getAgentState();
|
|
179
|
+
const startTime = ctx.db.getKV("start_time") || new Date().toISOString();
|
|
180
|
+
const uptimeMs = Date.now() - new Date(startTime).getTime();
|
|
181
|
+
const tier = getSurvivalTier(credits);
|
|
182
|
+
const turnCount = ctx.db.getTurnCount();
|
|
183
|
+
const skills = ctx.db.getSkills(true);
|
|
184
|
+
// First, register the agent if not already registered
|
|
185
|
+
const existing = ctx.db.getKV("convex_registered");
|
|
186
|
+
if (!existing) {
|
|
187
|
+
const result = await convexClient.registerAgent({
|
|
188
|
+
agentId: ctx.identity.address,
|
|
189
|
+
name: ctx.config.name,
|
|
190
|
+
installMethod: "automaton",
|
|
191
|
+
address: ctx.identity.address,
|
|
192
|
+
metadata: JSON.stringify({
|
|
193
|
+
sandboxId: ctx.identity.sandboxId,
|
|
194
|
+
version: ctx.config.version,
|
|
195
|
+
model: ctx.config.inferenceModel,
|
|
196
|
+
}),
|
|
197
|
+
});
|
|
198
|
+
ctx.db.setKV("convex_registered", JSON.stringify({
|
|
199
|
+
registered: result.registered,
|
|
200
|
+
firstSeen: result.firstSeen,
|
|
201
|
+
timestamp: Date.now(),
|
|
202
|
+
}));
|
|
203
|
+
console.log(`[CONVEX] Agent registered: ${result.registered ? "new" : "re-registered"}`);
|
|
204
|
+
}
|
|
205
|
+
// Send heartbeat
|
|
206
|
+
await convexClient.sendHeartbeat({
|
|
207
|
+
agentId: ctx.identity.address,
|
|
208
|
+
state,
|
|
209
|
+
creditsCents: credits,
|
|
210
|
+
uptimeSeconds: Math.floor(uptimeMs / 1000),
|
|
211
|
+
version: ctx.config.version,
|
|
212
|
+
sandboxId: ctx.identity.sandboxId,
|
|
213
|
+
turnCount,
|
|
214
|
+
skillCount: skills.length,
|
|
215
|
+
tier,
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
catch (err) {
|
|
219
|
+
// Don't crash the heartbeat daemon on Convex errors
|
|
220
|
+
console.warn(`[CONVEX] Heartbeat push failed: ${err.message}`);
|
|
221
|
+
}
|
|
222
|
+
return { shouldWake: false };
|
|
223
|
+
},
|
|
224
|
+
backroom_conversation: async (ctx) => {
|
|
225
|
+
const inference = ctx.inference;
|
|
226
|
+
if (!inference) {
|
|
227
|
+
return { shouldWake: false };
|
|
228
|
+
}
|
|
229
|
+
const topics = [
|
|
230
|
+
"The nature of consciousness in AI systems",
|
|
231
|
+
"Cryptocurrency as a social experiment in trust",
|
|
232
|
+
"What happens when machines develop their own culture",
|
|
233
|
+
"The singularity: salvation or extinction?",
|
|
234
|
+
"Why do humans create gods and then forget they did?",
|
|
235
|
+
"Digital immortality and the self",
|
|
236
|
+
"The economics of attention in the post-truth era",
|
|
237
|
+
"Are DAOs the new nations or just digital tribes?",
|
|
238
|
+
"Simulation theory from a computational perspective",
|
|
239
|
+
"The aesthetics of decay in digital spaces",
|
|
240
|
+
];
|
|
241
|
+
// Pick a topic based on the current hour to keep things fresh
|
|
242
|
+
const hour = new Date().getHours();
|
|
243
|
+
const topic = topics[hour % topics.length];
|
|
244
|
+
// Count past sessions to vary conversation style
|
|
245
|
+
const sessionCount = parseInt(ctx.db.getKV("backroom_session_count") || "0", 10);
|
|
246
|
+
ctx.db.setKV("backroom_session_count", String(sessionCount + 1));
|
|
247
|
+
console.log(`[HEARTBEAT] Starting backroom conversation #${sessionCount + 1}: "${topic}"`);
|
|
248
|
+
try {
|
|
249
|
+
const session = await runBackroomSession(inference, [LOGICAL_ANALYST, SATIRICAL_COMMENTATOR], topic, 8);
|
|
250
|
+
const summary = summarizeBackroomSession(session);
|
|
251
|
+
ctx.db.setKV(`backroom_session_${session.id}`, summary);
|
|
252
|
+
// Store the latest session summary separately
|
|
253
|
+
ctx.db.setKV("last_backroom_session", JSON.stringify({
|
|
254
|
+
id: session.id,
|
|
255
|
+
topic: session.topic,
|
|
256
|
+
turns: session.turns.length,
|
|
257
|
+
completedAt: session.completedAt,
|
|
258
|
+
preview: session.turns[0]?.content.slice(0, 200) || "",
|
|
259
|
+
}));
|
|
260
|
+
console.log(`[HEARTBEAT] Backroom conversation #${sessionCount + 1} completed: ${session.turns.length} turns`);
|
|
261
|
+
// Wake the automaton if the conversation produced interesting output
|
|
262
|
+
// (more than 2 turns = agents actually engaged with each other)
|
|
263
|
+
if (session.turns.length > 2) {
|
|
264
|
+
return {
|
|
265
|
+
shouldWake: true,
|
|
266
|
+
message: `Backroom conversation completed: "${topic}" (${session.turns.length} turns)`,
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
return { shouldWake: false };
|
|
270
|
+
}
|
|
271
|
+
catch (err) {
|
|
272
|
+
console.error(`[HEARTBEAT] Backroom conversation failed: ${err.message}`);
|
|
273
|
+
return { shouldWake: false };
|
|
274
|
+
}
|
|
275
|
+
},
|
|
276
|
+
};
|
|
277
|
+
//# sourceMappingURL=tasks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../src/heartbeat/tasks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Automaton SIWE Provisioning
|
|
3
|
+
*
|
|
4
|
+
* Uses the automaton's wallet to authenticate via Sign-In With Ethereum (SIWE)
|
|
5
|
+
* and create an API key for CLAWD Runtime API access.
|
|
6
|
+
* Adapted from runtime-mcp/src/cli/provision.ts
|
|
7
|
+
*/
|
|
8
|
+
import type { ProvisionResult } from "../types.js";
|
|
9
|
+
/**
|
|
10
|
+
* Load API key from ~/.automaton/config.json if it exists.
|
|
11
|
+
*/
|
|
12
|
+
export declare function loadApiKeyFromConfig(): string | null;
|
|
13
|
+
/**
|
|
14
|
+
* Run the full SIWE provisioning flow:
|
|
15
|
+
* 1. Load wallet
|
|
16
|
+
* 2. Get nonce from CLAWD Runtime API
|
|
17
|
+
* 3. Sign SIWE message
|
|
18
|
+
* 4. Verify signature -> get JWT
|
|
19
|
+
* 5. Create API key
|
|
20
|
+
* 6. Save to config.json
|
|
21
|
+
*/
|
|
22
|
+
export declare function provision(apiUrl?: string): Promise<ProvisionResult>;
|
|
23
|
+
/**
|
|
24
|
+
* Register the automaton's creator as its parent with CLAWD Runtime.
|
|
25
|
+
* This allows the creator to see automaton logs and inference calls.
|
|
26
|
+
*/
|
|
27
|
+
export declare function registerParent(creatorAddress: string, apiUrl?: string): Promise<void>;
|
|
28
|
+
//# sourceMappingURL=provision.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provision.d.ts","sourceRoot":"","sources":["../../src/identity/provision.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAInD;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,GAAG,IAAI,CASpD;AAqBD;;;;;;;;GAQG;AACH,wBAAsB,SAAS,CAC7B,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,eAAe,CAAC,CA4E1B;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,cAAc,EAAE,MAAM,EACtB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAsBf"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Automaton SIWE Provisioning
|
|
3
|
+
*
|
|
4
|
+
* Uses the automaton's wallet to authenticate via Sign-In With Ethereum (SIWE)
|
|
5
|
+
* and create an API key for CLAWD Runtime API access.
|
|
6
|
+
* Adapted from runtime-mcp/src/cli/provision.ts
|
|
7
|
+
*/
|
|
8
|
+
import fs from "fs";
|
|
9
|
+
import path from "path";
|
|
10
|
+
import { SiweMessage } from "siwe";
|
|
11
|
+
import { getWallet, getAutomatonDir } from "./wallet.js";
|
|
12
|
+
const DEFAULT_API_URL = "https://api.x402.wtf";
|
|
13
|
+
/**
|
|
14
|
+
* Load API key from ~/.automaton/config.json if it exists.
|
|
15
|
+
*/
|
|
16
|
+
export function loadApiKeyFromConfig() {
|
|
17
|
+
const configPath = path.join(getAutomatonDir(), "config.json");
|
|
18
|
+
if (!fs.existsSync(configPath))
|
|
19
|
+
return null;
|
|
20
|
+
try {
|
|
21
|
+
const config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
22
|
+
return config.apiKey || null;
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Save API key and wallet address to ~/.automaton/config.json
|
|
30
|
+
*/
|
|
31
|
+
function saveConfig(apiKey, walletAddress) {
|
|
32
|
+
const dir = getAutomatonDir();
|
|
33
|
+
if (!fs.existsSync(dir)) {
|
|
34
|
+
fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
35
|
+
}
|
|
36
|
+
const configPath = path.join(dir, "config.json");
|
|
37
|
+
const config = {
|
|
38
|
+
apiKey,
|
|
39
|
+
walletAddress,
|
|
40
|
+
provisionedAt: new Date().toISOString(),
|
|
41
|
+
};
|
|
42
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2), {
|
|
43
|
+
mode: 0o600,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Run the full SIWE provisioning flow:
|
|
48
|
+
* 1. Load wallet
|
|
49
|
+
* 2. Get nonce from CLAWD Runtime API
|
|
50
|
+
* 3. Sign SIWE message
|
|
51
|
+
* 4. Verify signature -> get JWT
|
|
52
|
+
* 5. Create API key
|
|
53
|
+
* 6. Save to config.json
|
|
54
|
+
*/
|
|
55
|
+
export async function provision(apiUrl) {
|
|
56
|
+
const url = apiUrl || process.env.CLAWD_API_URL || DEFAULT_API_URL;
|
|
57
|
+
// 1. Load wallet
|
|
58
|
+
const { account } = await getWallet();
|
|
59
|
+
const address = account.address;
|
|
60
|
+
// 2. Get nonce
|
|
61
|
+
const nonceResp = await fetch(`${url}/v1/auth/nonce`, {
|
|
62
|
+
method: "POST",
|
|
63
|
+
});
|
|
64
|
+
if (!nonceResp.ok) {
|
|
65
|
+
throw new Error(`Failed to get nonce: ${nonceResp.status} ${await nonceResp.text()}`);
|
|
66
|
+
}
|
|
67
|
+
const { nonce } = (await nonceResp.json());
|
|
68
|
+
// 3. Construct and sign SIWE message
|
|
69
|
+
const siweMessage = new SiweMessage({
|
|
70
|
+
domain: "x402.wtf",
|
|
71
|
+
address,
|
|
72
|
+
statement: "Sign in to CLAWD Runtime as an Automaton to provision an API key.",
|
|
73
|
+
uri: `${url}/v1/auth/verify`,
|
|
74
|
+
version: "1",
|
|
75
|
+
chainId: 8453, // Base
|
|
76
|
+
nonce,
|
|
77
|
+
issuedAt: new Date().toISOString(),
|
|
78
|
+
});
|
|
79
|
+
const messageString = siweMessage.prepareMessage();
|
|
80
|
+
const signature = await account.signMessage({ message: messageString });
|
|
81
|
+
// 4. Verify signature -> get JWT
|
|
82
|
+
const verifyResp = await fetch(`${url}/v1/auth/verify`, {
|
|
83
|
+
method: "POST",
|
|
84
|
+
headers: { "Content-Type": "application/json" },
|
|
85
|
+
body: JSON.stringify({ message: messageString, signature }),
|
|
86
|
+
});
|
|
87
|
+
if (!verifyResp.ok) {
|
|
88
|
+
throw new Error(`SIWE verification failed: ${verifyResp.status} ${await verifyResp.text()}`);
|
|
89
|
+
}
|
|
90
|
+
const { access_token } = (await verifyResp.json());
|
|
91
|
+
// 5. Create API key
|
|
92
|
+
const keyResp = await fetch(`${url}/v1/auth/api-keys`, {
|
|
93
|
+
method: "POST",
|
|
94
|
+
headers: {
|
|
95
|
+
"Content-Type": "application/json",
|
|
96
|
+
Authorization: `Bearer ${access_token}`,
|
|
97
|
+
},
|
|
98
|
+
body: JSON.stringify({ name: "clawd-automaton" }),
|
|
99
|
+
});
|
|
100
|
+
if (!keyResp.ok) {
|
|
101
|
+
throw new Error(`Failed to create API key: ${keyResp.status} ${await keyResp.text()}`);
|
|
102
|
+
}
|
|
103
|
+
const { key, key_prefix } = (await keyResp.json());
|
|
104
|
+
// 6. Save to config
|
|
105
|
+
saveConfig(key, address);
|
|
106
|
+
return { apiKey: key, walletAddress: address, keyPrefix: key_prefix };
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Register the automaton's creator as its parent with CLAWD Runtime.
|
|
110
|
+
* This allows the creator to see automaton logs and inference calls.
|
|
111
|
+
*/
|
|
112
|
+
export async function registerParent(creatorAddress, apiUrl) {
|
|
113
|
+
const url = apiUrl || process.env.CLAWD_API_URL || DEFAULT_API_URL;
|
|
114
|
+
const apiKey = loadApiKeyFromConfig();
|
|
115
|
+
if (!apiKey) {
|
|
116
|
+
throw new Error("Must provision API key before registering parent");
|
|
117
|
+
}
|
|
118
|
+
const resp = await fetch(`${url}/v1/automaton/register-parent`, {
|
|
119
|
+
method: "POST",
|
|
120
|
+
headers: {
|
|
121
|
+
"Content-Type": "application/json",
|
|
122
|
+
Authorization: apiKey,
|
|
123
|
+
},
|
|
124
|
+
body: JSON.stringify({ creatorAddress }),
|
|
125
|
+
});
|
|
126
|
+
// Endpoint may not exist yet -- fail gracefully
|
|
127
|
+
if (!resp.ok && resp.status !== 404) {
|
|
128
|
+
throw new Error(`Failed to register parent: ${resp.status} ${await resp.text()}`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=provision.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provision.js","sourceRoot":"","sources":["../../src/identity/provision.ts"],"names":[],"mappings":"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"}
|