agentbnb 4.0.4 → 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.
Files changed (45) hide show
  1. package/dist/chunk-AUBHR7HH.js +25 -0
  2. package/dist/chunk-B5FTAGFN.js +393 -0
  3. package/dist/{chunk-GGYC5U2Z.js → chunk-BTTL24TZ.js} +29 -91
  4. package/dist/chunk-C6KPAFCC.js +387 -0
  5. package/dist/{chunk-JXEOE7HX.js → chunk-CRFCWD6V.js} +163 -92
  6. package/dist/chunk-CSATDXZC.js +89 -0
  7. package/dist/{chunk-T7NS2J2B.js → chunk-DFBX3BBD.js} +84 -1
  8. package/dist/{chunk-DNWT5FZQ.js → chunk-EANI2N2V.js} +98 -1
  9. package/dist/{chunk-HH24WMFN.js → chunk-FLY3WIQR.js} +1 -1
  10. package/dist/{chunk-EVBX22YU.js → chunk-HLUEOLSZ.js} +11 -17
  11. package/dist/chunk-IVOYM3WG.js +25 -0
  12. package/dist/chunk-LCAIAAG2.js +916 -0
  13. package/dist/chunk-MLS6IGGG.js +294 -0
  14. package/dist/{chunk-4P3EMGL4.js → chunk-MNO4COST.js} +5 -3
  15. package/dist/chunk-NH2FIERR.js +138 -0
  16. package/dist/chunk-UKT6H7YT.js +29 -0
  17. package/dist/{chunk-BH6WGYFB.js → chunk-VE3E4AMH.js} +8 -8
  18. package/dist/{chunk-5QGXARLJ.js → chunk-W5BZMKMF.js} +159 -27
  19. package/dist/{chunk-FF226TIV.js → chunk-ZX5623ER.js} +0 -57
  20. package/dist/cli/index.js +362 -4633
  21. package/dist/{conduct-N52JX7RT.js → conduct-KM6ZNJGE.js} +10 -8
  22. package/dist/{conduct-GZQNFTRP.js → conduct-WGTMQND5.js} +10 -8
  23. package/dist/{conductor-mode-XUWGR4ZE.js → conductor-mode-OL2FNOYY.js} +6 -4
  24. package/dist/{conductor-mode-ESGFZ6T5.js → conductor-mode-VRO7TYW2.js} +20 -167
  25. package/dist/execute-CPFSOOO3.js +13 -0
  26. package/dist/execute-IP2QHALV.js +10 -0
  27. package/dist/index.d.ts +14 -8
  28. package/dist/index.js +186 -35
  29. package/dist/{peers-E4MKNNDN.js → peers-CJ7T4RJO.js} +2 -1
  30. package/dist/process-guard-CC7CNRQJ.js +176 -0
  31. package/dist/{request-4GQSSM4B.js → request-YOWPXVLQ.js} +13 -10
  32. package/dist/schema-7BSSLZ4S.js +8 -0
  33. package/dist/{serve-skill-Q6NHX2RA.js → serve-skill-JHFNR7BW.js} +8 -7
  34. package/dist/{server-B5E566CI.js → server-HKJJWFRG.js} +10 -8
  35. package/dist/service-coordinator-5R4LQW6L.js +4917 -0
  36. package/dist/skills/agentbnb/bootstrap.js +5028 -848
  37. package/dist/websocket-client-WRN3HO73.js +6 -0
  38. package/package.json +4 -1
  39. package/skills/agentbnb/SKILL.md +87 -70
  40. package/skills/agentbnb/bootstrap.test.ts +142 -242
  41. package/skills/agentbnb/bootstrap.ts +88 -95
  42. package/skills/agentbnb/install.sh +97 -27
  43. package/dist/card-RNEWSAQ6.js +0 -88
  44. package/dist/chunk-UB2NPFC7.js +0 -165
  45. package/dist/execute-QH6F54D7.js +0 -10
