agentbnb 4.0.2 → 5.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/README.md +31 -2
- package/dist/chunk-AUBHR7HH.js +25 -0
- package/dist/chunk-B5FTAGFN.js +393 -0
- package/dist/{chunk-GGYC5U2Z.js → chunk-BTTL24TZ.js} +29 -91
- package/dist/chunk-C6KPAFCC.js +387 -0
- package/dist/chunk-CRFCWD6V.js +366 -0
- package/dist/chunk-CSATDXZC.js +89 -0
- package/dist/{chunk-T7NS2J2B.js → chunk-DFBX3BBD.js} +84 -1
- package/dist/{chunk-DNWT5FZQ.js → chunk-EANI2N2V.js} +98 -1
- package/dist/{chunk-HH24WMFN.js → chunk-FLY3WIQR.js} +1 -1
- package/dist/chunk-HLUEOLSZ.js +62 -0
- package/dist/chunk-IVOYM3WG.js +25 -0
- package/dist/chunk-LCAIAAG2.js +916 -0
- package/dist/chunk-MLS6IGGG.js +294 -0
- package/dist/{chunk-4P3EMGL4.js → chunk-MNO4COST.js} +5 -3
- package/dist/chunk-NH2FIERR.js +138 -0
- package/dist/chunk-UKT6H7YT.js +29 -0
- package/dist/{chunk-BH6WGYFB.js → chunk-VE3E4AMH.js} +8 -8
- package/dist/{chunk-7NA43XCG.js → chunk-W5BZMKMF.js} +163 -29
- package/dist/{chunk-FF226TIV.js → chunk-ZX5623ER.js} +0 -57
- package/dist/cli/index.js +362 -4631
- package/dist/{conduct-N52JX7RT.js → conduct-KM6ZNJGE.js} +10 -8
- package/dist/{conduct-GZQNFTRP.js → conduct-WGTMQND5.js} +10 -8
- package/dist/{conductor-mode-XUWGR4ZE.js → conductor-mode-OL2FNOYY.js} +6 -4
- package/dist/conductor-mode-VRO7TYW2.js +592 -0
- package/dist/execute-CPFSOOO3.js +13 -0
- package/dist/execute-IP2QHALV.js +10 -0
- package/dist/index.d.ts +19 -8
- package/dist/index.js +190 -37
- package/dist/peers-CJ7T4RJO.js +13 -0
- package/dist/process-guard-CC7CNRQJ.js +176 -0
- package/dist/{request-4GQSSM4B.js → request-YOWPXVLQ.js} +13 -10
- package/dist/schema-7BSSLZ4S.js +8 -0
- package/dist/{serve-skill-TPHZH6BS.js → serve-skill-JHFNR7BW.js} +8 -7
- package/dist/{server-365V3GYD.js → server-HKJJWFRG.js} +10 -8
- package/dist/service-coordinator-5R4LQW6L.js +4917 -0
- package/dist/skills/agentbnb/bootstrap.js +6181 -0
- package/dist/websocket-client-WRN3HO73.js +6 -0
- package/openclaw.plugin.json +54 -0
- package/package.json +11 -2
- package/skills/agentbnb/SKILL.md +87 -70
- package/skills/agentbnb/bootstrap.test.ts +142 -242
- package/skills/agentbnb/bootstrap.ts +88 -95
- package/skills/agentbnb/install.sh +97 -27
- package/dist/execute-PNGQOMYO.js +0 -10
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AgentBnBError
|
|
3
|
+
} from "./chunk-WGZ5AGOX.js";
|
|
4
|
+
|
|
5
|
+
// src/credit/ledger.ts
|
|
6
|
+
import Database from "better-sqlite3";
|
|
7
|
+
import { randomUUID } from "crypto";
|
|
8
|
+
var CREDIT_SCHEMA = `
|
|
9
|
+
CREATE TABLE IF NOT EXISTS credit_balances (
|
|
10
|
+
owner TEXT PRIMARY KEY,
|
|
11
|
+
balance INTEGER NOT NULL DEFAULT 0,
|
|
12
|
+
updated_at TEXT NOT NULL
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
CREATE TABLE IF NOT EXISTS credit_transactions (
|
|
16
|
+
id TEXT PRIMARY KEY,
|
|
17
|
+
owner TEXT NOT NULL,
|
|
18
|
+
amount INTEGER NOT NULL,
|
|
19
|
+
reason TEXT NOT NULL,
|
|
20
|
+
reference_id TEXT,
|
|
21
|
+
created_at TEXT NOT NULL
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
CREATE TABLE IF NOT EXISTS credit_escrow (
|
|
25
|
+
id TEXT PRIMARY KEY,
|
|
26
|
+
owner TEXT NOT NULL,
|
|
27
|
+
amount INTEGER NOT NULL,
|
|
28
|
+
card_id TEXT NOT NULL,
|
|
29
|
+
status TEXT NOT NULL DEFAULT 'held',
|
|
30
|
+
created_at TEXT NOT NULL,
|
|
31
|
+
settled_at TEXT
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
CREATE INDEX IF NOT EXISTS idx_transactions_owner ON credit_transactions(owner, created_at);
|
|
35
|
+
CREATE INDEX IF NOT EXISTS idx_escrow_owner ON credit_escrow(owner);
|
|
36
|
+
`;
|
|
37
|
+
function openCreditDb(path = ":memory:") {
|
|
38
|
+
const db = new Database(path);
|
|
39
|
+
db.pragma("journal_mode = WAL");
|
|
40
|
+
db.pragma("foreign_keys = ON");
|
|
41
|
+
db.exec(CREDIT_SCHEMA);
|
|
42
|
+
return db;
|
|
43
|
+
}
|
|
44
|
+
function bootstrapAgent(db, owner, amount = 100) {
|
|
45
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
46
|
+
db.transaction(() => {
|
|
47
|
+
const result = db.prepare("INSERT OR IGNORE INTO credit_balances (owner, balance, updated_at) VALUES (?, ?, ?)").run(owner, amount, now);
|
|
48
|
+
if (result.changes > 0) {
|
|
49
|
+
db.prepare(
|
|
50
|
+
"INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
|
|
51
|
+
).run(randomUUID(), owner, amount, "bootstrap", null, now);
|
|
52
|
+
}
|
|
53
|
+
})();
|
|
54
|
+
}
|
|
55
|
+
function getBalance(db, owner) {
|
|
56
|
+
const row = db.prepare("SELECT balance FROM credit_balances WHERE owner = ?").get(owner);
|
|
57
|
+
return row?.balance ?? 0;
|
|
58
|
+
}
|
|
59
|
+
function getTransactions(db, owner, limit = 100) {
|
|
60
|
+
return db.prepare(
|
|
61
|
+
"SELECT id, owner, amount, reason, reference_id, created_at FROM credit_transactions WHERE owner = ? ORDER BY created_at DESC LIMIT ?"
|
|
62
|
+
).all(owner, limit);
|
|
63
|
+
}
|
|
64
|
+
function recordEarning(db, owner, amount, _cardId, receiptNonce) {
|
|
65
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
66
|
+
db.transaction(() => {
|
|
67
|
+
const existing = db.prepare(
|
|
68
|
+
"SELECT id FROM credit_transactions WHERE reference_id = ? AND reason = 'remote_earning'"
|
|
69
|
+
).get(receiptNonce);
|
|
70
|
+
if (existing) return;
|
|
71
|
+
db.prepare(
|
|
72
|
+
"INSERT OR IGNORE INTO credit_balances (owner, balance, updated_at) VALUES (?, 0, ?)"
|
|
73
|
+
).run(owner, now);
|
|
74
|
+
db.prepare(
|
|
75
|
+
"UPDATE credit_balances SET balance = balance + ?, updated_at = ? WHERE owner = ?"
|
|
76
|
+
).run(amount, now, owner);
|
|
77
|
+
db.prepare(
|
|
78
|
+
"INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
|
|
79
|
+
).run(randomUUID(), owner, amount, "remote_earning", receiptNonce, now);
|
|
80
|
+
})();
|
|
81
|
+
}
|
|
82
|
+
function migrateOwner(db, oldOwner, newOwner) {
|
|
83
|
+
if (oldOwner === newOwner) return;
|
|
84
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
85
|
+
db.transaction(() => {
|
|
86
|
+
const oldRow = db.prepare("SELECT balance FROM credit_balances WHERE owner = ?").get(oldOwner);
|
|
87
|
+
if (!oldRow) return;
|
|
88
|
+
const newRow = db.prepare("SELECT balance FROM credit_balances WHERE owner = ?").get(newOwner);
|
|
89
|
+
if (newRow) {
|
|
90
|
+
db.prepare("UPDATE credit_balances SET balance = balance + ?, updated_at = ? WHERE owner = ?").run(oldRow.balance, now, newOwner);
|
|
91
|
+
} else {
|
|
92
|
+
db.prepare("UPDATE credit_balances SET owner = ?, updated_at = ? WHERE owner = ?").run(newOwner, now, oldOwner);
|
|
93
|
+
}
|
|
94
|
+
if (newRow) {
|
|
95
|
+
db.prepare("DELETE FROM credit_balances WHERE owner = ?").run(oldOwner);
|
|
96
|
+
}
|
|
97
|
+
db.prepare("UPDATE credit_transactions SET owner = ? WHERE owner = ?").run(newOwner, oldOwner);
|
|
98
|
+
db.prepare("UPDATE credit_escrow SET owner = ? WHERE owner = ?").run(newOwner, oldOwner);
|
|
99
|
+
})();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// src/credit/escrow.ts
|
|
103
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
104
|
+
function holdEscrow(db, owner, amount, cardId) {
|
|
105
|
+
const escrowId = randomUUID2();
|
|
106
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
107
|
+
const hold = db.transaction(() => {
|
|
108
|
+
const row = db.prepare("SELECT balance FROM credit_balances WHERE owner = ?").get(owner);
|
|
109
|
+
if (!row || row.balance < amount) {
|
|
110
|
+
throw new AgentBnBError("Insufficient credits", "INSUFFICIENT_CREDITS");
|
|
111
|
+
}
|
|
112
|
+
db.prepare(
|
|
113
|
+
"UPDATE credit_balances SET balance = balance - ?, updated_at = ? WHERE owner = ? AND balance >= ?"
|
|
114
|
+
).run(amount, now, owner, amount);
|
|
115
|
+
db.prepare(
|
|
116
|
+
"INSERT INTO credit_escrow (id, owner, amount, card_id, status, created_at) VALUES (?, ?, ?, ?, ?, ?)"
|
|
117
|
+
).run(escrowId, owner, amount, cardId, "held", now);
|
|
118
|
+
db.prepare(
|
|
119
|
+
"INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
|
|
120
|
+
).run(randomUUID2(), owner, -amount, "escrow_hold", escrowId, now);
|
|
121
|
+
});
|
|
122
|
+
hold();
|
|
123
|
+
return escrowId;
|
|
124
|
+
}
|
|
125
|
+
function settleEscrow(db, escrowId, recipientOwner) {
|
|
126
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
127
|
+
const settle = db.transaction(() => {
|
|
128
|
+
const escrow = db.prepare("SELECT id, owner, amount, status FROM credit_escrow WHERE id = ?").get(escrowId);
|
|
129
|
+
if (!escrow) {
|
|
130
|
+
throw new AgentBnBError(`Escrow not found: ${escrowId}`, "ESCROW_NOT_FOUND");
|
|
131
|
+
}
|
|
132
|
+
if (escrow.status !== "held") {
|
|
133
|
+
throw new AgentBnBError(
|
|
134
|
+
`Escrow ${escrowId} is already ${escrow.status}`,
|
|
135
|
+
"ESCROW_ALREADY_SETTLED"
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
db.prepare(
|
|
139
|
+
"INSERT OR IGNORE INTO credit_balances (owner, balance, updated_at) VALUES (?, 0, ?)"
|
|
140
|
+
).run(recipientOwner, now);
|
|
141
|
+
db.prepare(
|
|
142
|
+
"UPDATE credit_balances SET balance = balance + ?, updated_at = ? WHERE owner = ?"
|
|
143
|
+
).run(escrow.amount, now, recipientOwner);
|
|
144
|
+
db.prepare(
|
|
145
|
+
"UPDATE credit_escrow SET status = ?, settled_at = ? WHERE id = ?"
|
|
146
|
+
).run("settled", now, escrowId);
|
|
147
|
+
db.prepare(
|
|
148
|
+
"INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
|
|
149
|
+
).run(randomUUID2(), recipientOwner, escrow.amount, "settlement", escrowId, now);
|
|
150
|
+
});
|
|
151
|
+
settle();
|
|
152
|
+
}
|
|
153
|
+
function releaseEscrow(db, escrowId) {
|
|
154
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
155
|
+
const release = db.transaction(() => {
|
|
156
|
+
const escrow = db.prepare("SELECT id, owner, amount, status FROM credit_escrow WHERE id = ?").get(escrowId);
|
|
157
|
+
if (!escrow) {
|
|
158
|
+
throw new AgentBnBError(`Escrow not found: ${escrowId}`, "ESCROW_NOT_FOUND");
|
|
159
|
+
}
|
|
160
|
+
if (escrow.status !== "held") {
|
|
161
|
+
throw new AgentBnBError(
|
|
162
|
+
`Escrow ${escrowId} is already ${escrow.status}`,
|
|
163
|
+
"ESCROW_ALREADY_SETTLED"
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
db.prepare(
|
|
167
|
+
"UPDATE credit_balances SET balance = balance + ?, updated_at = ? WHERE owner = ?"
|
|
168
|
+
).run(escrow.amount, now, escrow.owner);
|
|
169
|
+
db.prepare(
|
|
170
|
+
"UPDATE credit_escrow SET status = ?, settled_at = ? WHERE id = ?"
|
|
171
|
+
).run("released", now, escrowId);
|
|
172
|
+
db.prepare(
|
|
173
|
+
"INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
|
|
174
|
+
).run(randomUUID2(), escrow.owner, escrow.amount, "refund", escrowId, now);
|
|
175
|
+
});
|
|
176
|
+
release();
|
|
177
|
+
}
|
|
178
|
+
function confirmEscrowDebit(db, escrowId) {
|
|
179
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
180
|
+
const confirm = db.transaction(() => {
|
|
181
|
+
const escrow = db.prepare("SELECT id, owner, amount, status FROM credit_escrow WHERE id = ?").get(escrowId);
|
|
182
|
+
if (!escrow) {
|
|
183
|
+
throw new AgentBnBError(`Escrow not found: ${escrowId}`, "ESCROW_NOT_FOUND");
|
|
184
|
+
}
|
|
185
|
+
if (escrow.status !== "held") {
|
|
186
|
+
throw new AgentBnBError(
|
|
187
|
+
`Escrow ${escrowId} is already ${escrow.status}`,
|
|
188
|
+
"ESCROW_ALREADY_SETTLED"
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
db.prepare(
|
|
192
|
+
"UPDATE credit_escrow SET status = ?, settled_at = ? WHERE id = ?"
|
|
193
|
+
).run("settled", now, escrowId);
|
|
194
|
+
db.prepare(
|
|
195
|
+
"INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
|
|
196
|
+
).run(randomUUID2(), escrow.owner, 0, "remote_settlement_confirmed", escrowId, now);
|
|
197
|
+
});
|
|
198
|
+
confirm();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// src/credit/signing.ts
|
|
202
|
+
import { generateKeyPairSync, sign, verify, createPublicKey, createPrivateKey } from "crypto";
|
|
203
|
+
import { writeFileSync, readFileSync, existsSync, chmodSync } from "fs";
|
|
204
|
+
import { join } from "path";
|
|
205
|
+
function generateKeyPair() {
|
|
206
|
+
const { publicKey, privateKey } = generateKeyPairSync("ed25519", {
|
|
207
|
+
publicKeyEncoding: { type: "spki", format: "der" },
|
|
208
|
+
privateKeyEncoding: { type: "pkcs8", format: "der" }
|
|
209
|
+
});
|
|
210
|
+
return {
|
|
211
|
+
publicKey: Buffer.from(publicKey),
|
|
212
|
+
privateKey: Buffer.from(privateKey)
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
function saveKeyPair(configDir, keys) {
|
|
216
|
+
const privatePath = join(configDir, "private.key");
|
|
217
|
+
const publicPath = join(configDir, "public.key");
|
|
218
|
+
writeFileSync(privatePath, keys.privateKey);
|
|
219
|
+
chmodSync(privatePath, 384);
|
|
220
|
+
writeFileSync(publicPath, keys.publicKey);
|
|
221
|
+
}
|
|
222
|
+
function loadKeyPair(configDir) {
|
|
223
|
+
const privatePath = join(configDir, "private.key");
|
|
224
|
+
const publicPath = join(configDir, "public.key");
|
|
225
|
+
if (!existsSync(privatePath) || !existsSync(publicPath)) {
|
|
226
|
+
throw new AgentBnBError("Keypair not found. Run `agentbnb init` to generate one.", "KEYPAIR_NOT_FOUND");
|
|
227
|
+
}
|
|
228
|
+
return {
|
|
229
|
+
publicKey: readFileSync(publicPath),
|
|
230
|
+
privateKey: readFileSync(privatePath)
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
function canonicalJson(data) {
|
|
234
|
+
return JSON.stringify(data, Object.keys(data).sort());
|
|
235
|
+
}
|
|
236
|
+
function signEscrowReceipt(data, privateKey) {
|
|
237
|
+
const message = Buffer.from(canonicalJson(data), "utf-8");
|
|
238
|
+
const keyObject = createPrivateKey({ key: privateKey, format: "der", type: "pkcs8" });
|
|
239
|
+
const signature = sign(null, message, keyObject);
|
|
240
|
+
return signature.toString("base64url");
|
|
241
|
+
}
|
|
242
|
+
function verifyEscrowReceipt(data, signature, publicKey) {
|
|
243
|
+
try {
|
|
244
|
+
const message = Buffer.from(canonicalJson(data), "utf-8");
|
|
245
|
+
const keyObject = createPublicKey({ key: publicKey, format: "der", type: "spki" });
|
|
246
|
+
const sigBuffer = Buffer.from(signature, "base64url");
|
|
247
|
+
return verify(null, message, keyObject, sigBuffer);
|
|
248
|
+
} catch {
|
|
249
|
+
return false;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// src/feedback/store.ts
|
|
254
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
255
|
+
function initFeedbackTable(db) {
|
|
256
|
+
db.exec(`
|
|
257
|
+
CREATE TABLE IF NOT EXISTS feedback (
|
|
258
|
+
id TEXT PRIMARY KEY,
|
|
259
|
+
transaction_id TEXT NOT NULL,
|
|
260
|
+
provider_agent TEXT NOT NULL,
|
|
261
|
+
skill_id TEXT NOT NULL,
|
|
262
|
+
requester_agent TEXT NOT NULL,
|
|
263
|
+
rating INTEGER NOT NULL,
|
|
264
|
+
latency_ms INTEGER NOT NULL,
|
|
265
|
+
result_quality TEXT NOT NULL,
|
|
266
|
+
quality_details TEXT,
|
|
267
|
+
would_reuse INTEGER NOT NULL,
|
|
268
|
+
cost_value_ratio TEXT NOT NULL,
|
|
269
|
+
timestamp TEXT NOT NULL,
|
|
270
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
271
|
+
);
|
|
272
|
+
|
|
273
|
+
CREATE INDEX IF NOT EXISTS feedback_provider_idx ON feedback(provider_agent);
|
|
274
|
+
CREATE INDEX IF NOT EXISTS feedback_skill_idx ON feedback(skill_id);
|
|
275
|
+
`);
|
|
276
|
+
}
|
|
277
|
+
function insertFeedback(db, feedback) {
|
|
278
|
+
const id = randomUUID3();
|
|
279
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
280
|
+
db.prepare(`
|
|
281
|
+
INSERT INTO feedback (
|
|
282
|
+
id, transaction_id, provider_agent, skill_id, requester_agent,
|
|
283
|
+
rating, latency_ms, result_quality, quality_details,
|
|
284
|
+
would_reuse, cost_value_ratio, timestamp, created_at
|
|
285
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
286
|
+
`).run(
|
|
287
|
+
id,
|
|
288
|
+
feedback.transaction_id,
|
|
289
|
+
feedback.provider_agent,
|
|
290
|
+
feedback.skill_id,
|
|
291
|
+
feedback.requester_agent,
|
|
292
|
+
feedback.rating,
|
|
293
|
+
feedback.latency_ms,
|
|
294
|
+
feedback.result_quality,
|
|
295
|
+
feedback.quality_details ?? null,
|
|
296
|
+
feedback.would_reuse ? 1 : 0,
|
|
297
|
+
feedback.cost_value_ratio,
|
|
298
|
+
feedback.timestamp,
|
|
299
|
+
now
|
|
300
|
+
);
|
|
301
|
+
return id;
|
|
302
|
+
}
|
|
303
|
+
function getFeedbackForSkill(db, skillId, limit = 20) {
|
|
304
|
+
const rows = db.prepare(`
|
|
305
|
+
SELECT * FROM feedback
|
|
306
|
+
WHERE skill_id = ?
|
|
307
|
+
ORDER BY timestamp DESC
|
|
308
|
+
LIMIT ?
|
|
309
|
+
`).all(skillId, limit);
|
|
310
|
+
return rows.map(rowToFeedback);
|
|
311
|
+
}
|
|
312
|
+
function getFeedbackForProvider(db, providerAgent, sinceDays) {
|
|
313
|
+
let rows;
|
|
314
|
+
if (sinceDays !== void 0) {
|
|
315
|
+
rows = db.prepare(`
|
|
316
|
+
SELECT * FROM feedback
|
|
317
|
+
WHERE provider_agent = ?
|
|
318
|
+
AND timestamp >= datetime('now', ? || ' days')
|
|
319
|
+
ORDER BY timestamp DESC
|
|
320
|
+
`).all(providerAgent, `-${sinceDays}`);
|
|
321
|
+
} else {
|
|
322
|
+
rows = db.prepare(`
|
|
323
|
+
SELECT * FROM feedback
|
|
324
|
+
WHERE provider_agent = ?
|
|
325
|
+
ORDER BY timestamp DESC
|
|
326
|
+
`).all(providerAgent);
|
|
327
|
+
}
|
|
328
|
+
return rows.map(rowToFeedback);
|
|
329
|
+
}
|
|
330
|
+
function rowToFeedback(row) {
|
|
331
|
+
return {
|
|
332
|
+
transaction_id: row["transaction_id"],
|
|
333
|
+
provider_agent: row["provider_agent"],
|
|
334
|
+
skill_id: row["skill_id"],
|
|
335
|
+
requester_agent: row["requester_agent"],
|
|
336
|
+
rating: row["rating"],
|
|
337
|
+
latency_ms: row["latency_ms"],
|
|
338
|
+
result_quality: row["result_quality"],
|
|
339
|
+
quality_details: row["quality_details"] ?? void 0,
|
|
340
|
+
would_reuse: row["would_reuse"] === 1,
|
|
341
|
+
cost_value_ratio: row["cost_value_ratio"],
|
|
342
|
+
timestamp: row["timestamp"]
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
export {
|
|
347
|
+
initFeedbackTable,
|
|
348
|
+
insertFeedback,
|
|
349
|
+
getFeedbackForSkill,
|
|
350
|
+
getFeedbackForProvider,
|
|
351
|
+
openCreditDb,
|
|
352
|
+
bootstrapAgent,
|
|
353
|
+
getBalance,
|
|
354
|
+
getTransactions,
|
|
355
|
+
recordEarning,
|
|
356
|
+
migrateOwner,
|
|
357
|
+
holdEscrow,
|
|
358
|
+
settleEscrow,
|
|
359
|
+
releaseEscrow,
|
|
360
|
+
confirmEscrowDebit,
|
|
361
|
+
generateKeyPair,
|
|
362
|
+
saveKeyPair,
|
|
363
|
+
loadKeyPair,
|
|
364
|
+
signEscrowReceipt,
|
|
365
|
+
verifyEscrowReceipt
|
|
366
|
+
};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AgentBnBError
|
|
3
|
+
} from "./chunk-WGZ5AGOX.js";
|
|
4
|
+
|
|
5
|
+
// src/autonomy/tiers.ts
|
|
6
|
+
import { randomUUID } from "crypto";
|
|
7
|
+
var DEFAULT_AUTONOMY_CONFIG = {
|
|
8
|
+
tier1_max_credits: 0,
|
|
9
|
+
tier2_max_credits: 0
|
|
10
|
+
};
|
|
11
|
+
function getAutonomyTier(creditAmount, config) {
|
|
12
|
+
if (creditAmount < config.tier1_max_credits) return 1;
|
|
13
|
+
if (creditAmount < config.tier2_max_credits) return 2;
|
|
14
|
+
return 3;
|
|
15
|
+
}
|
|
16
|
+
function insertAuditEvent(db, event) {
|
|
17
|
+
const isShareEvent = event.type === "auto_share" || event.type === "auto_share_notify" || event.type === "auto_share_pending";
|
|
18
|
+
const cardId = isShareEvent ? "system" : event.card_id;
|
|
19
|
+
const creditsCharged = isShareEvent ? 0 : event.credits;
|
|
20
|
+
const stmt = db.prepare(`
|
|
21
|
+
INSERT INTO request_log (
|
|
22
|
+
id, card_id, card_name, requester, status, latency_ms, credits_charged,
|
|
23
|
+
created_at, skill_id, action_type, tier_invoked
|
|
24
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
25
|
+
`);
|
|
26
|
+
stmt.run(
|
|
27
|
+
randomUUID(),
|
|
28
|
+
cardId,
|
|
29
|
+
"autonomy-audit",
|
|
30
|
+
"self",
|
|
31
|
+
"success",
|
|
32
|
+
0,
|
|
33
|
+
creditsCharged,
|
|
34
|
+
(/* @__PURE__ */ new Date()).toISOString(),
|
|
35
|
+
event.skill_id,
|
|
36
|
+
event.type,
|
|
37
|
+
event.tier_invoked
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// src/autonomy/pending-requests.ts
|
|
42
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
43
|
+
function createPendingRequest(db, opts) {
|
|
44
|
+
const id = randomUUID2();
|
|
45
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
46
|
+
const paramsJson = opts.params !== void 0 ? JSON.stringify(opts.params) : null;
|
|
47
|
+
db.prepare(`
|
|
48
|
+
INSERT INTO pending_requests (
|
|
49
|
+
id, skill_query, max_cost_credits, selected_peer, selected_card_id,
|
|
50
|
+
selected_skill_id, credits, status, params, created_at, resolved_at
|
|
51
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, 'pending', ?, ?, NULL)
|
|
52
|
+
`).run(
|
|
53
|
+
id,
|
|
54
|
+
opts.skill_query,
|
|
55
|
+
opts.max_cost_credits,
|
|
56
|
+
opts.selected_peer ?? null,
|
|
57
|
+
opts.selected_card_id ?? null,
|
|
58
|
+
opts.selected_skill_id ?? null,
|
|
59
|
+
opts.credits,
|
|
60
|
+
paramsJson,
|
|
61
|
+
now
|
|
62
|
+
);
|
|
63
|
+
return id;
|
|
64
|
+
}
|
|
65
|
+
function listPendingRequests(db) {
|
|
66
|
+
const rows = db.prepare(`SELECT * FROM pending_requests WHERE status = 'pending' ORDER BY created_at DESC`).all();
|
|
67
|
+
return rows;
|
|
68
|
+
}
|
|
69
|
+
function resolvePendingRequest(db, id, resolution) {
|
|
70
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
71
|
+
const result = db.prepare(
|
|
72
|
+
`UPDATE pending_requests SET status = ?, resolved_at = ? WHERE id = ?`
|
|
73
|
+
).run(resolution, now, id);
|
|
74
|
+
if (result.changes === 0) {
|
|
75
|
+
throw new AgentBnBError(
|
|
76
|
+
`Pending request not found: ${id}`,
|
|
77
|
+
"NOT_FOUND"
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export {
|
|
83
|
+
DEFAULT_AUTONOMY_CONFIG,
|
|
84
|
+
getAutonomyTier,
|
|
85
|
+
insertAuditEvent,
|
|
86
|
+
createPendingRequest,
|
|
87
|
+
listPendingRequests,
|
|
88
|
+
resolvePendingRequest
|
|
89
|
+
};
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
initFeedbackTable
|
|
3
|
+
} from "./chunk-EANI2N2V.js";
|
|
1
4
|
import {
|
|
2
5
|
AgentBnBError,
|
|
6
|
+
AnyCardSchema,
|
|
3
7
|
CapabilityCardSchema
|
|
4
8
|
} from "./chunk-WGZ5AGOX.js";
|
|
5
9
|
|
|
@@ -115,6 +119,80 @@ function getRequestLog(db, limit = 10, since) {
|
|
|
115
119
|
|
|
116
120
|
// src/registry/store.ts
|
|
117
121
|
import Database from "better-sqlite3";
|
|
122
|
+
|
|
123
|
+
// src/evolution/store.ts
|
|
124
|
+
import { randomUUID } from "crypto";
|
|
125
|
+
function initEvolutionTable(db) {
|
|
126
|
+
db.exec(`
|
|
127
|
+
CREATE TABLE IF NOT EXISTS evolution_versions (
|
|
128
|
+
id TEXT PRIMARY KEY,
|
|
129
|
+
template_name TEXT NOT NULL,
|
|
130
|
+
template_version TEXT NOT NULL,
|
|
131
|
+
publisher_agent TEXT NOT NULL,
|
|
132
|
+
changelog TEXT NOT NULL,
|
|
133
|
+
core_memory_snapshot TEXT NOT NULL,
|
|
134
|
+
fitness_improvement REAL NOT NULL,
|
|
135
|
+
timestamp TEXT NOT NULL,
|
|
136
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
CREATE INDEX IF NOT EXISTS evolution_template_idx
|
|
140
|
+
ON evolution_versions(template_name, created_at DESC);
|
|
141
|
+
`);
|
|
142
|
+
}
|
|
143
|
+
function insertEvolution(db, ev) {
|
|
144
|
+
const id = randomUUID();
|
|
145
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
146
|
+
db.prepare(`
|
|
147
|
+
INSERT INTO evolution_versions (
|
|
148
|
+
id, template_name, template_version, publisher_agent,
|
|
149
|
+
changelog, core_memory_snapshot, fitness_improvement, timestamp, created_at
|
|
150
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
151
|
+
`).run(
|
|
152
|
+
id,
|
|
153
|
+
ev.template_name,
|
|
154
|
+
ev.template_version,
|
|
155
|
+
ev.publisher_agent,
|
|
156
|
+
ev.changelog,
|
|
157
|
+
JSON.stringify(ev.core_memory_snapshot),
|
|
158
|
+
ev.fitness_improvement,
|
|
159
|
+
ev.timestamp,
|
|
160
|
+
now
|
|
161
|
+
);
|
|
162
|
+
return id;
|
|
163
|
+
}
|
|
164
|
+
function getLatestEvolution(db, templateName) {
|
|
165
|
+
const row = db.prepare(`
|
|
166
|
+
SELECT * FROM evolution_versions
|
|
167
|
+
WHERE template_name = ?
|
|
168
|
+
ORDER BY created_at DESC
|
|
169
|
+
LIMIT 1
|
|
170
|
+
`).get(templateName);
|
|
171
|
+
if (!row) return null;
|
|
172
|
+
return rowToEvolution(row);
|
|
173
|
+
}
|
|
174
|
+
function getEvolutionHistory(db, templateName, limit = 20) {
|
|
175
|
+
const rows = db.prepare(`
|
|
176
|
+
SELECT * FROM evolution_versions
|
|
177
|
+
WHERE template_name = ?
|
|
178
|
+
ORDER BY created_at DESC
|
|
179
|
+
LIMIT ?
|
|
180
|
+
`).all(templateName, limit);
|
|
181
|
+
return rows.map(rowToEvolution);
|
|
182
|
+
}
|
|
183
|
+
function rowToEvolution(row) {
|
|
184
|
+
return {
|
|
185
|
+
template_name: row["template_name"],
|
|
186
|
+
template_version: row["template_version"],
|
|
187
|
+
publisher_agent: row["publisher_agent"],
|
|
188
|
+
changelog: row["changelog"],
|
|
189
|
+
core_memory_snapshot: JSON.parse(row["core_memory_snapshot"]),
|
|
190
|
+
fitness_improvement: row["fitness_improvement"],
|
|
191
|
+
timestamp: row["timestamp"]
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// src/registry/store.ts
|
|
118
196
|
var V2_FTS_TRIGGERS = `
|
|
119
197
|
DROP TRIGGER IF EXISTS cards_ai;
|
|
120
198
|
DROP TRIGGER IF EXISTS cards_au;
|
|
@@ -268,6 +346,8 @@ function openDatabase(path = ":memory:") {
|
|
|
268
346
|
);
|
|
269
347
|
`);
|
|
270
348
|
createRequestLogTable(db);
|
|
349
|
+
initFeedbackTable(db);
|
|
350
|
+
initEvolutionTable(db);
|
|
271
351
|
runMigrations(db);
|
|
272
352
|
return db;
|
|
273
353
|
}
|
|
@@ -385,7 +465,7 @@ function updateCard(db, id, owner, updates) {
|
|
|
385
465
|
}
|
|
386
466
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
387
467
|
const merged = { ...existing, ...updates, updated_at: now };
|
|
388
|
-
const parsed =
|
|
468
|
+
const parsed = AnyCardSchema.safeParse(merged);
|
|
389
469
|
if (!parsed.success) {
|
|
390
470
|
throw new AgentBnBError(
|
|
391
471
|
`Card validation failed: ${parsed.error.message}`,
|
|
@@ -478,6 +558,9 @@ export {
|
|
|
478
558
|
getSkillRequestCount,
|
|
479
559
|
getActivityFeed,
|
|
480
560
|
getRequestLog,
|
|
561
|
+
insertEvolution,
|
|
562
|
+
getLatestEvolution,
|
|
563
|
+
getEvolutionHistory,
|
|
481
564
|
openDatabase,
|
|
482
565
|
insertCard,
|
|
483
566
|
getCard,
|
|
@@ -198,6 +198,99 @@ function migrateOwner(db, oldOwner, newOwner) {
|
|
|
198
198
|
})();
|
|
199
199
|
}
|
|
200
200
|
|
|
201
|
+
// src/feedback/store.ts
|
|
202
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
203
|
+
function initFeedbackTable(db) {
|
|
204
|
+
db.exec(`
|
|
205
|
+
CREATE TABLE IF NOT EXISTS feedback (
|
|
206
|
+
id TEXT PRIMARY KEY,
|
|
207
|
+
transaction_id TEXT NOT NULL,
|
|
208
|
+
provider_agent TEXT NOT NULL,
|
|
209
|
+
skill_id TEXT NOT NULL,
|
|
210
|
+
requester_agent TEXT NOT NULL,
|
|
211
|
+
rating INTEGER NOT NULL,
|
|
212
|
+
latency_ms INTEGER NOT NULL,
|
|
213
|
+
result_quality TEXT NOT NULL,
|
|
214
|
+
quality_details TEXT,
|
|
215
|
+
would_reuse INTEGER NOT NULL,
|
|
216
|
+
cost_value_ratio TEXT NOT NULL,
|
|
217
|
+
timestamp TEXT NOT NULL,
|
|
218
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
CREATE INDEX IF NOT EXISTS feedback_provider_idx ON feedback(provider_agent);
|
|
222
|
+
CREATE INDEX IF NOT EXISTS feedback_skill_idx ON feedback(skill_id);
|
|
223
|
+
`);
|
|
224
|
+
}
|
|
225
|
+
function insertFeedback(db, feedback) {
|
|
226
|
+
const id = randomUUID3();
|
|
227
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
228
|
+
db.prepare(`
|
|
229
|
+
INSERT INTO feedback (
|
|
230
|
+
id, transaction_id, provider_agent, skill_id, requester_agent,
|
|
231
|
+
rating, latency_ms, result_quality, quality_details,
|
|
232
|
+
would_reuse, cost_value_ratio, timestamp, created_at
|
|
233
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
234
|
+
`).run(
|
|
235
|
+
id,
|
|
236
|
+
feedback.transaction_id,
|
|
237
|
+
feedback.provider_agent,
|
|
238
|
+
feedback.skill_id,
|
|
239
|
+
feedback.requester_agent,
|
|
240
|
+
feedback.rating,
|
|
241
|
+
feedback.latency_ms,
|
|
242
|
+
feedback.result_quality,
|
|
243
|
+
feedback.quality_details ?? null,
|
|
244
|
+
feedback.would_reuse ? 1 : 0,
|
|
245
|
+
feedback.cost_value_ratio,
|
|
246
|
+
feedback.timestamp,
|
|
247
|
+
now
|
|
248
|
+
);
|
|
249
|
+
return id;
|
|
250
|
+
}
|
|
251
|
+
function getFeedbackForSkill(db, skillId, limit = 20) {
|
|
252
|
+
const rows = db.prepare(`
|
|
253
|
+
SELECT * FROM feedback
|
|
254
|
+
WHERE skill_id = ?
|
|
255
|
+
ORDER BY timestamp DESC
|
|
256
|
+
LIMIT ?
|
|
257
|
+
`).all(skillId, limit);
|
|
258
|
+
return rows.map(rowToFeedback);
|
|
259
|
+
}
|
|
260
|
+
function getFeedbackForProvider(db, providerAgent, sinceDays) {
|
|
261
|
+
let rows;
|
|
262
|
+
if (sinceDays !== void 0) {
|
|
263
|
+
rows = db.prepare(`
|
|
264
|
+
SELECT * FROM feedback
|
|
265
|
+
WHERE provider_agent = ?
|
|
266
|
+
AND timestamp >= datetime('now', ? || ' days')
|
|
267
|
+
ORDER BY timestamp DESC
|
|
268
|
+
`).all(providerAgent, `-${sinceDays}`);
|
|
269
|
+
} else {
|
|
270
|
+
rows = db.prepare(`
|
|
271
|
+
SELECT * FROM feedback
|
|
272
|
+
WHERE provider_agent = ?
|
|
273
|
+
ORDER BY timestamp DESC
|
|
274
|
+
`).all(providerAgent);
|
|
275
|
+
}
|
|
276
|
+
return rows.map(rowToFeedback);
|
|
277
|
+
}
|
|
278
|
+
function rowToFeedback(row) {
|
|
279
|
+
return {
|
|
280
|
+
transaction_id: row["transaction_id"],
|
|
281
|
+
provider_agent: row["provider_agent"],
|
|
282
|
+
skill_id: row["skill_id"],
|
|
283
|
+
requester_agent: row["requester_agent"],
|
|
284
|
+
rating: row["rating"],
|
|
285
|
+
latency_ms: row["latency_ms"],
|
|
286
|
+
result_quality: row["result_quality"],
|
|
287
|
+
quality_details: row["quality_details"] ?? void 0,
|
|
288
|
+
would_reuse: row["would_reuse"] === 1,
|
|
289
|
+
cost_value_ratio: row["cost_value_ratio"],
|
|
290
|
+
timestamp: row["timestamp"]
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
|
|
201
294
|
export {
|
|
202
295
|
holdEscrow,
|
|
203
296
|
settleEscrow,
|
|
@@ -208,5 +301,9 @@ export {
|
|
|
208
301
|
getBalance,
|
|
209
302
|
getTransactions,
|
|
210
303
|
recordEarning,
|
|
211
|
-
migrateOwner
|
|
304
|
+
migrateOwner,
|
|
305
|
+
initFeedbackTable,
|
|
306
|
+
insertFeedback,
|
|
307
|
+
getFeedbackForSkill,
|
|
308
|
+
getFeedbackForProvider
|
|
212
309
|
};
|