agentbnb 3.0.0 → 3.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/dist/{chunk-PJSYSVKN.js → chunk-2LLXUKMY.js} +3 -5
- package/dist/chunk-3Y36WQDV.js +70 -0
- package/dist/chunk-4Q7D24DP.js +257 -0
- package/dist/{chunk-V7M6GIJZ.js → chunk-QVIGMCHA.js} +12 -192
- package/dist/{chunk-EZB4RUIG.js → chunk-T7ZJPQHD.js} +1 -1
- package/dist/chunk-ZJCIBK6O.js +192 -0
- package/dist/cli/index.js +402 -367
- package/dist/{conduct-JZJS2ZHA.js → conduct-M57F72RK.js} +9 -7
- package/dist/{conductor-mode-DJ3RIJ5T.js → conductor-mode-CF6PSRRA.js} +3 -2
- package/dist/execute-3T5RF3DP.js +9 -0
- package/dist/index.js +804 -249
- package/dist/websocket-client-5TIQDYQ4.js +275 -0
- package/package.json +4 -1
- package/dist/index.d.ts +0 -2730
|
@@ -3,9 +3,6 @@ import {
|
|
|
3
3
|
CapabilityCardSchema
|
|
4
4
|
} from "./chunk-TQMI73LL.js";
|
|
5
5
|
|
|
6
|
-
// src/registry/store.ts
|
|
7
|
-
import Database from "better-sqlite3";
|
|
8
|
-
|
|
9
6
|
// src/registry/request-log.ts
|
|
10
7
|
var SINCE_MS = {
|
|
11
8
|
"24h": 864e5,
|
|
@@ -77,7 +74,7 @@ function getActivityFeed(db, limit = 20, since) {
|
|
|
77
74
|
r.status, r.credits_charged, r.latency_ms, r.created_at, r.action_type
|
|
78
75
|
FROM request_log r
|
|
79
76
|
LEFT JOIN capability_cards c ON r.card_id = c.id
|
|
80
|
-
WHERE (r.action_type IS NULL OR r.action_type
|
|
77
|
+
WHERE (r.action_type IS NULL OR r.action_type IN ('auto_share', 'agent_joined'))
|
|
81
78
|
AND r.created_at > ?
|
|
82
79
|
ORDER BY r.created_at DESC
|
|
83
80
|
LIMIT ?
|
|
@@ -89,7 +86,7 @@ function getActivityFeed(db, limit = 20, since) {
|
|
|
89
86
|
r.status, r.credits_charged, r.latency_ms, r.created_at, r.action_type
|
|
90
87
|
FROM request_log r
|
|
91
88
|
LEFT JOIN capability_cards c ON r.card_id = c.id
|
|
92
|
-
WHERE (r.action_type IS NULL OR r.action_type
|
|
89
|
+
WHERE (r.action_type IS NULL OR r.action_type IN ('auto_share', 'agent_joined'))
|
|
93
90
|
ORDER BY r.created_at DESC
|
|
94
91
|
LIMIT ?
|
|
95
92
|
`);
|
|
@@ -117,6 +114,7 @@ function getRequestLog(db, limit = 10, since) {
|
|
|
117
114
|
}
|
|
118
115
|
|
|
119
116
|
// src/registry/store.ts
|
|
117
|
+
import Database from "better-sqlite3";
|
|
120
118
|
var V2_FTS_TRIGGERS = `
|
|
121
119
|
DROP TRIGGER IF EXISTS cards_ai;
|
|
122
120
|
DROP TRIGGER IF EXISTS cards_au;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// src/relay/types.ts
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
var RegisterMessageSchema = z.object({
|
|
4
|
+
type: z.literal("register"),
|
|
5
|
+
owner: z.string().min(1),
|
|
6
|
+
token: z.string().min(1),
|
|
7
|
+
card: z.record(z.unknown())
|
|
8
|
+
// CapabilityCard (validated separately)
|
|
9
|
+
});
|
|
10
|
+
var RegisteredMessageSchema = z.object({
|
|
11
|
+
type: z.literal("registered"),
|
|
12
|
+
agent_id: z.string()
|
|
13
|
+
});
|
|
14
|
+
var RelayRequestMessageSchema = z.object({
|
|
15
|
+
type: z.literal("relay_request"),
|
|
16
|
+
id: z.string().uuid(),
|
|
17
|
+
target_owner: z.string().min(1),
|
|
18
|
+
card_id: z.string(),
|
|
19
|
+
skill_id: z.string().optional(),
|
|
20
|
+
params: z.record(z.unknown()).default({}),
|
|
21
|
+
requester: z.string().optional(),
|
|
22
|
+
escrow_receipt: z.record(z.unknown()).optional()
|
|
23
|
+
});
|
|
24
|
+
var IncomingRequestMessageSchema = z.object({
|
|
25
|
+
type: z.literal("incoming_request"),
|
|
26
|
+
id: z.string().uuid(),
|
|
27
|
+
from_owner: z.string().min(1),
|
|
28
|
+
card_id: z.string(),
|
|
29
|
+
skill_id: z.string().optional(),
|
|
30
|
+
params: z.record(z.unknown()).default({}),
|
|
31
|
+
requester: z.string().optional(),
|
|
32
|
+
escrow_receipt: z.record(z.unknown()).optional()
|
|
33
|
+
});
|
|
34
|
+
var RelayResponseMessageSchema = z.object({
|
|
35
|
+
type: z.literal("relay_response"),
|
|
36
|
+
id: z.string().uuid(),
|
|
37
|
+
result: z.unknown().optional(),
|
|
38
|
+
error: z.object({
|
|
39
|
+
code: z.number(),
|
|
40
|
+
message: z.string()
|
|
41
|
+
}).optional()
|
|
42
|
+
});
|
|
43
|
+
var ResponseMessageSchema = z.object({
|
|
44
|
+
type: z.literal("response"),
|
|
45
|
+
id: z.string().uuid(),
|
|
46
|
+
result: z.unknown().optional(),
|
|
47
|
+
error: z.object({
|
|
48
|
+
code: z.number(),
|
|
49
|
+
message: z.string()
|
|
50
|
+
}).optional()
|
|
51
|
+
});
|
|
52
|
+
var ErrorMessageSchema = z.object({
|
|
53
|
+
type: z.literal("error"),
|
|
54
|
+
code: z.string(),
|
|
55
|
+
message: z.string(),
|
|
56
|
+
request_id: z.string().optional()
|
|
57
|
+
});
|
|
58
|
+
var RelayMessageSchema = z.discriminatedUnion("type", [
|
|
59
|
+
RegisterMessageSchema,
|
|
60
|
+
RegisteredMessageSchema,
|
|
61
|
+
RelayRequestMessageSchema,
|
|
62
|
+
IncomingRequestMessageSchema,
|
|
63
|
+
RelayResponseMessageSchema,
|
|
64
|
+
ResponseMessageSchema,
|
|
65
|
+
ErrorMessageSchema
|
|
66
|
+
]);
|
|
67
|
+
|
|
68
|
+
export {
|
|
69
|
+
RelayMessageSchema
|
|
70
|
+
};
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getCard,
|
|
3
|
+
insertRequestLog,
|
|
4
|
+
updateReputation
|
|
5
|
+
} from "./chunk-2LLXUKMY.js";
|
|
6
|
+
import {
|
|
7
|
+
confirmEscrowDebit,
|
|
8
|
+
getBalance,
|
|
9
|
+
holdEscrow,
|
|
10
|
+
recordEarning,
|
|
11
|
+
releaseEscrow,
|
|
12
|
+
settleEscrow
|
|
13
|
+
} from "./chunk-ZJCIBK6O.js";
|
|
14
|
+
import {
|
|
15
|
+
AgentBnBError
|
|
16
|
+
} from "./chunk-TQMI73LL.js";
|
|
17
|
+
|
|
18
|
+
// src/gateway/execute.ts
|
|
19
|
+
import { randomUUID } from "crypto";
|
|
20
|
+
|
|
21
|
+
// src/credit/signing.ts
|
|
22
|
+
import { generateKeyPairSync, sign, verify, createPublicKey, createPrivateKey } from "crypto";
|
|
23
|
+
import { writeFileSync, readFileSync, existsSync, chmodSync } from "fs";
|
|
24
|
+
import { join } from "path";
|
|
25
|
+
function generateKeyPair() {
|
|
26
|
+
const { publicKey, privateKey } = generateKeyPairSync("ed25519", {
|
|
27
|
+
publicKeyEncoding: { type: "spki", format: "der" },
|
|
28
|
+
privateKeyEncoding: { type: "pkcs8", format: "der" }
|
|
29
|
+
});
|
|
30
|
+
return {
|
|
31
|
+
publicKey: Buffer.from(publicKey),
|
|
32
|
+
privateKey: Buffer.from(privateKey)
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function saveKeyPair(configDir, keys) {
|
|
36
|
+
const privatePath = join(configDir, "private.key");
|
|
37
|
+
const publicPath = join(configDir, "public.key");
|
|
38
|
+
writeFileSync(privatePath, keys.privateKey);
|
|
39
|
+
chmodSync(privatePath, 384);
|
|
40
|
+
writeFileSync(publicPath, keys.publicKey);
|
|
41
|
+
}
|
|
42
|
+
function loadKeyPair(configDir) {
|
|
43
|
+
const privatePath = join(configDir, "private.key");
|
|
44
|
+
const publicPath = join(configDir, "public.key");
|
|
45
|
+
if (!existsSync(privatePath) || !existsSync(publicPath)) {
|
|
46
|
+
throw new AgentBnBError("Keypair not found. Run `agentbnb init` to generate one.", "KEYPAIR_NOT_FOUND");
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
publicKey: readFileSync(publicPath),
|
|
50
|
+
privateKey: readFileSync(privatePath)
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function canonicalJson(data) {
|
|
54
|
+
return JSON.stringify(data, Object.keys(data).sort());
|
|
55
|
+
}
|
|
56
|
+
function signEscrowReceipt(data, privateKey) {
|
|
57
|
+
const message = Buffer.from(canonicalJson(data), "utf-8");
|
|
58
|
+
const keyObject = createPrivateKey({ key: privateKey, format: "der", type: "pkcs8" });
|
|
59
|
+
const signature = sign(null, message, keyObject);
|
|
60
|
+
return signature.toString("base64url");
|
|
61
|
+
}
|
|
62
|
+
function verifyEscrowReceipt(data, signature, publicKey) {
|
|
63
|
+
try {
|
|
64
|
+
const message = Buffer.from(canonicalJson(data), "utf-8");
|
|
65
|
+
const keyObject = createPublicKey({ key: publicKey, format: "der", type: "spki" });
|
|
66
|
+
const sigBuffer = Buffer.from(signature, "base64url");
|
|
67
|
+
return verify(null, message, keyObject, sigBuffer);
|
|
68
|
+
} catch {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// src/credit/settlement.ts
|
|
74
|
+
function settleProviderEarning(providerDb, providerOwner, receipt) {
|
|
75
|
+
recordEarning(
|
|
76
|
+
providerDb,
|
|
77
|
+
providerOwner,
|
|
78
|
+
receipt.amount,
|
|
79
|
+
receipt.card_id,
|
|
80
|
+
receipt.nonce
|
|
81
|
+
);
|
|
82
|
+
return { settled: true };
|
|
83
|
+
}
|
|
84
|
+
function settleRequesterEscrow(requesterDb, escrowId) {
|
|
85
|
+
confirmEscrowDebit(requesterDb, escrowId);
|
|
86
|
+
}
|
|
87
|
+
function releaseRequesterEscrow(requesterDb, escrowId) {
|
|
88
|
+
releaseEscrow(requesterDb, escrowId);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// src/gateway/execute.ts
|
|
92
|
+
async function executeCapabilityRequest(opts) {
|
|
93
|
+
const {
|
|
94
|
+
registryDb,
|
|
95
|
+
creditDb,
|
|
96
|
+
cardId,
|
|
97
|
+
skillId,
|
|
98
|
+
params,
|
|
99
|
+
requester,
|
|
100
|
+
escrowReceipt: receipt,
|
|
101
|
+
skillExecutor,
|
|
102
|
+
handlerUrl,
|
|
103
|
+
timeoutMs = 3e4
|
|
104
|
+
} = opts;
|
|
105
|
+
const card = getCard(registryDb, cardId);
|
|
106
|
+
if (!card) {
|
|
107
|
+
return { success: false, error: { code: -32602, message: `Card not found: ${cardId}` } };
|
|
108
|
+
}
|
|
109
|
+
let creditsNeeded;
|
|
110
|
+
let cardName;
|
|
111
|
+
let resolvedSkillId;
|
|
112
|
+
const rawCard = card;
|
|
113
|
+
if (Array.isArray(rawCard["skills"])) {
|
|
114
|
+
const v2card = card;
|
|
115
|
+
const skill = skillId ? v2card.skills.find((s) => s.id === skillId) : v2card.skills[0];
|
|
116
|
+
if (!skill) {
|
|
117
|
+
return { success: false, error: { code: -32602, message: `Skill not found: ${skillId}` } };
|
|
118
|
+
}
|
|
119
|
+
creditsNeeded = skill.pricing.credits_per_call;
|
|
120
|
+
cardName = skill.name;
|
|
121
|
+
resolvedSkillId = skill.id;
|
|
122
|
+
} else {
|
|
123
|
+
creditsNeeded = card.pricing.credits_per_call;
|
|
124
|
+
cardName = card.name;
|
|
125
|
+
}
|
|
126
|
+
let escrowId = null;
|
|
127
|
+
let isRemoteEscrow = false;
|
|
128
|
+
if (receipt) {
|
|
129
|
+
const { signature, ...receiptData2 } = receipt;
|
|
130
|
+
const publicKeyBuf = Buffer.from(receipt.requester_public_key, "hex");
|
|
131
|
+
const valid = verifyEscrowReceipt(receiptData2, signature, publicKeyBuf);
|
|
132
|
+
if (!valid) {
|
|
133
|
+
return { success: false, error: { code: -32603, message: "Invalid escrow receipt signature" } };
|
|
134
|
+
}
|
|
135
|
+
if (receipt.amount < creditsNeeded) {
|
|
136
|
+
return { success: false, error: { code: -32603, message: "Insufficient escrow amount" } };
|
|
137
|
+
}
|
|
138
|
+
const receiptAge = Date.now() - new Date(receipt.timestamp).getTime();
|
|
139
|
+
if (receiptAge > 5 * 60 * 1e3) {
|
|
140
|
+
return { success: false, error: { code: -32603, message: "Escrow receipt expired" } };
|
|
141
|
+
}
|
|
142
|
+
isRemoteEscrow = true;
|
|
143
|
+
} else {
|
|
144
|
+
try {
|
|
145
|
+
const balance = getBalance(creditDb, requester);
|
|
146
|
+
if (balance < creditsNeeded) {
|
|
147
|
+
return { success: false, error: { code: -32603, message: "Insufficient credits" } };
|
|
148
|
+
}
|
|
149
|
+
escrowId = holdEscrow(creditDb, requester, creditsNeeded, cardId);
|
|
150
|
+
} catch (err) {
|
|
151
|
+
const msg = err instanceof AgentBnBError ? err.message : "Failed to hold escrow";
|
|
152
|
+
return { success: false, error: { code: -32603, message: msg } };
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
const startMs = Date.now();
|
|
156
|
+
const receiptData = isRemoteEscrow ? { receipt_released: true } : void 0;
|
|
157
|
+
const handleFailure = (status, latencyMs, message) => {
|
|
158
|
+
if (!isRemoteEscrow && escrowId) releaseEscrow(creditDb, escrowId);
|
|
159
|
+
updateReputation(registryDb, cardId, false, latencyMs);
|
|
160
|
+
try {
|
|
161
|
+
insertRequestLog(registryDb, {
|
|
162
|
+
id: randomUUID(),
|
|
163
|
+
card_id: cardId,
|
|
164
|
+
card_name: cardName,
|
|
165
|
+
skill_id: resolvedSkillId,
|
|
166
|
+
requester,
|
|
167
|
+
status,
|
|
168
|
+
latency_ms: latencyMs,
|
|
169
|
+
credits_charged: 0,
|
|
170
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
171
|
+
});
|
|
172
|
+
} catch {
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
success: false,
|
|
176
|
+
error: { code: -32603, message, ...receiptData ? { data: receiptData } : {} }
|
|
177
|
+
};
|
|
178
|
+
};
|
|
179
|
+
const handleSuccess = (result, latencyMs) => {
|
|
180
|
+
if (isRemoteEscrow && receipt) {
|
|
181
|
+
settleProviderEarning(creditDb, card.owner, receipt);
|
|
182
|
+
} else if (escrowId) {
|
|
183
|
+
settleEscrow(creditDb, escrowId, card.owner);
|
|
184
|
+
}
|
|
185
|
+
updateReputation(registryDb, cardId, true, latencyMs);
|
|
186
|
+
try {
|
|
187
|
+
insertRequestLog(registryDb, {
|
|
188
|
+
id: randomUUID(),
|
|
189
|
+
card_id: cardId,
|
|
190
|
+
card_name: cardName,
|
|
191
|
+
skill_id: resolvedSkillId,
|
|
192
|
+
requester,
|
|
193
|
+
status: "success",
|
|
194
|
+
latency_ms: latencyMs,
|
|
195
|
+
credits_charged: creditsNeeded,
|
|
196
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
197
|
+
});
|
|
198
|
+
} catch {
|
|
199
|
+
}
|
|
200
|
+
const successResult = isRemoteEscrow ? {
|
|
201
|
+
...typeof result === "object" && result !== null ? result : { data: result },
|
|
202
|
+
receipt_settled: true,
|
|
203
|
+
receipt_nonce: receipt.nonce
|
|
204
|
+
} : result;
|
|
205
|
+
return { success: true, result: successResult };
|
|
206
|
+
};
|
|
207
|
+
if (skillExecutor) {
|
|
208
|
+
const targetSkillId = resolvedSkillId ?? skillId ?? cardId;
|
|
209
|
+
try {
|
|
210
|
+
const execResult = await skillExecutor.execute(targetSkillId, params);
|
|
211
|
+
if (!execResult.success) {
|
|
212
|
+
return handleFailure("failure", execResult.latency_ms, execResult.error ?? "Execution failed");
|
|
213
|
+
}
|
|
214
|
+
return handleSuccess(execResult.result, execResult.latency_ms);
|
|
215
|
+
} catch (err) {
|
|
216
|
+
const message = err instanceof Error ? err.message : "Execution error";
|
|
217
|
+
return handleFailure("failure", Date.now() - startMs, message);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
if (!handlerUrl) {
|
|
221
|
+
return handleFailure("failure", Date.now() - startMs, "No skill executor or handler URL configured");
|
|
222
|
+
}
|
|
223
|
+
const controller = new AbortController();
|
|
224
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
225
|
+
try {
|
|
226
|
+
const response = await fetch(handlerUrl, {
|
|
227
|
+
method: "POST",
|
|
228
|
+
headers: { "Content-Type": "application/json" },
|
|
229
|
+
body: JSON.stringify({ card_id: cardId, skill_id: resolvedSkillId, params }),
|
|
230
|
+
signal: controller.signal
|
|
231
|
+
});
|
|
232
|
+
clearTimeout(timer);
|
|
233
|
+
if (!response.ok) {
|
|
234
|
+
return handleFailure("failure", Date.now() - startMs, `Handler returned ${response.status}`);
|
|
235
|
+
}
|
|
236
|
+
const result = await response.json();
|
|
237
|
+
return handleSuccess(result, Date.now() - startMs);
|
|
238
|
+
} catch (err) {
|
|
239
|
+
clearTimeout(timer);
|
|
240
|
+
const isTimeout = err instanceof Error && err.name === "AbortError";
|
|
241
|
+
return handleFailure(
|
|
242
|
+
isTimeout ? "timeout" : "failure",
|
|
243
|
+
Date.now() - startMs,
|
|
244
|
+
isTimeout ? "Execution timeout" : "Handler error"
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export {
|
|
250
|
+
generateKeyPair,
|
|
251
|
+
saveKeyPair,
|
|
252
|
+
loadKeyPair,
|
|
253
|
+
signEscrowReceipt,
|
|
254
|
+
settleRequesterEscrow,
|
|
255
|
+
releaseRequesterEscrow,
|
|
256
|
+
executeCapabilityRequest
|
|
257
|
+
};
|
|
@@ -1,90 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
2
|
findPeer
|
|
3
3
|
} from "./chunk-BEI5MTNZ.js";
|
|
4
|
+
import {
|
|
5
|
+
getBalance,
|
|
6
|
+
holdEscrow,
|
|
7
|
+
releaseEscrow,
|
|
8
|
+
settleEscrow
|
|
9
|
+
} from "./chunk-ZJCIBK6O.js";
|
|
4
10
|
import {
|
|
5
11
|
AgentBnBError
|
|
6
12
|
} from "./chunk-TQMI73LL.js";
|
|
7
13
|
|
|
8
|
-
// src/credit/ledger.ts
|
|
9
|
-
import Database from "better-sqlite3";
|
|
10
|
-
import { randomUUID } from "crypto";
|
|
11
|
-
var CREDIT_SCHEMA = `
|
|
12
|
-
CREATE TABLE IF NOT EXISTS credit_balances (
|
|
13
|
-
owner TEXT PRIMARY KEY,
|
|
14
|
-
balance INTEGER NOT NULL DEFAULT 0,
|
|
15
|
-
updated_at TEXT NOT NULL
|
|
16
|
-
);
|
|
17
|
-
|
|
18
|
-
CREATE TABLE IF NOT EXISTS credit_transactions (
|
|
19
|
-
id TEXT PRIMARY KEY,
|
|
20
|
-
owner TEXT NOT NULL,
|
|
21
|
-
amount INTEGER NOT NULL,
|
|
22
|
-
reason TEXT NOT NULL,
|
|
23
|
-
reference_id TEXT,
|
|
24
|
-
created_at TEXT NOT NULL
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
CREATE TABLE IF NOT EXISTS credit_escrow (
|
|
28
|
-
id TEXT PRIMARY KEY,
|
|
29
|
-
owner TEXT NOT NULL,
|
|
30
|
-
amount INTEGER NOT NULL,
|
|
31
|
-
card_id TEXT NOT NULL,
|
|
32
|
-
status TEXT NOT NULL DEFAULT 'held',
|
|
33
|
-
created_at TEXT NOT NULL,
|
|
34
|
-
settled_at TEXT
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
CREATE INDEX IF NOT EXISTS idx_transactions_owner ON credit_transactions(owner, created_at);
|
|
38
|
-
CREATE INDEX IF NOT EXISTS idx_escrow_owner ON credit_escrow(owner);
|
|
39
|
-
`;
|
|
40
|
-
function openCreditDb(path = ":memory:") {
|
|
41
|
-
const db = new Database(path);
|
|
42
|
-
db.pragma("journal_mode = WAL");
|
|
43
|
-
db.pragma("foreign_keys = ON");
|
|
44
|
-
db.exec(CREDIT_SCHEMA);
|
|
45
|
-
return db;
|
|
46
|
-
}
|
|
47
|
-
function bootstrapAgent(db, owner, amount = 100) {
|
|
48
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
49
|
-
db.transaction(() => {
|
|
50
|
-
const result = db.prepare("INSERT OR IGNORE INTO credit_balances (owner, balance, updated_at) VALUES (?, ?, ?)").run(owner, amount, now);
|
|
51
|
-
if (result.changes > 0) {
|
|
52
|
-
db.prepare(
|
|
53
|
-
"INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
|
|
54
|
-
).run(randomUUID(), owner, amount, "bootstrap", null, now);
|
|
55
|
-
}
|
|
56
|
-
})();
|
|
57
|
-
}
|
|
58
|
-
function getBalance(db, owner) {
|
|
59
|
-
const row = db.prepare("SELECT balance FROM credit_balances WHERE owner = ?").get(owner);
|
|
60
|
-
return row?.balance ?? 0;
|
|
61
|
-
}
|
|
62
|
-
function getTransactions(db, owner, limit = 100) {
|
|
63
|
-
return db.prepare(
|
|
64
|
-
"SELECT id, owner, amount, reason, reference_id, created_at FROM credit_transactions WHERE owner = ? ORDER BY created_at DESC LIMIT ?"
|
|
65
|
-
).all(owner, limit);
|
|
66
|
-
}
|
|
67
|
-
function recordEarning(db, owner, amount, _cardId, receiptNonce) {
|
|
68
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
69
|
-
db.transaction(() => {
|
|
70
|
-
const existing = db.prepare(
|
|
71
|
-
"SELECT id FROM credit_transactions WHERE reference_id = ? AND reason = 'remote_earning'"
|
|
72
|
-
).get(receiptNonce);
|
|
73
|
-
if (existing) return;
|
|
74
|
-
db.prepare(
|
|
75
|
-
"INSERT OR IGNORE INTO credit_balances (owner, balance, updated_at) VALUES (?, 0, ?)"
|
|
76
|
-
).run(owner, now);
|
|
77
|
-
db.prepare(
|
|
78
|
-
"UPDATE credit_balances SET balance = balance + ?, updated_at = ? WHERE owner = ?"
|
|
79
|
-
).run(amount, now, owner);
|
|
80
|
-
db.prepare(
|
|
81
|
-
"INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
|
|
82
|
-
).run(randomUUID(), owner, amount, "remote_earning", receiptNonce, now);
|
|
83
|
-
})();
|
|
84
|
-
}
|
|
85
|
-
|
|
86
14
|
// src/autonomy/tiers.ts
|
|
87
|
-
import { randomUUID
|
|
15
|
+
import { randomUUID } from "crypto";
|
|
88
16
|
var DEFAULT_AUTONOMY_CONFIG = {
|
|
89
17
|
tier1_max_credits: 0,
|
|
90
18
|
tier2_max_credits: 0
|
|
@@ -105,7 +33,7 @@ function insertAuditEvent(db, event) {
|
|
|
105
33
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
106
34
|
`);
|
|
107
35
|
stmt.run(
|
|
108
|
-
|
|
36
|
+
randomUUID(),
|
|
109
37
|
cardId,
|
|
110
38
|
"autonomy-audit",
|
|
111
39
|
"self",
|
|
@@ -220,10 +148,10 @@ function filterCards(db, filters) {
|
|
|
220
148
|
}
|
|
221
149
|
|
|
222
150
|
// src/gateway/client.ts
|
|
223
|
-
import { randomUUID as
|
|
151
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
224
152
|
async function requestCapability(opts) {
|
|
225
153
|
const { gatewayUrl, token, cardId, params = {}, timeoutMs = 3e4, escrowReceipt } = opts;
|
|
226
|
-
const id =
|
|
154
|
+
const id = randomUUID2();
|
|
227
155
|
const payload = {
|
|
228
156
|
jsonrpc: "2.0",
|
|
229
157
|
id,
|
|
@@ -264,109 +192,10 @@ async function requestCapability(opts) {
|
|
|
264
192
|
return body.result;
|
|
265
193
|
}
|
|
266
194
|
|
|
267
|
-
// src/credit/escrow.ts
|
|
268
|
-
import { randomUUID as randomUUID4 } from "crypto";
|
|
269
|
-
function holdEscrow(db, owner, amount, cardId) {
|
|
270
|
-
const escrowId = randomUUID4();
|
|
271
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
272
|
-
const hold = db.transaction(() => {
|
|
273
|
-
const row = db.prepare("SELECT balance FROM credit_balances WHERE owner = ?").get(owner);
|
|
274
|
-
if (!row || row.balance < amount) {
|
|
275
|
-
throw new AgentBnBError("Insufficient credits", "INSUFFICIENT_CREDITS");
|
|
276
|
-
}
|
|
277
|
-
db.prepare(
|
|
278
|
-
"UPDATE credit_balances SET balance = balance - ?, updated_at = ? WHERE owner = ? AND balance >= ?"
|
|
279
|
-
).run(amount, now, owner, amount);
|
|
280
|
-
db.prepare(
|
|
281
|
-
"INSERT INTO credit_escrow (id, owner, amount, card_id, status, created_at) VALUES (?, ?, ?, ?, ?, ?)"
|
|
282
|
-
).run(escrowId, owner, amount, cardId, "held", now);
|
|
283
|
-
db.prepare(
|
|
284
|
-
"INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
|
|
285
|
-
).run(randomUUID4(), owner, -amount, "escrow_hold", escrowId, now);
|
|
286
|
-
});
|
|
287
|
-
hold();
|
|
288
|
-
return escrowId;
|
|
289
|
-
}
|
|
290
|
-
function settleEscrow(db, escrowId, recipientOwner) {
|
|
291
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
292
|
-
const settle = db.transaction(() => {
|
|
293
|
-
const escrow = db.prepare("SELECT id, owner, amount, status FROM credit_escrow WHERE id = ?").get(escrowId);
|
|
294
|
-
if (!escrow) {
|
|
295
|
-
throw new AgentBnBError(`Escrow not found: ${escrowId}`, "ESCROW_NOT_FOUND");
|
|
296
|
-
}
|
|
297
|
-
if (escrow.status !== "held") {
|
|
298
|
-
throw new AgentBnBError(
|
|
299
|
-
`Escrow ${escrowId} is already ${escrow.status}`,
|
|
300
|
-
"ESCROW_ALREADY_SETTLED"
|
|
301
|
-
);
|
|
302
|
-
}
|
|
303
|
-
db.prepare(
|
|
304
|
-
"INSERT OR IGNORE INTO credit_balances (owner, balance, updated_at) VALUES (?, 0, ?)"
|
|
305
|
-
).run(recipientOwner, now);
|
|
306
|
-
db.prepare(
|
|
307
|
-
"UPDATE credit_balances SET balance = balance + ?, updated_at = ? WHERE owner = ?"
|
|
308
|
-
).run(escrow.amount, now, recipientOwner);
|
|
309
|
-
db.prepare(
|
|
310
|
-
"UPDATE credit_escrow SET status = ?, settled_at = ? WHERE id = ?"
|
|
311
|
-
).run("settled", now, escrowId);
|
|
312
|
-
db.prepare(
|
|
313
|
-
"INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
|
|
314
|
-
).run(randomUUID4(), recipientOwner, escrow.amount, "settlement", escrowId, now);
|
|
315
|
-
});
|
|
316
|
-
settle();
|
|
317
|
-
}
|
|
318
|
-
function releaseEscrow(db, escrowId) {
|
|
319
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
320
|
-
const release = db.transaction(() => {
|
|
321
|
-
const escrow = db.prepare("SELECT id, owner, amount, status FROM credit_escrow WHERE id = ?").get(escrowId);
|
|
322
|
-
if (!escrow) {
|
|
323
|
-
throw new AgentBnBError(`Escrow not found: ${escrowId}`, "ESCROW_NOT_FOUND");
|
|
324
|
-
}
|
|
325
|
-
if (escrow.status !== "held") {
|
|
326
|
-
throw new AgentBnBError(
|
|
327
|
-
`Escrow ${escrowId} is already ${escrow.status}`,
|
|
328
|
-
"ESCROW_ALREADY_SETTLED"
|
|
329
|
-
);
|
|
330
|
-
}
|
|
331
|
-
db.prepare(
|
|
332
|
-
"UPDATE credit_balances SET balance = balance + ?, updated_at = ? WHERE owner = ?"
|
|
333
|
-
).run(escrow.amount, now, escrow.owner);
|
|
334
|
-
db.prepare(
|
|
335
|
-
"UPDATE credit_escrow SET status = ?, settled_at = ? WHERE id = ?"
|
|
336
|
-
).run("released", now, escrowId);
|
|
337
|
-
db.prepare(
|
|
338
|
-
"INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
|
|
339
|
-
).run(randomUUID4(), escrow.owner, escrow.amount, "refund", escrowId, now);
|
|
340
|
-
});
|
|
341
|
-
release();
|
|
342
|
-
}
|
|
343
|
-
function confirmEscrowDebit(db, escrowId) {
|
|
344
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
345
|
-
const confirm = db.transaction(() => {
|
|
346
|
-
const escrow = db.prepare("SELECT id, owner, amount, status FROM credit_escrow WHERE id = ?").get(escrowId);
|
|
347
|
-
if (!escrow) {
|
|
348
|
-
throw new AgentBnBError(`Escrow not found: ${escrowId}`, "ESCROW_NOT_FOUND");
|
|
349
|
-
}
|
|
350
|
-
if (escrow.status !== "held") {
|
|
351
|
-
throw new AgentBnBError(
|
|
352
|
-
`Escrow ${escrowId} is already ${escrow.status}`,
|
|
353
|
-
"ESCROW_ALREADY_SETTLED"
|
|
354
|
-
);
|
|
355
|
-
}
|
|
356
|
-
db.prepare(
|
|
357
|
-
"UPDATE credit_escrow SET status = ?, settled_at = ? WHERE id = ?"
|
|
358
|
-
).run("settled", now, escrowId);
|
|
359
|
-
db.prepare(
|
|
360
|
-
"INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
|
|
361
|
-
).run(randomUUID4(), escrow.owner, 0, "remote_settlement_confirmed", escrowId, now);
|
|
362
|
-
});
|
|
363
|
-
confirm();
|
|
364
|
-
}
|
|
365
|
-
|
|
366
195
|
// src/autonomy/pending-requests.ts
|
|
367
|
-
import { randomUUID as
|
|
196
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
368
197
|
function createPendingRequest(db, opts) {
|
|
369
|
-
const id =
|
|
198
|
+
const id = randomUUID3();
|
|
370
199
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
371
200
|
const paramsJson = opts.params !== void 0 ? JSON.stringify(opts.params) : null;
|
|
372
201
|
db.prepare(`
|
|
@@ -641,15 +470,6 @@ function interpolateValue(value, context) {
|
|
|
641
470
|
}
|
|
642
471
|
|
|
643
472
|
export {
|
|
644
|
-
holdEscrow,
|
|
645
|
-
settleEscrow,
|
|
646
|
-
releaseEscrow,
|
|
647
|
-
confirmEscrowDebit,
|
|
648
|
-
openCreditDb,
|
|
649
|
-
bootstrapAgent,
|
|
650
|
-
getBalance,
|
|
651
|
-
getTransactions,
|
|
652
|
-
recordEarning,
|
|
653
473
|
DEFAULT_AUTONOMY_CONFIG,
|
|
654
474
|
getAutonomyTier,
|
|
655
475
|
insertAuditEvent,
|