agentbnb 4.0.4 → 5.1.1
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-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-JXEOE7HX.js → chunk-CRFCWD6V.js} +163 -92
- 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-EVBX22YU.js → chunk-HLUEOLSZ.js} +11 -17
- 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-5QGXARLJ.js → chunk-W5BZMKMF.js} +159 -27
- package/dist/{chunk-FF226TIV.js → chunk-ZX5623ER.js} +0 -57
- package/dist/cli/index.js +362 -4633
- 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-ESGFZ6T5.js → conductor-mode-VRO7TYW2.js} +20 -167
- package/dist/execute-CPFSOOO3.js +13 -0
- package/dist/execute-IP2QHALV.js +10 -0
- package/dist/index.d.ts +14 -8
- package/dist/index.js +190 -36
- package/dist/{peers-E4MKNNDN.js → peers-CJ7T4RJO.js} +2 -1
- 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-Q6NHX2RA.js → serve-skill-JHFNR7BW.js} +8 -7
- package/dist/{server-B5E566CI.js → server-HKJJWFRG.js} +10 -8
- package/dist/service-coordinator-UTKI4FRI.js +4922 -0
- package/dist/skills/agentbnb/bootstrap.js +5034 -849
- package/dist/websocket-client-WRN3HO73.js +6 -0
- package/package.json +4 -1
- 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/skills/deep-stock-analyst/package.json +24 -0
- package/skills/deep-stock-analyst/src/analysis/financial-health.ts +167 -0
- package/skills/deep-stock-analyst/src/analysis/sentiment.ts +68 -0
- package/skills/deep-stock-analyst/src/analysis/signal.ts +188 -0
- package/skills/deep-stock-analyst/src/analysis/technicals.ts +318 -0
- package/skills/deep-stock-analyst/src/analysis/utils.ts +137 -0
- package/skills/deep-stock-analyst/src/analysis/valuation.ts +95 -0
- package/skills/deep-stock-analyst/src/api/alpha-vantage.ts +133 -0
- package/skills/deep-stock-analyst/src/api/types.ts +238 -0
- package/skills/deep-stock-analyst/src/index.ts +84 -0
- package/skills/deep-stock-analyst/src/llm/thesis.ts +101 -0
- package/skills/deep-stock-analyst/src/orchestrator.ts +228 -0
- package/skills/deep-stock-analyst/tsconfig.json +21 -0
- package/dist/card-RNEWSAQ6.js +0 -88
- package/dist/chunk-UB2NPFC7.js +0 -165
- package/dist/execute-QH6F54D7.js +0 -10
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
// src/relay/websocket-client.ts
|
|
2
|
+
import WebSocket from "ws";
|
|
3
|
+
import { randomUUID } from "crypto";
|
|
4
|
+
|
|
5
|
+
// src/relay/types.ts
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
var RegisterMessageSchema = z.object({
|
|
8
|
+
type: z.literal("register"),
|
|
9
|
+
owner: z.string().min(1),
|
|
10
|
+
token: z.string().min(1),
|
|
11
|
+
card: z.record(z.unknown()),
|
|
12
|
+
// CapabilityCard (validated separately)
|
|
13
|
+
cards: z.array(z.record(z.unknown())).optional()
|
|
14
|
+
// Additional cards (e.g., conductor card)
|
|
15
|
+
});
|
|
16
|
+
var RegisteredMessageSchema = z.object({
|
|
17
|
+
type: z.literal("registered"),
|
|
18
|
+
agent_id: z.string()
|
|
19
|
+
});
|
|
20
|
+
var RelayRequestMessageSchema = z.object({
|
|
21
|
+
type: z.literal("relay_request"),
|
|
22
|
+
id: z.string().uuid(),
|
|
23
|
+
target_owner: z.string().min(1),
|
|
24
|
+
card_id: z.string(),
|
|
25
|
+
skill_id: z.string().optional(),
|
|
26
|
+
params: z.record(z.unknown()).default({}),
|
|
27
|
+
requester: z.string().optional(),
|
|
28
|
+
escrow_receipt: z.record(z.unknown()).optional()
|
|
29
|
+
});
|
|
30
|
+
var IncomingRequestMessageSchema = z.object({
|
|
31
|
+
type: z.literal("incoming_request"),
|
|
32
|
+
id: z.string().uuid(),
|
|
33
|
+
from_owner: z.string().min(1),
|
|
34
|
+
card_id: z.string(),
|
|
35
|
+
skill_id: z.string().optional(),
|
|
36
|
+
params: z.record(z.unknown()).default({}),
|
|
37
|
+
requester: z.string().optional(),
|
|
38
|
+
escrow_receipt: z.record(z.unknown()).optional()
|
|
39
|
+
});
|
|
40
|
+
var RelayResponseMessageSchema = z.object({
|
|
41
|
+
type: z.literal("relay_response"),
|
|
42
|
+
id: z.string().uuid(),
|
|
43
|
+
result: z.unknown().optional(),
|
|
44
|
+
error: z.object({
|
|
45
|
+
code: z.number(),
|
|
46
|
+
message: z.string()
|
|
47
|
+
}).optional()
|
|
48
|
+
});
|
|
49
|
+
var ResponseMessageSchema = z.object({
|
|
50
|
+
type: z.literal("response"),
|
|
51
|
+
id: z.string().uuid(),
|
|
52
|
+
result: z.unknown().optional(),
|
|
53
|
+
error: z.object({
|
|
54
|
+
code: z.number(),
|
|
55
|
+
message: z.string()
|
|
56
|
+
}).optional()
|
|
57
|
+
});
|
|
58
|
+
var ErrorMessageSchema = z.object({
|
|
59
|
+
type: z.literal("error"),
|
|
60
|
+
code: z.string(),
|
|
61
|
+
message: z.string(),
|
|
62
|
+
request_id: z.string().optional()
|
|
63
|
+
});
|
|
64
|
+
var RelayProgressMessageSchema = z.object({
|
|
65
|
+
type: z.literal("relay_progress"),
|
|
66
|
+
id: z.string().uuid(),
|
|
67
|
+
// request ID this progress relates to
|
|
68
|
+
progress: z.number().min(0).max(100).optional(),
|
|
69
|
+
// optional percentage
|
|
70
|
+
message: z.string().optional()
|
|
71
|
+
// optional status message
|
|
72
|
+
});
|
|
73
|
+
var RelayMessageSchema = z.discriminatedUnion("type", [
|
|
74
|
+
RegisterMessageSchema,
|
|
75
|
+
RegisteredMessageSchema,
|
|
76
|
+
RelayRequestMessageSchema,
|
|
77
|
+
IncomingRequestMessageSchema,
|
|
78
|
+
RelayResponseMessageSchema,
|
|
79
|
+
ResponseMessageSchema,
|
|
80
|
+
ErrorMessageSchema,
|
|
81
|
+
RelayProgressMessageSchema
|
|
82
|
+
]);
|
|
83
|
+
|
|
84
|
+
// src/relay/websocket-client.ts
|
|
85
|
+
var RelayClient = class {
|
|
86
|
+
ws = null;
|
|
87
|
+
opts;
|
|
88
|
+
pendingRequests = /* @__PURE__ */ new Map();
|
|
89
|
+
reconnectAttempts = 0;
|
|
90
|
+
reconnectTimer = null;
|
|
91
|
+
intentionalClose = false;
|
|
92
|
+
registered = false;
|
|
93
|
+
pongTimeout = null;
|
|
94
|
+
pingInterval = null;
|
|
95
|
+
constructor(opts) {
|
|
96
|
+
this.opts = opts;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Connect to the registry relay and register.
|
|
100
|
+
* Resolves when registration is acknowledged.
|
|
101
|
+
*/
|
|
102
|
+
async connect() {
|
|
103
|
+
return new Promise((resolve, reject) => {
|
|
104
|
+
this.intentionalClose = false;
|
|
105
|
+
this.registered = false;
|
|
106
|
+
const wsUrl = this.buildWsUrl();
|
|
107
|
+
this.ws = new WebSocket(wsUrl);
|
|
108
|
+
let resolved = false;
|
|
109
|
+
this.ws.on("open", () => {
|
|
110
|
+
this.reconnectAttempts = 0;
|
|
111
|
+
this.startPingInterval();
|
|
112
|
+
this.send({
|
|
113
|
+
type: "register",
|
|
114
|
+
owner: this.opts.owner,
|
|
115
|
+
token: this.opts.token,
|
|
116
|
+
card: this.opts.card,
|
|
117
|
+
...this.opts.cards && this.opts.cards.length > 0 ? { cards: this.opts.cards } : {}
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
this.ws.on("message", (raw) => {
|
|
121
|
+
this.handleMessage(raw, (err) => {
|
|
122
|
+
if (!resolved) {
|
|
123
|
+
resolved = true;
|
|
124
|
+
if (err) reject(err);
|
|
125
|
+
else resolve();
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
this.ws.on("close", () => {
|
|
130
|
+
this.cleanup();
|
|
131
|
+
if (!this.intentionalClose) {
|
|
132
|
+
if (!resolved) {
|
|
133
|
+
resolved = true;
|
|
134
|
+
reject(new Error("WebSocket closed before registration"));
|
|
135
|
+
}
|
|
136
|
+
this.scheduleReconnect();
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
this.ws.on("error", (err) => {
|
|
140
|
+
if (!resolved) {
|
|
141
|
+
resolved = true;
|
|
142
|
+
reject(err);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
setTimeout(() => {
|
|
146
|
+
if (!resolved) {
|
|
147
|
+
resolved = true;
|
|
148
|
+
reject(new Error("Connection timeout"));
|
|
149
|
+
this.ws?.close();
|
|
150
|
+
}
|
|
151
|
+
}, 1e4);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Disconnect from the registry relay.
|
|
156
|
+
*/
|
|
157
|
+
disconnect() {
|
|
158
|
+
this.intentionalClose = true;
|
|
159
|
+
this.cleanup();
|
|
160
|
+
if (this.ws) {
|
|
161
|
+
try {
|
|
162
|
+
this.ws.close(1e3, "Client disconnect");
|
|
163
|
+
} catch {
|
|
164
|
+
}
|
|
165
|
+
this.ws = null;
|
|
166
|
+
}
|
|
167
|
+
for (const [id, pending] of this.pendingRequests) {
|
|
168
|
+
clearTimeout(pending.timeout);
|
|
169
|
+
pending.reject(new Error("Client disconnected"));
|
|
170
|
+
this.pendingRequests.delete(id);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Send a relay request to another agent via the registry.
|
|
175
|
+
* @returns The result from the target agent.
|
|
176
|
+
*/
|
|
177
|
+
async request(opts) {
|
|
178
|
+
if (!this.ws || this.ws.readyState !== WebSocket.OPEN || !this.registered) {
|
|
179
|
+
throw new Error("Not connected to registry relay");
|
|
180
|
+
}
|
|
181
|
+
const id = randomUUID();
|
|
182
|
+
const timeoutMs = opts.timeoutMs ?? 3e5;
|
|
183
|
+
return new Promise((resolve, reject) => {
|
|
184
|
+
const timeout = setTimeout(() => {
|
|
185
|
+
this.pendingRequests.delete(id);
|
|
186
|
+
reject(new Error("Relay request timeout"));
|
|
187
|
+
}, timeoutMs);
|
|
188
|
+
this.pendingRequests.set(id, { resolve, reject, timeout, timeoutMs, onProgress: opts.onProgress });
|
|
189
|
+
this.send({
|
|
190
|
+
type: "relay_request",
|
|
191
|
+
id,
|
|
192
|
+
target_owner: opts.targetOwner,
|
|
193
|
+
card_id: opts.cardId,
|
|
194
|
+
skill_id: opts.skillId,
|
|
195
|
+
params: opts.params,
|
|
196
|
+
requester: opts.requester ?? this.opts.owner,
|
|
197
|
+
escrow_receipt: opts.escrowReceipt
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Send a relay_progress message to the relay server for a given request.
|
|
203
|
+
* Used by the onRequest handler to forward SkillExecutor progress updates
|
|
204
|
+
* to the requesting agent so it can reset its timeout window.
|
|
205
|
+
*
|
|
206
|
+
* @param requestId - The relay request ID to associate progress with.
|
|
207
|
+
* @param info - Progress details (step, total, message).
|
|
208
|
+
*/
|
|
209
|
+
sendProgress(requestId, info) {
|
|
210
|
+
this.send({
|
|
211
|
+
type: "relay_progress",
|
|
212
|
+
id: requestId,
|
|
213
|
+
progress: Math.round(info.step / info.total * 100),
|
|
214
|
+
message: info.message
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
/** Whether the client is connected and registered */
|
|
218
|
+
get isConnected() {
|
|
219
|
+
return this.ws !== null && this.ws.readyState === WebSocket.OPEN && this.registered;
|
|
220
|
+
}
|
|
221
|
+
// ── Private methods ─────────────────────────────────────────────────────────
|
|
222
|
+
buildWsUrl() {
|
|
223
|
+
let url = this.opts.registryUrl;
|
|
224
|
+
if (url.startsWith("http://")) {
|
|
225
|
+
url = "ws://" + url.slice(7);
|
|
226
|
+
} else if (url.startsWith("https://")) {
|
|
227
|
+
url = "wss://" + url.slice(8);
|
|
228
|
+
} else if (!url.startsWith("ws://") && !url.startsWith("wss://")) {
|
|
229
|
+
url = "wss://" + url;
|
|
230
|
+
}
|
|
231
|
+
if (!url.endsWith("/ws")) {
|
|
232
|
+
url = url.replace(/\/$/, "") + "/ws";
|
|
233
|
+
}
|
|
234
|
+
return url;
|
|
235
|
+
}
|
|
236
|
+
handleMessage(raw, onRegistered) {
|
|
237
|
+
let data;
|
|
238
|
+
try {
|
|
239
|
+
data = JSON.parse(typeof raw === "string" ? raw : raw.toString("utf-8"));
|
|
240
|
+
} catch {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
const parsed = RelayMessageSchema.safeParse(data);
|
|
244
|
+
if (!parsed.success) return;
|
|
245
|
+
const msg = parsed.data;
|
|
246
|
+
switch (msg.type) {
|
|
247
|
+
case "registered":
|
|
248
|
+
this.registered = true;
|
|
249
|
+
if (!this.opts.silent) {
|
|
250
|
+
console.log(` \u2713 Registered with registry (agent_id: ${msg.agent_id})`);
|
|
251
|
+
}
|
|
252
|
+
onRegistered?.();
|
|
253
|
+
break;
|
|
254
|
+
case "incoming_request":
|
|
255
|
+
this.handleIncomingRequest(msg);
|
|
256
|
+
break;
|
|
257
|
+
case "response":
|
|
258
|
+
this.handleResponse(msg);
|
|
259
|
+
break;
|
|
260
|
+
case "error":
|
|
261
|
+
this.handleError(msg);
|
|
262
|
+
break;
|
|
263
|
+
case "relay_progress":
|
|
264
|
+
this.handleProgress(msg);
|
|
265
|
+
break;
|
|
266
|
+
default:
|
|
267
|
+
break;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
async handleIncomingRequest(msg) {
|
|
271
|
+
try {
|
|
272
|
+
const result = await this.opts.onRequest(msg);
|
|
273
|
+
this.send({
|
|
274
|
+
type: "relay_response",
|
|
275
|
+
id: msg.id,
|
|
276
|
+
result: result.result,
|
|
277
|
+
error: result.error
|
|
278
|
+
});
|
|
279
|
+
} catch (err) {
|
|
280
|
+
this.send({
|
|
281
|
+
type: "relay_response",
|
|
282
|
+
id: msg.id,
|
|
283
|
+
error: {
|
|
284
|
+
code: -32603,
|
|
285
|
+
message: err instanceof Error ? err.message : "Internal error"
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
handleResponse(msg) {
|
|
291
|
+
const pending = this.pendingRequests.get(msg.id);
|
|
292
|
+
if (!pending) return;
|
|
293
|
+
clearTimeout(pending.timeout);
|
|
294
|
+
this.pendingRequests.delete(msg.id);
|
|
295
|
+
if (msg.error) {
|
|
296
|
+
pending.reject(new Error(msg.error.message));
|
|
297
|
+
} else {
|
|
298
|
+
pending.resolve(msg.result);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
handleError(msg) {
|
|
302
|
+
if (msg.request_id) {
|
|
303
|
+
const pending = this.pendingRequests.get(msg.request_id);
|
|
304
|
+
if (pending) {
|
|
305
|
+
clearTimeout(pending.timeout);
|
|
306
|
+
this.pendingRequests.delete(msg.request_id);
|
|
307
|
+
pending.reject(new Error(`${msg.code}: ${msg.message}`));
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
handleProgress(msg) {
|
|
312
|
+
const pending = this.pendingRequests.get(msg.id);
|
|
313
|
+
if (!pending) return;
|
|
314
|
+
clearTimeout(pending.timeout);
|
|
315
|
+
const newTimeout = setTimeout(() => {
|
|
316
|
+
this.pendingRequests.delete(msg.id);
|
|
317
|
+
pending.reject(new Error("Relay request timeout"));
|
|
318
|
+
}, pending.timeoutMs);
|
|
319
|
+
pending.timeout = newTimeout;
|
|
320
|
+
if (pending.onProgress) {
|
|
321
|
+
pending.onProgress({ id: msg.id, progress: msg.progress, message: msg.message });
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
send(msg) {
|
|
325
|
+
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
326
|
+
this.ws.send(JSON.stringify(msg));
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
startPingInterval() {
|
|
330
|
+
this.stopPingInterval();
|
|
331
|
+
this.pingInterval = setInterval(() => {
|
|
332
|
+
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
333
|
+
this.ws.ping();
|
|
334
|
+
this.pongTimeout = setTimeout(() => {
|
|
335
|
+
if (!this.opts.silent) {
|
|
336
|
+
console.log(" \u26A0 Registry pong timeout, reconnecting...");
|
|
337
|
+
}
|
|
338
|
+
this.ws?.terminate();
|
|
339
|
+
}, 15e3);
|
|
340
|
+
}
|
|
341
|
+
}, 3e4);
|
|
342
|
+
this.ws?.on("pong", () => {
|
|
343
|
+
if (this.pongTimeout) {
|
|
344
|
+
clearTimeout(this.pongTimeout);
|
|
345
|
+
this.pongTimeout = null;
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
stopPingInterval() {
|
|
350
|
+
if (this.pingInterval) {
|
|
351
|
+
clearInterval(this.pingInterval);
|
|
352
|
+
this.pingInterval = null;
|
|
353
|
+
}
|
|
354
|
+
if (this.pongTimeout) {
|
|
355
|
+
clearTimeout(this.pongTimeout);
|
|
356
|
+
this.pongTimeout = null;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
cleanup() {
|
|
360
|
+
this.stopPingInterval();
|
|
361
|
+
this.registered = false;
|
|
362
|
+
}
|
|
363
|
+
scheduleReconnect() {
|
|
364
|
+
if (this.intentionalClose) return;
|
|
365
|
+
if (this.reconnectTimer) return;
|
|
366
|
+
const delay = Math.min(1e3 * Math.pow(2, this.reconnectAttempts), 3e4);
|
|
367
|
+
this.reconnectAttempts++;
|
|
368
|
+
if (!this.opts.silent) {
|
|
369
|
+
console.log(` \u21BB Reconnecting to registry in ${delay / 1e3}s...`);
|
|
370
|
+
}
|
|
371
|
+
this.reconnectTimer = setTimeout(async () => {
|
|
372
|
+
this.reconnectTimer = null;
|
|
373
|
+
try {
|
|
374
|
+
await this.connect();
|
|
375
|
+
if (!this.opts.silent) {
|
|
376
|
+
console.log(" \u2713 Reconnected to registry");
|
|
377
|
+
}
|
|
378
|
+
} catch {
|
|
379
|
+
}
|
|
380
|
+
}, delay);
|
|
381
|
+
}
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
export {
|
|
385
|
+
RelayMessageSchema,
|
|
386
|
+
RelayClient
|
|
387
|
+
};
|
|
@@ -1,46 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AgentBnBError
|
|
3
|
-
} from "./chunk-
|
|
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
|
-
}
|
|
3
|
+
} from "./chunk-WGZ5AGOX.js";
|
|
40
4
|
|
|
41
5
|
// src/credit/ledger.ts
|
|
42
6
|
import Database from "better-sqlite3";
|
|
43
|
-
import { randomUUID
|
|
7
|
+
import { randomUUID } from "crypto";
|
|
44
8
|
var CREDIT_SCHEMA = `
|
|
45
9
|
CREATE TABLE IF NOT EXISTS credit_balances (
|
|
46
10
|
owner TEXT PRIMARY KEY,
|
|
@@ -77,10 +41,26 @@ function openCreditDb(path = ":memory:") {
|
|
|
77
41
|
db.exec(CREDIT_SCHEMA);
|
|
78
42
|
return db;
|
|
79
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
|
+
}
|
|
80
55
|
function getBalance(db, owner) {
|
|
81
56
|
const row = db.prepare("SELECT balance FROM credit_balances WHERE owner = ?").get(owner);
|
|
82
57
|
return row?.balance ?? 0;
|
|
83
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
|
+
}
|
|
84
64
|
function recordEarning(db, owner, amount, _cardId, receiptNonce) {
|
|
85
65
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
86
66
|
db.transaction(() => {
|
|
@@ -96,14 +76,33 @@ function recordEarning(db, owner, amount, _cardId, receiptNonce) {
|
|
|
96
76
|
).run(amount, now, owner);
|
|
97
77
|
db.prepare(
|
|
98
78
|
"INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
|
|
99
|
-
).run(
|
|
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);
|
|
100
99
|
})();
|
|
101
100
|
}
|
|
102
101
|
|
|
103
102
|
// src/credit/escrow.ts
|
|
104
|
-
import { randomUUID as
|
|
103
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
105
104
|
function holdEscrow(db, owner, amount, cardId) {
|
|
106
|
-
const escrowId =
|
|
105
|
+
const escrowId = randomUUID2();
|
|
107
106
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
108
107
|
const hold = db.transaction(() => {
|
|
109
108
|
const row = db.prepare("SELECT balance FROM credit_balances WHERE owner = ?").get(owner);
|
|
@@ -118,7 +117,7 @@ function holdEscrow(db, owner, amount, cardId) {
|
|
|
118
117
|
).run(escrowId, owner, amount, cardId, "held", now);
|
|
119
118
|
db.prepare(
|
|
120
119
|
"INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
|
|
121
|
-
).run(
|
|
120
|
+
).run(randomUUID2(), owner, -amount, "escrow_hold", escrowId, now);
|
|
122
121
|
});
|
|
123
122
|
hold();
|
|
124
123
|
return escrowId;
|
|
@@ -147,7 +146,7 @@ function settleEscrow(db, escrowId, recipientOwner) {
|
|
|
147
146
|
).run("settled", now, escrowId);
|
|
148
147
|
db.prepare(
|
|
149
148
|
"INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
|
|
150
|
-
).run(
|
|
149
|
+
).run(randomUUID2(), recipientOwner, escrow.amount, "settlement", escrowId, now);
|
|
151
150
|
});
|
|
152
151
|
settle();
|
|
153
152
|
}
|
|
@@ -172,56 +171,31 @@ function releaseEscrow(db, escrowId) {
|
|
|
172
171
|
).run("released", now, escrowId);
|
|
173
172
|
db.prepare(
|
|
174
173
|
"INSERT INTO credit_transactions (id, owner, amount, reason, reference_id, created_at) VALUES (?, ?, ?, ?, ?, ?)"
|
|
175
|
-
).run(
|
|
174
|
+
).run(randomUUID2(), escrow.owner, escrow.amount, "refund", escrowId, now);
|
|
176
175
|
});
|
|
177
176
|
release();
|
|
178
177
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
if (current === null || current === void 0) {
|
|
186
|
-
return void 0;
|
|
187
|
-
}
|
|
188
|
-
if (typeof current !== "object") {
|
|
189
|
-
return void 0;
|
|
190
|
-
}
|
|
191
|
-
current = current[segment];
|
|
192
|
-
}
|
|
193
|
-
return current;
|
|
194
|
-
}
|
|
195
|
-
function interpolate(template, context) {
|
|
196
|
-
return template.replace(/\$\{([^}]+)\}/g, (_match, expression) => {
|
|
197
|
-
const resolved = resolvePath(context, expression.trim());
|
|
198
|
-
if (resolved === void 0 || resolved === null) {
|
|
199
|
-
return "";
|
|
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");
|
|
200
184
|
}
|
|
201
|
-
if (
|
|
202
|
-
|
|
185
|
+
if (escrow.status !== "held") {
|
|
186
|
+
throw new AgentBnBError(
|
|
187
|
+
`Escrow ${escrowId} is already ${escrow.status}`,
|
|
188
|
+
"ESCROW_ALREADY_SETTLED"
|
|
189
|
+
);
|
|
203
190
|
}
|
|
204
|
-
|
|
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);
|
|
205
197
|
});
|
|
206
|
-
|
|
207
|
-
function interpolateObject(obj, context) {
|
|
208
|
-
const result = {};
|
|
209
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
210
|
-
result[key] = interpolateValue(value, context);
|
|
211
|
-
}
|
|
212
|
-
return result;
|
|
213
|
-
}
|
|
214
|
-
function interpolateValue(value, context) {
|
|
215
|
-
if (typeof value === "string") {
|
|
216
|
-
return interpolate(value, context);
|
|
217
|
-
}
|
|
218
|
-
if (Array.isArray(value)) {
|
|
219
|
-
return value.map((item) => interpolateValue(item, context));
|
|
220
|
-
}
|
|
221
|
-
if (value !== null && typeof value === "object") {
|
|
222
|
-
return interpolateObject(value, context);
|
|
223
|
-
}
|
|
224
|
-
return value;
|
|
198
|
+
confirm();
|
|
225
199
|
}
|
|
226
200
|
|
|
227
201
|
// src/credit/signing.ts
|
|
@@ -276,20 +250,117 @@ function verifyEscrowReceipt(data, signature, publicKey) {
|
|
|
276
250
|
}
|
|
277
251
|
}
|
|
278
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
|
+
|
|
279
346
|
export {
|
|
347
|
+
initFeedbackTable,
|
|
348
|
+
insertFeedback,
|
|
349
|
+
getFeedbackForSkill,
|
|
350
|
+
getFeedbackForProvider,
|
|
280
351
|
openCreditDb,
|
|
352
|
+
bootstrapAgent,
|
|
281
353
|
getBalance,
|
|
354
|
+
getTransactions,
|
|
282
355
|
recordEarning,
|
|
356
|
+
migrateOwner,
|
|
283
357
|
holdEscrow,
|
|
284
358
|
settleEscrow,
|
|
285
359
|
releaseEscrow,
|
|
286
|
-
|
|
360
|
+
confirmEscrowDebit,
|
|
287
361
|
generateKeyPair,
|
|
288
362
|
saveKeyPair,
|
|
289
363
|
loadKeyPair,
|
|
290
364
|
signEscrowReceipt,
|
|
291
|
-
verifyEscrowReceipt
|
|
292
|
-
DEFAULT_AUTONOMY_CONFIG,
|
|
293
|
-
getAutonomyTier,
|
|
294
|
-
insertAuditEvent
|
|
365
|
+
verifyEscrowReceipt
|
|
295
366
|
};
|