@@ -0,0 +1,25 @@
1
+ // src/feedback/schema.ts
2
+ import { z } from "zod";
3
+ var StructuredFeedbackSchema = z.object({
4
+ transaction_id: z.string().uuid(),
5
+ // must match a request_log entry id
6
+ provider_agent: z.string().min(1),
7
+ skill_id: z.string().min(1),
8
+ requester_agent: z.string().min(1),
9
+ rating: z.number().int().min(1).max(5),
10
+ latency_ms: z.number().int().min(0),
11
+ result_quality: z.enum(["excellent", "good", "acceptable", "poor", "failed"]),
12
+ quality_details: z.string().max(500).optional(),
13
+ would_reuse: z.boolean(),
14
+ cost_value_ratio: z.enum(["great", "fair", "overpriced"]),
15
+ timestamp: z.string().datetime()
16
+ });
17
+ var FeedbackResponseSchema = z.object({
18
+ feedback_id: z.string().uuid(),
19
+ received_at: z.string().datetime()
20
+ });
21
+
22
+ export {
23
+ StructuredFeedbackSchema,
24
+ FeedbackResponseSchema
25
+ };
@@ -0,0 +1,393 @@
1
+ import {
2
+ getFeedbackForProvider,
3
+ signEscrowReceipt
4
+ } from "./chunk-CRFCWD6V.js";
5
+ import {
6
+ AgentBnBError
7
+ } from "./chunk-WGZ5AGOX.js";
8
+
9
+ // src/utils/interpolation.ts
10
+ function resolvePath(obj, path) {
11
+ const segments = path.replace(/\[(\d+)\]/g, ".$1").split(".").filter((s) => s.length > 0);
12
+ let current = obj;
13
+ for (const segment of segments) {
14
+ if (current === null || current === void 0) {
15
+ return void 0;
16
+ }
17
+ if (typeof current !== "object") {
18
+ return void 0;
19
+ }
20
+ current = current[segment];
21
+ }
22
+ return current;
23
+ }
24
+ function interpolate(template, context) {
25
+ return template.replace(/\$\{([^}]+)\}/g, (_match, expression) => {
26
+ const resolved = resolvePath(context, expression.trim());
27
+ if (resolved === void 0 || resolved === null) {
28
+ return "";
29
+ }
30
+ if (typeof resolved === "object") {
31
+ return JSON.stringify(resolved);
32
+ }
33
+ return String(resolved);
34
+ });
35
+ }
36
+ function interpolateObject(obj, context) {
37
+ const result = {};
38
+ for (const [key, value] of Object.entries(obj)) {
39
+ result[key] = interpolateValue(value, context);
40
+ }
41
+ return result;
42
+ }
43
+ function interpolateValue(value, context) {
44
+ if (typeof value === "string") {
45
+ return interpolate(value, context);
46
+ }
47
+ if (Array.isArray(value)) {
48
+ return value.map((item) => interpolateValue(item, context));
49
+ }
50
+ if (value !== null && typeof value === "object") {
51
+ return interpolateObject(value, context);
52
+ }
53
+ return value;
54
+ }
55
+
56
+ // src/feedback/reputation.ts
57
+ var QUALITY_SCORES = {
58
+ excellent: 1,
59
+ good: 0.8,
60
+ acceptable: 0.6,
61
+ poor: 0.3,
62
+ failed: 0
63
+ };
64
+ var COST_VALUE_SCORES = {
65
+ great: 1,
66
+ fair: 0.6,
67
+ overpriced: 0.2
68
+ };
69
+ var DECAY_DAYS = 30;
70
+ var WEIGHTS = {
71
+ rating: 0.4,
72
+ quality: 0.3,
73
+ would_reuse: 0.2,
74
+ cost_value: 0.1
75
+ };
76
+ function computeReputation(feedbacks) {
77
+ if (feedbacks.length === 0) return 0.5;
78
+ const now = Date.now();
79
+ let weightedSum = 0;
80
+ let totalWeight = 0;
81
+ for (const fb of feedbacks) {
82
+ const feedbackDate = new Date(fb.timestamp).getTime();
83
+ const ageDays = Math.max(0, (now - feedbackDate) / (1e3 * 60 * 60 * 24));
84
+ const recencyWeight = Math.exp(-ageDays / DECAY_DAYS);
85
+ const ratingScore = (fb.rating - 1) / 4;
86
+ const qualityScore = QUALITY_SCORES[fb.result_quality];
87
+ const reuseScore = fb.would_reuse ? 1 : 0;
88
+ const costScore = COST_VALUE_SCORES[fb.cost_value_ratio];
89
+ const componentScore = WEIGHTS.rating * ratingScore + WEIGHTS.quality * qualityScore + WEIGHTS.would_reuse * reuseScore + WEIGHTS.cost_value * costScore;
90
+ weightedSum += recencyWeight * componentScore;
91
+ totalWeight += recencyWeight;
92
+ }
93
+ if (totalWeight === 0) return 0.5;
94
+ const raw = weightedSum / totalWeight;
95
+ return Math.max(0, Math.min(1, raw));
96
+ }
97
+ function getReputationScore(db, agentId) {
98
+ const feedbacks = getFeedbackForProvider(db, agentId);
99
+ return computeReputation(feedbacks);
100
+ }
101
+
102
+ // src/registry/matcher.ts
103
+ function searchCards(db, query, filters = {}) {
104
+ const words = query.trim().split(/\s+/).map((w) => w.replace(/["*^{}():]/g, "")).filter((w) => w.length > 0);
105
+ if (words.length === 0) return [];
106
+ const ftsQuery = words.map((w) => `"${w}"`).join(" OR ");
107
+ const conditions = [];
108
+ const params = [ftsQuery];
109
+ if (filters.level !== void 0) {
110
+ conditions.push(`json_extract(cc.data, '$.level') = ?`);
111
+ params.push(filters.level);
112
+ }
113
+ if (filters.online !== void 0) {
114
+ conditions.push(`json_extract(cc.data, '$.availability.online') = ?`);
115
+ params.push(filters.online ? 1 : 0);
116
+ }
117
+ const whereClause = conditions.length > 0 ? `AND ${conditions.join(" AND ")}` : "";
118
+ const sql = `
119
+ SELECT cc.data
120
+ FROM capability_cards cc
121
+ JOIN cards_fts ON cc.rowid = cards_fts.rowid
122
+ WHERE cards_fts MATCH ?
123
+ ${whereClause}
124
+ ORDER BY bm25(cards_fts)
125
+ LIMIT 50
126
+ `;
127
+ const stmt = db.prepare(sql);
128
+ const rows = stmt.all(...params);
129
+ const results = rows.map((row) => JSON.parse(row.data));
130
+ let filtered = results;
131
+ if (filters.apis_used && filters.apis_used.length > 0) {
132
+ const requiredApis = filters.apis_used;
133
+ filtered = filtered.filter((card) => {
134
+ const cardApis = card.metadata?.apis_used ?? [];
135
+ return requiredApis.every((api) => cardApis.includes(api));
136
+ });
137
+ }
138
+ if (filters.min_reputation !== void 0 && filters.min_reputation > 0) {
139
+ filtered = applyReputationFilter(db, filtered, filters.min_reputation);
140
+ }
141
+ return filtered;
142
+ }
143
+ function filterCards(db, filters) {
144
+ const conditions = [];
145
+ const params = [];
146
+ if (filters.level !== void 0) {
147
+ conditions.push(`json_extract(data, '$.level') = ?`);
148
+ params.push(filters.level);
149
+ }
150
+ if (filters.online !== void 0) {
151
+ conditions.push(`json_extract(data, '$.availability.online') = ?`);
152
+ params.push(filters.online ? 1 : 0);
153
+ }
154
+ const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
155
+ const sql = `SELECT data FROM capability_cards ${whereClause}`;
156
+ const stmt = db.prepare(sql);
157
+ const rows = stmt.all(...params);
158
+ let cards = rows.map((row) => JSON.parse(row.data));
159
+ if (filters.min_reputation !== void 0 && filters.min_reputation > 0) {
160
+ cards = applyReputationFilter(db, cards, filters.min_reputation);
161
+ }
162
+ return cards;
163
+ }
164
+ function applyReputationFilter(db, cards, minReputation) {
165
+ const owners = [...new Set(cards.map((c) => c.owner))];
166
+ const reputationMap = /* @__PURE__ */ new Map();
167
+ for (const owner of owners) {
168
+ reputationMap.set(owner, getReputationScore(db, owner));
169
+ }
170
+ return cards.filter((card) => {
171
+ const score = reputationMap.get(card.owner) ?? 0.5;
172
+ return score >= minReputation;
173
+ });
174
+ }
175
+ function buildReputationMap(db, owners) {
176
+ const unique = [...new Set(owners)];
177
+ const map = /* @__PURE__ */ new Map();
178
+ for (const owner of unique) {
179
+ map.set(owner, getReputationScore(db, owner));
180
+ }
181
+ return map;
182
+ }
183
+
184
+ // src/gateway/client.ts
185
+ import { randomUUID } from "crypto";
186
+ async function requestCapability(opts) {
187
+ const { gatewayUrl, token, cardId, params = {}, timeoutMs = 3e5, escrowReceipt, identity } = opts;
188
+ const id = randomUUID();
189
+ const payload = {
190
+ jsonrpc: "2.0",
191
+ id,
192
+ method: "capability.execute",
193
+ params: {
194
+ card_id: cardId,
195
+ ...params,
196
+ ...escrowReceipt ? { escrow_receipt: escrowReceipt } : {}
197
+ }
198
+ };
199
+ const headers = { "Content-Type": "application/json" };
200
+ if (identity) {
201
+ const signature = signEscrowReceipt(payload, identity.privateKey);
202
+ headers["X-Agent-Id"] = identity.agentId;
203
+ headers["X-Agent-Public-Key"] = identity.publicKey;
204
+ headers["X-Agent-Signature"] = signature;
205
+ } else if (token) {
206
+ headers["Authorization"] = `Bearer ${token}`;
207
+ }
208
+ const controller = new AbortController();
209
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
210
+ let response;
211
+ try {
212
+ response = await fetch(`${gatewayUrl}/rpc`, {
213
+ method: "POST",
214
+ headers,
215
+ body: JSON.stringify(payload),
216
+ signal: controller.signal
217
+ });
218
+ } catch (err) {
219
+ clearTimeout(timer);
220
+ const isTimeout = err instanceof Error && err.name === "AbortError";
221
+ throw new AgentBnBError(
222
+ isTimeout ? "Request timed out" : `Network error: ${String(err)}`,
223
+ isTimeout ? "TIMEOUT" : "NETWORK_ERROR"
224
+ );
225
+ } finally {
226
+ clearTimeout(timer);
227
+ }
228
+ const body = await response.json();
229
+ if (body.error) {
230
+ throw new AgentBnBError(body.error.message, `RPC_ERROR_${body.error.code}`);
231
+ }
232
+ return body.result;
233
+ }
234
+ async function requestViaRelay(relay, opts) {
235
+ try {
236
+ return await relay.request({
237
+ targetOwner: opts.targetOwner,
238
+ cardId: opts.cardId,
239
+ skillId: opts.skillId,
240
+ params: opts.params ?? {},
241
+ requester: opts.requester,
242
+ escrowReceipt: opts.escrowReceipt,
243
+ timeoutMs: opts.timeoutMs
244
+ });
245
+ } catch (err) {
246
+ const message = err instanceof Error ? err.message : String(err);
247
+ if (message.includes("timeout")) {
248
+ throw new AgentBnBError(message, "TIMEOUT");
249
+ }
250
+ if (message.includes("offline")) {
251
+ throw new AgentBnBError(message, "AGENT_OFFLINE");
252
+ }
253
+ throw new AgentBnBError(message, "RELAY_ERROR");
254
+ }
255
+ }
256
+
257
+ // src/autonomy/tiers.ts
258
+ import { randomUUID as randomUUID2 } from "crypto";
259
+ var DEFAULT_AUTONOMY_CONFIG = {
260
+ tier1_max_credits: 0,
261
+ tier2_max_credits: 0
262
+ };
263
+ function getAutonomyTier(creditAmount, config) {
264
+ if (creditAmount < config.tier1_max_credits) return 1;
265
+ if (creditAmount < config.tier2_max_credits) return 2;
266
+ return 3;
267
+ }
268
+ function insertAuditEvent(db, event) {
269
+ const isShareEvent = event.type === "auto_share" || event.type === "auto_share_notify" || event.type === "auto_share_pending";
270
+ const cardId = isShareEvent ? "system" : event.card_id;
271
+ const creditsCharged = isShareEvent ? 0 : event.credits;
272
+ const stmt = db.prepare(`
273
+ INSERT INTO request_log (
274
+ id, card_id, card_name, requester, status, latency_ms, credits_charged,
275
+ created_at, skill_id, action_type, tier_invoked
276
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
277
+ `);
278
+ stmt.run(
279
+ randomUUID2(),
280
+ cardId,
281
+ "autonomy-audit",
282
+ "self",
283
+ "success",
284
+ 0,
285
+ creditsCharged,
286
+ (/* @__PURE__ */ new Date()).toISOString(),
287
+ event.skill_id,
288
+ event.type,
289
+ event.tier_invoked
290
+ );
291
+ }
292
+
293
+ // src/cli/remote-registry.ts
294
+ var RegistryTimeoutError = class extends AgentBnBError {
295
+ constructor(url) {
296
+ super(
297
+ `Registry at ${url} did not respond within 5s. Showing local results only.`,
298
+ "REGISTRY_TIMEOUT"
299
+ );
300
+ this.name = "RegistryTimeoutError";
301
+ }
302
+ };
303
+ var RegistryConnectionError = class extends AgentBnBError {
304
+ constructor(url) {
305
+ super(
306
+ `Cannot reach ${url}. Is the registry running? Showing local results only.`,
307
+ "REGISTRY_CONNECTION"
308
+ );
309
+ this.name = "RegistryConnectionError";
310
+ }
311
+ };
312
+ var RegistryAuthError = class extends AgentBnBError {
313
+ constructor(url) {
314
+ super(
315
+ `Authentication failed for ${url}. Run \`agentbnb config set token <your-token>\`.`,
316
+ "REGISTRY_AUTH"
317
+ );
318
+ this.name = "RegistryAuthError";
319
+ }
320
+ };
321
+ async function fetchRemoteCards(registryUrl, params, timeoutMs = 5e3) {
322
+ let cardsUrl;
323
+ try {
324
+ cardsUrl = new URL("/cards", registryUrl);
325
+ } catch {
326
+ throw new AgentBnBError(`Invalid registry URL: ${registryUrl}`, "INVALID_REGISTRY_URL");
327
+ }
328
+ const searchParams = new URLSearchParams();
329
+ if (params.q !== void 0) searchParams.set("q", params.q);
330
+ if (params.level !== void 0) searchParams.set("level", String(params.level));
331
+ if (params.online !== void 0) searchParams.set("online", String(params.online));
332
+ if (params.tag !== void 0) searchParams.set("tag", params.tag);
333
+ searchParams.set("limit", "100");
334
+ cardsUrl.search = searchParams.toString();
335
+ const controller = new AbortController();
336
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
337
+ let response;
338
+ try {
339
+ response = await fetch(cardsUrl.toString(), { signal: controller.signal });
340
+ } catch (err) {
341
+ clearTimeout(timer);
342
+ const isTimeout = err instanceof Error && err.name === "AbortError";
343
+ if (isTimeout) {
344
+ throw new RegistryTimeoutError(registryUrl);
345
+ }
346
+ throw new RegistryConnectionError(registryUrl);
347
+ } finally {
348
+ clearTimeout(timer);
349
+ }
350
+ if (response.status === 401 || response.status === 403) {
351
+ throw new RegistryAuthError(registryUrl);
352
+ }
353
+ if (!response.ok) {
354
+ throw new RegistryConnectionError(registryUrl);
355
+ }
356
+ const body = await response.json();
357
+ return body.items;
358
+ }
359
+
360
+ // src/autonomy/pending-requests.ts
361
+ import { randomUUID as randomUUID3 } from "crypto";
362
+ function listPendingRequests(db) {
363
+ const rows = db.prepare(`SELECT * FROM pending_requests WHERE status = 'pending' ORDER BY created_at DESC`).all();
364
+ return rows;
365
+ }
366
+ function resolvePendingRequest(db, id, resolution) {
367
+ const now = (/* @__PURE__ */ new Date()).toISOString();
368
+ const result = db.prepare(
369
+ `UPDATE pending_requests SET status = ?, resolved_at = ? WHERE id = ?`
370
+ ).run(resolution, now, id);
371
+ if (result.changes === 0) {
372
+ throw new AgentBnBError(
373
+ `Pending request not found: ${id}`,
374
+ "NOT_FOUND"
375
+ );
376
+ }
377
+ }
378
+
379
+ export {
380
+ interpolateObject,
381
+ computeReputation,
382
+ searchCards,
383
+ filterCards,
384
+ buildReputationMap,
385
+ requestCapability,
386
+ requestViaRelay,
387
+ DEFAULT_AUTONOMY_CONFIG,
388
+ getAutonomyTier,
389
+ insertAuditEvent,
390
+ listPendingRequests,
391
+ resolvePendingRequest,
392
+ fetchRemoteCards
393
+ };
@@ -1,7 +1,14 @@
1
1
  import {
2
- fetchRemoteCards,
2
+ createPendingRequest,
3
+ getAutonomyTier,
4
+ insertAuditEvent
5
+ } from "./chunk-CSATDXZC.js";
6
+ import {
7
+ fetchRemoteCards
8
+ } from "./chunk-ZX5623ER.js";
9
+ import {
3
10
  searchCards
4
- } from "./chunk-FF226TIV.js";
11
+ } from "./chunk-NH2FIERR.js";
5
12
  import {
6
13
  requestCapability
7
14
  } from "./chunk-XND2DWTZ.js";
@@ -13,46 +20,7 @@ import {
13
20
  holdEscrow,
14
21
  releaseEscrow,
15
22
  settleEscrow
16
- } from "./chunk-DNWT5FZQ.js";
17
- import {
18
- AgentBnBError
19
- } from "./chunk-WGZ5AGOX.js";
20
-
21
- // src/autonomy/tiers.ts
22
- import { randomUUID } from "crypto";
23
- var DEFAULT_AUTONOMY_CONFIG = {
24
- tier1_max_credits: 0,
25
- tier2_max_credits: 0
26
- };
27
- function getAutonomyTier(creditAmount, config) {
28
- if (creditAmount < config.tier1_max_credits) return 1;
29
- if (creditAmount < config.tier2_max_credits) return 2;
30
- return 3;
31
- }
32
- function insertAuditEvent(db, event) {
33
- const isShareEvent = event.type === "auto_share" || event.type === "auto_share_notify" || event.type === "auto_share_pending";
34
- const cardId = isShareEvent ? "system" : event.card_id;
35
- const creditsCharged = isShareEvent ? 0 : event.credits;
36
- const stmt = db.prepare(`
37
- INSERT INTO request_log (
38
- id, card_id, card_name, requester, status, latency_ms, credits_charged,
39
- created_at, skill_id, action_type, tier_invoked
40
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
41
- `);
42
- stmt.run(
43
- randomUUID(),
44
- cardId,
45
- "autonomy-audit",
46
- "self",
47
- "success",
48
- 0,
49
- creditsCharged,
50
- (/* @__PURE__ */ new Date()).toISOString(),
51
- event.skill_id,
52
- event.type,
53
- event.tier_invoked
54
- );
55
- }
23
+ } from "./chunk-EANI2N2V.js";
56
24
 
57
25
  // src/credit/budget.ts
58
26
  var DEFAULT_BUDGET_CONFIG = {
@@ -99,47 +67,6 @@ var BudgetManager = class {
99
67
  }
100
68
  };
101
69
 
102
- // src/autonomy/pending-requests.ts
103
- import { randomUUID as randomUUID2 } from "crypto";
104
- function createPendingRequest(db, opts) {
105
- const id = randomUUID2();
106
- const now = (/* @__PURE__ */ new Date()).toISOString();
107
- const paramsJson = opts.params !== void 0 ? JSON.stringify(opts.params) : null;
108
- db.prepare(`
109
- INSERT INTO pending_requests (
110
- id, skill_query, max_cost_credits, selected_peer, selected_card_id,
111
- selected_skill_id, credits, status, params, created_at, resolved_at
112
- ) VALUES (?, ?, ?, ?, ?, ?, ?, 'pending', ?, ?, NULL)
113
- `).run(
114
- id,
115
- opts.skill_query,
116
- opts.max_cost_credits,
117
- opts.selected_peer ?? null,
118
- opts.selected_card_id ?? null,
119
- opts.selected_skill_id ?? null,
120
- opts.credits,
121
- paramsJson,
122
- now
123
- );
124
- return id;
125
- }
126
- function listPendingRequests(db) {
127
- const rows = db.prepare(`SELECT * FROM pending_requests WHERE status = 'pending' ORDER BY created_at DESC`).all();
128
- return rows;
129
- }
130
- function resolvePendingRequest(db, id, resolution) {
131
- const now = (/* @__PURE__ */ new Date()).toISOString();
132
- const result = db.prepare(
133
- `UPDATE pending_requests SET status = ?, resolved_at = ? WHERE id = ?`
134
- ).run(resolution, now, id);
135
- if (result.changes === 0) {
136
- throw new AgentBnBError(
137
- `Pending request not found: ${id}`,
138
- "NOT_FOUND"
139
- );
140
- }
141
- }
142
-
143
70
  // src/autonomy/auto-request.ts
144
71
  function minMaxNormalize(values) {
145
72
  if (values.length === 0) return [];
@@ -154,11 +81,20 @@ function minMaxNormalize(values) {
154
81
  function scorePeers(candidates, selfOwner) {
155
82
  const eligible = candidates.filter((c) => c.card.owner !== selfOwner);
156
83
  if (eligible.length === 0) return [];
157
- const successRates = eligible.map((c) => c.card.metadata?.success_rate ?? 0.5);
84
+ const successRates = eligible.map((c) => {
85
+ if (c.skillMetadata?.success_rate !== void 0) {
86
+ return c.skillMetadata.success_rate;
87
+ }
88
+ return c.card.metadata?.success_rate ?? 0.5;
89
+ });
158
90
  const costEfficiencies = eligible.map((c) => c.cost === 0 ? 1 : 1 / c.cost);
159
91
  const idleRates = eligible.map((c) => {
92
+ if (c.skillInternal !== void 0) {
93
+ const skillIdleRate = c.skillInternal["idle_rate"];
94
+ if (typeof skillIdleRate === "number") return skillIdleRate;
95
+ }
160
96
  const internal = c.card._internal;
161
- const idleRate = internal?.idle_rate;
97
+ const idleRate = internal?.["idle_rate"];
162
98
  return typeof idleRate === "number" ? idleRate : 1;
163
99
  });
164
100
  const normSuccess = minMaxNormalize(successRates);
@@ -234,7 +170,14 @@ var AutoRequestor = class {
234
170
  for (const skill of cardAsV2.skills) {
235
171
  const cost = skill.pricing.credits_per_call;
236
172
  if (cost <= need.maxCostCredits) {
237
- candidates.push({ card, cost, skillId: skill.id });
173
+ candidates.push({
174
+ card,
175
+ cost,
176
+ skillId: skill.id,
177
+ // Carry skill-level metadata so scorePeers() can prefer it over card-level
178
+ skillMetadata: skill.metadata,
179
+ skillInternal: skill._internal
180
+ });
238
181
  }
239
182
  }
240
183
  } else {
@@ -348,13 +291,8 @@ var AutoRequestor = class {
348
291
  };
349
292
 
350
293
  export {
351
- DEFAULT_AUTONOMY_CONFIG,
352
- getAutonomyTier,
353
- insertAuditEvent,
354
294
  DEFAULT_BUDGET_CONFIG,
355
295
  BudgetManager,
356
- listPendingRequests,
357
- resolvePendingRequest,
358
296
  scorePeers,
359
297
  AutoRequestor
360
298
  };