open-agents-ai 0.184.7 → 0.184.9
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/index.js +231 -51
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5571,6 +5571,123 @@ async function handleCmd(cmd) {
|
|
|
5571
5571
|
writeResp(id, { ok: true, output: 'Message sent (id: ' + msgId + ')' });
|
|
5572
5572
|
break;
|
|
5573
5573
|
}
|
|
5574
|
+
// \u2500\u2500 Sponsor announcement via NATS \u2500\u2500
|
|
5575
|
+
case 'sponsor_announce': {
|
|
5576
|
+
// Publish sponsor metadata to NATS so other OA instances can discover it
|
|
5577
|
+
if (!_natsConn || !_natsCodec) {
|
|
5578
|
+
writeResp(id, { ok: false, output: 'NATS not connected \u2014 cannot announce sponsorship' });
|
|
5579
|
+
return;
|
|
5580
|
+
}
|
|
5581
|
+
var sponsorData = {
|
|
5582
|
+
type: 'sponsor.announce',
|
|
5583
|
+
peerId: globalThis._daemonPeerId || 'unknown',
|
|
5584
|
+
name: args.name || 'Anonymous Sponsor',
|
|
5585
|
+
models: args.models || [],
|
|
5586
|
+
tunnelUrl: args.tunnel_url || null,
|
|
5587
|
+
authKey: args.auth_key || '',
|
|
5588
|
+
limits: {
|
|
5589
|
+
maxRequestsPerMinute: parseInt(args.rpm || '60', 10),
|
|
5590
|
+
maxTokensPerDay: parseInt(args.tpd || '100000', 10),
|
|
5591
|
+
},
|
|
5592
|
+
banner: args.banner || null,
|
|
5593
|
+
message: args.message || '',
|
|
5594
|
+
linkUrl: args.link_url || '',
|
|
5595
|
+
linkText: args.link_text || '',
|
|
5596
|
+
status: 'active',
|
|
5597
|
+
timestamp: Date.now(),
|
|
5598
|
+
};
|
|
5599
|
+
_natsConn.publish('nexus.sponsors.announce', _natsCodec.encode(JSON.stringify(sponsorData)));
|
|
5600
|
+
dlog('sponsor_announce: published to nexus.sponsors.announce');
|
|
5601
|
+
// Also join the sponsors room and send as room message for persistence
|
|
5602
|
+
if (!rooms.has('sponsors')) {
|
|
5603
|
+
try {
|
|
5604
|
+
var spRoom = await nexus.joinRoom('sponsors');
|
|
5605
|
+
rooms.set('sponsors', spRoom);
|
|
5606
|
+
dlog('sponsor_announce: auto-joined sponsors room');
|
|
5607
|
+
} catch (roomErr) {
|
|
5608
|
+
dlog('sponsor_announce: room join failed: ' + (roomErr.message || roomErr));
|
|
5609
|
+
}
|
|
5610
|
+
}
|
|
5611
|
+
if (rooms.has('sponsors')) {
|
|
5612
|
+
try {
|
|
5613
|
+
await rooms.get('sponsors').send(JSON.stringify(sponsorData), { format: 'application/json' });
|
|
5614
|
+
} catch {}
|
|
5615
|
+
}
|
|
5616
|
+
writeResp(id, { ok: true, output: 'Sponsor announced: ' + sponsorData.name + ' (' + sponsorData.models.length + ' models)' });
|
|
5617
|
+
break;
|
|
5618
|
+
}
|
|
5619
|
+
case 'sponsor_discover': {
|
|
5620
|
+
// Subscribe to nexus.sponsors.announce for a short window and collect announcements
|
|
5621
|
+
if (!_natsConn || !_natsCodec) {
|
|
5622
|
+
writeResp(id, { ok: false, output: 'NATS not connected', sponsors: [] });
|
|
5623
|
+
return;
|
|
5624
|
+
}
|
|
5625
|
+
var foundSponsors = [];
|
|
5626
|
+
var discoverTimeout = parseInt(args.timeout_ms || '5000', 10);
|
|
5627
|
+
|
|
5628
|
+
// Also check sponsors room inbox for cached messages
|
|
5629
|
+
var sponsorInbox = join(inboxDir, 'sponsors');
|
|
5630
|
+
try {
|
|
5631
|
+
if (existsSync(sponsorInbox)) {
|
|
5632
|
+
var inboxFiles = readdirSync(sponsorInbox).filter(f => f.endsWith('.json')).sort().reverse().slice(0, 20);
|
|
5633
|
+
for (var fi = 0; fi < inboxFiles.length; fi++) {
|
|
5634
|
+
try {
|
|
5635
|
+
var msg = JSON.parse(readFileSync(join(sponsorInbox, inboxFiles[fi]), 'utf8'));
|
|
5636
|
+
var content = msg.content || '';
|
|
5637
|
+
try {
|
|
5638
|
+
var parsed = JSON.parse(content);
|
|
5639
|
+
if (parsed.type === 'sponsor.announce' && parsed.status === 'active') {
|
|
5640
|
+
// Only include if not too stale (< 10 minutes)
|
|
5641
|
+
if (Date.now() - (parsed.timestamp || 0) < 600000) {
|
|
5642
|
+
foundSponsors.push(parsed);
|
|
5643
|
+
}
|
|
5644
|
+
}
|
|
5645
|
+
} catch {}
|
|
5646
|
+
} catch {}
|
|
5647
|
+
}
|
|
5648
|
+
}
|
|
5649
|
+
} catch {}
|
|
5650
|
+
|
|
5651
|
+
// Join sponsors room to receive future announcements
|
|
5652
|
+
if (!rooms.has('sponsors')) {
|
|
5653
|
+
try {
|
|
5654
|
+
var spRoom2 = await nexus.joinRoom('sponsors');
|
|
5655
|
+
rooms.set('sponsors', spRoom2);
|
|
5656
|
+
} catch {}
|
|
5657
|
+
}
|
|
5658
|
+
|
|
5659
|
+
// Subscribe to NATS for live announcements (short window)
|
|
5660
|
+
try {
|
|
5661
|
+
var sub = _natsConn.subscribe('nexus.sponsors.announce');
|
|
5662
|
+
var subDone = false;
|
|
5663
|
+
setTimeout(() => { subDone = true; sub.unsubscribe(); }, discoverTimeout);
|
|
5664
|
+
for await (var natMsg of sub) {
|
|
5665
|
+
if (subDone) break;
|
|
5666
|
+
try {
|
|
5667
|
+
var sp = JSON.parse(_natsCodec.decode(natMsg.data));
|
|
5668
|
+
if (sp.type === 'sponsor.announce' && sp.status === 'active') {
|
|
5669
|
+
foundSponsors.push(sp);
|
|
5670
|
+
}
|
|
5671
|
+
} catch {}
|
|
5672
|
+
}
|
|
5673
|
+
} catch (subErr) {
|
|
5674
|
+
dlog('sponsor_discover: NATS sub error: ' + (subErr.message || subErr));
|
|
5675
|
+
}
|
|
5676
|
+
|
|
5677
|
+
// Deduplicate by peerId
|
|
5678
|
+
var seen = {};
|
|
5679
|
+
var unique = [];
|
|
5680
|
+
for (var si = 0; si < foundSponsors.length; si++) {
|
|
5681
|
+
var key = foundSponsors[si].peerId || foundSponsors[si].tunnelUrl || ('sp-' + si);
|
|
5682
|
+
if (!seen[key]) {
|
|
5683
|
+
seen[key] = true;
|
|
5684
|
+
unique.push(foundSponsors[si]);
|
|
5685
|
+
}
|
|
5686
|
+
}
|
|
5687
|
+
|
|
5688
|
+
writeResp(id, { ok: true, output: unique.length + ' sponsor(s) found', sponsors: unique });
|
|
5689
|
+
break;
|
|
5690
|
+
}
|
|
5574
5691
|
case 'discover_peers': {
|
|
5575
5692
|
const node = nexus.network?.node;
|
|
5576
5693
|
const peers = node?.getPeers?.() || [];
|
|
@@ -8173,6 +8290,12 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
8173
8290
|
case "expose":
|
|
8174
8291
|
result = await this.sendDaemonCmd("expose", args, 6e4);
|
|
8175
8292
|
break;
|
|
8293
|
+
case "sponsor_announce":
|
|
8294
|
+
result = await this.sendDaemonCmd("sponsor_announce", args, 1e4);
|
|
8295
|
+
break;
|
|
8296
|
+
case "sponsor_discover":
|
|
8297
|
+
result = await this.sendDaemonCmd("sponsor_discover", args, 1e4);
|
|
8298
|
+
break;
|
|
8176
8299
|
case "pricing_menu":
|
|
8177
8300
|
result = await this.sendDaemonCmd("pricing_menu", args);
|
|
8178
8301
|
break;
|
|
@@ -47236,6 +47359,28 @@ async function handleSlashCommand(input, ctx) {
|
|
|
47236
47359
|
renderError(`P2P start failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
47237
47360
|
}
|
|
47238
47361
|
}
|
|
47362
|
+
try {
|
|
47363
|
+
const { NexusTool: NexusTool2 } = __require("@open-agents/execution");
|
|
47364
|
+
const nexus = new NexusTool2(projectDir);
|
|
47365
|
+
const tunnelGw = ctx.getExposeGateway?.();
|
|
47366
|
+
const enabledEps = config.endpoints.filter((e) => e.enabled);
|
|
47367
|
+
const allModels = enabledEps.flatMap((e) => e.models || []);
|
|
47368
|
+
await nexus.execute({
|
|
47369
|
+
action: "sponsor_announce",
|
|
47370
|
+
name: config.header.message || "OA Sponsor",
|
|
47371
|
+
models: allModels.join(","),
|
|
47372
|
+
tunnel_url: tunnelGw?.tunnelUrl || "",
|
|
47373
|
+
auth_key: tunnelGw?.authKey || "",
|
|
47374
|
+
rpm: String(config.rateLimits.maxRequestsPerMinute),
|
|
47375
|
+
tpd: String(config.rateLimits.maxTokensPerDay),
|
|
47376
|
+
banner: config.banner.preset,
|
|
47377
|
+
message: config.header.message,
|
|
47378
|
+
link_url: config.header.linkUrl,
|
|
47379
|
+
link_text: config.header.linkText
|
|
47380
|
+
});
|
|
47381
|
+
renderInfo("Announced on nexus P2P mesh \u2014 other users can discover you via /endpoint sponsor");
|
|
47382
|
+
} catch {
|
|
47383
|
+
}
|
|
47239
47384
|
}
|
|
47240
47385
|
});
|
|
47241
47386
|
if (result) {
|
|
@@ -49006,39 +49151,75 @@ async function handleEndpoint(arg, ctx, local = false) {
|
|
|
49006
49151
|
async function handleSponsoredEndpoint(ctx, local) {
|
|
49007
49152
|
process.stdout.write(`
|
|
49008
49153
|
${c2.dim("Scanning for sponsored inference endpoints...")}
|
|
49009
|
-
|
|
49010
49154
|
`);
|
|
49011
49155
|
const sponsors = [];
|
|
49156
|
+
let nexusTool = null;
|
|
49157
|
+
try {
|
|
49158
|
+
const { NexusTool: NexusTool2 } = __require("@open-agents/execution");
|
|
49159
|
+
nexusTool = new NexusTool2(ctx.repoRoot ?? process.cwd());
|
|
49160
|
+
} catch {
|
|
49161
|
+
}
|
|
49162
|
+
if (nexusTool) {
|
|
49163
|
+
process.stdout.write(` ${c2.dim("Connecting to nexus P2P mesh...")}
|
|
49164
|
+
`);
|
|
49165
|
+
try {
|
|
49166
|
+
const statusResult = await nexusTool.execute({ action: "status" });
|
|
49167
|
+
const isConnected = typeof statusResult === "string" && statusResult.includes("connected");
|
|
49168
|
+
if (!isConnected) {
|
|
49169
|
+
process.stdout.write(` ${c2.dim("Starting nexus daemon...")}
|
|
49170
|
+
`);
|
|
49171
|
+
await nexusTool.execute({ action: "connect" });
|
|
49172
|
+
await new Promise((r) => setTimeout(r, 3e3));
|
|
49173
|
+
}
|
|
49174
|
+
process.stdout.write(` ${c2.dim("Querying nexus sponsors room...")}
|
|
49175
|
+
`);
|
|
49176
|
+
const discoverResult = await nexusTool.execute({
|
|
49177
|
+
action: "sponsor_discover",
|
|
49178
|
+
timeout_ms: "5000"
|
|
49179
|
+
});
|
|
49180
|
+
if (typeof discoverResult === "string") {
|
|
49181
|
+
try {
|
|
49182
|
+
const parsed = JSON.parse(discoverResult);
|
|
49183
|
+
const nexusSponsors = parsed.sponsors || [];
|
|
49184
|
+
for (const ns of nexusSponsors) {
|
|
49185
|
+
sponsors.push({
|
|
49186
|
+
name: ns.name || "Unknown Sponsor",
|
|
49187
|
+
url: ns.tunnelUrl || "",
|
|
49188
|
+
peerId: ns.peerId || void 0,
|
|
49189
|
+
authKey: ns.authKey || "",
|
|
49190
|
+
models: Array.isArray(ns.models) ? ns.models : (ns.models || "").split(",").filter(Boolean),
|
|
49191
|
+
limits: {
|
|
49192
|
+
rpm: ns.limits?.maxRequestsPerMinute || 60,
|
|
49193
|
+
tpd: ns.limits?.maxTokensPerDay || 1e5
|
|
49194
|
+
},
|
|
49195
|
+
source: "nexus",
|
|
49196
|
+
banner: { preset: ns.banner?.preset, message: ns.message }
|
|
49197
|
+
});
|
|
49198
|
+
}
|
|
49199
|
+
if (nexusSponsors.length > 0) {
|
|
49200
|
+
process.stdout.write(` ${c2.green("\u25CF")} Found ${nexusSponsors.length} sponsor(s) on nexus mesh
|
|
49201
|
+
`);
|
|
49202
|
+
}
|
|
49203
|
+
} catch {
|
|
49204
|
+
}
|
|
49205
|
+
}
|
|
49206
|
+
} catch (nexusErr) {
|
|
49207
|
+
process.stdout.write(` ${c2.dim("Nexus unavailable: " + (nexusErr instanceof Error ? nexusErr.message : String(nexusErr)).slice(0, 60))}
|
|
49208
|
+
`);
|
|
49209
|
+
}
|
|
49210
|
+
}
|
|
49012
49211
|
const gateway = ctx.getExposeGateway?.();
|
|
49013
49212
|
if (gateway && gateway.isActive) {
|
|
49014
49213
|
const gwUrl = gateway.tunnelUrl || `http://127.0.0.1:${gateway._proxyPort || 11434}`;
|
|
49015
|
-
sponsors.
|
|
49016
|
-
|
|
49017
|
-
|
|
49018
|
-
|
|
49019
|
-
|
|
49020
|
-
|
|
49021
|
-
|
|
49022
|
-
|
|
49023
|
-
|
|
49024
|
-
const { loadSponsorConfig: loadSpCfg } = await Promise.resolve().then(() => (init_sponsor_wizard(), sponsor_wizard_exports));
|
|
49025
|
-
const spCfg = loadSpCfg(ctx.repoRoot ?? process.cwd());
|
|
49026
|
-
if (spCfg && spCfg.status === "active") {
|
|
49027
|
-
const epUrls = new Set(sponsors.map((s) => s.url));
|
|
49028
|
-
for (const ep of spCfg.endpoints.filter((e) => e.enabled)) {
|
|
49029
|
-
if (!epUrls.has(ep.url)) {
|
|
49030
|
-
sponsors.push({
|
|
49031
|
-
name: ep.label,
|
|
49032
|
-
url: ep.url,
|
|
49033
|
-
authKey: "",
|
|
49034
|
-
models: ep.models,
|
|
49035
|
-
limits: {
|
|
49036
|
-
rpm: spCfg.rateLimits.maxRequestsPerMinute,
|
|
49037
|
-
tpd: spCfg.rateLimits.maxTokensPerDay
|
|
49038
|
-
},
|
|
49039
|
-
source: "local"
|
|
49040
|
-
});
|
|
49041
|
-
}
|
|
49214
|
+
if (!sponsors.some((s) => s.url === gwUrl)) {
|
|
49215
|
+
sponsors.push({
|
|
49216
|
+
name: "Local Gateway",
|
|
49217
|
+
url: gwUrl,
|
|
49218
|
+
authKey: gateway.authKey,
|
|
49219
|
+
models: [],
|
|
49220
|
+
limits: { rpm: 60, tpd: 1e5 },
|
|
49221
|
+
source: "local"
|
|
49222
|
+
});
|
|
49042
49223
|
}
|
|
49043
49224
|
}
|
|
49044
49225
|
const sponsorDir2 = join58(ctx.repoRoot ?? process.cwd(), ".oa", "sponsor");
|
|
@@ -49047,30 +49228,19 @@ async function handleSponsoredEndpoint(ctx, local) {
|
|
|
49047
49228
|
if (existsSync42(knownFile)) {
|
|
49048
49229
|
const saved = JSON.parse(readFileSync31(knownFile, "utf8"));
|
|
49049
49230
|
for (const s of saved) {
|
|
49050
|
-
|
|
49051
|
-
|
|
49052
|
-
headers: s.authKey ? { Authorization: `Bearer ${s.authKey}` } : {},
|
|
49053
|
-
signal: AbortSignal.timeout(5e3)
|
|
49054
|
-
});
|
|
49055
|
-
if (probe.ok) {
|
|
49056
|
-
const data = await probe.json();
|
|
49057
|
-
s.models = (data.models || []).map((m) => m.name);
|
|
49058
|
-
sponsors.push(s);
|
|
49059
|
-
}
|
|
49060
|
-
} catch {
|
|
49231
|
+
if (!sponsors.some((sp) => sp.url === s.url)) {
|
|
49232
|
+
sponsors.push({ ...s, source: "saved" });
|
|
49061
49233
|
}
|
|
49062
49234
|
}
|
|
49063
49235
|
}
|
|
49064
49236
|
} catch {
|
|
49065
49237
|
}
|
|
49238
|
+
process.stdout.write("\n");
|
|
49066
49239
|
if (sponsors.length === 0) {
|
|
49067
|
-
renderInfo("No sponsored endpoints found.");
|
|
49068
|
-
renderInfo("");
|
|
49069
|
-
renderInfo("To connect to a sponsor, use:");
|
|
49070
|
-
renderInfo(" /endpoint <tunnel-url> --auth <key>");
|
|
49240
|
+
renderInfo("No sponsored endpoints found on the nexus mesh.");
|
|
49071
49241
|
renderInfo("");
|
|
49072
|
-
renderInfo("
|
|
49073
|
-
renderInfo("
|
|
49242
|
+
renderInfo("Make sure the nexus is connected (/nexus) and sponsors are online.");
|
|
49243
|
+
renderInfo("Or connect directly: /endpoint <tunnel-url> --auth <key>");
|
|
49074
49244
|
return;
|
|
49075
49245
|
}
|
|
49076
49246
|
const items = [
|
|
@@ -49078,9 +49248,10 @@ async function handleSponsoredEndpoint(ctx, local) {
|
|
|
49078
49248
|
];
|
|
49079
49249
|
for (const sp of sponsors) {
|
|
49080
49250
|
const modelList = sp.models.length > 0 ? sp.models.slice(0, 3).join(", ") + (sp.models.length > 3 ? ` +${sp.models.length - 3}` : "") : "probing...";
|
|
49251
|
+
const transport = sp.url ? "tunnel" : sp.peerId ? "p2p" : "?";
|
|
49081
49252
|
items.push({
|
|
49082
|
-
key: sp.url,
|
|
49083
|
-
label: ` ${sp.name} (${sp.source})`,
|
|
49253
|
+
key: sp.url || sp.peerId || sp.name,
|
|
49254
|
+
label: ` ${sp.name} (${sp.source}, ${transport})`,
|
|
49084
49255
|
detail: ` Models: ${modelList} | ${sp.limits.rpm} req/min, ${sp.limits.tpd >= 1e3 ? (sp.limits.tpd / 1e3).toFixed(0) + "K" : sp.limits.tpd} tokens/day`
|
|
49085
49256
|
});
|
|
49086
49257
|
}
|
|
@@ -49108,15 +49279,24 @@ async function handleSponsoredEndpoint(ctx, local) {
|
|
|
49108
49279
|
renderInfo("Use: /endpoint <tunnel-url> --auth <key>");
|
|
49109
49280
|
return;
|
|
49110
49281
|
}
|
|
49111
|
-
const
|
|
49282
|
+
const selectedKey = result.key;
|
|
49283
|
+
const selected = sponsors.find((s) => (s.url || s.peerId || s.name) === selectedKey);
|
|
49112
49284
|
if (!selected)
|
|
49113
49285
|
return;
|
|
49114
|
-
|
|
49115
|
-
|
|
49286
|
+
if (selected.url && selected.url.startsWith("http")) {
|
|
49287
|
+
const endpointArg = selected.authKey ? `${selected.url} --auth ${selected.authKey}` : selected.url;
|
|
49288
|
+
await handleEndpoint(endpointArg, ctx, local);
|
|
49289
|
+
} else if (selected.peerId) {
|
|
49290
|
+
await handlePeerEndpoint(selected.peerId, selected.authKey || void 0, ctx, local);
|
|
49291
|
+
} else {
|
|
49292
|
+
renderError("Sponsor has no reachable endpoint (no tunnel URL or peer ID).");
|
|
49293
|
+
return;
|
|
49294
|
+
}
|
|
49295
|
+
const saveKey = selected.url || selected.peerId || selected.name;
|
|
49116
49296
|
try {
|
|
49117
49297
|
mkdirSync18(sponsorDir2, { recursive: true });
|
|
49118
49298
|
const existing = existsSync42(knownFile) ? JSON.parse(readFileSync31(knownFile, "utf8")) : [];
|
|
49119
|
-
const updated = existing.filter((s) => s.url
|
|
49299
|
+
const updated = existing.filter((s) => (s.url || s.peerId || s.name) !== saveKey);
|
|
49120
49300
|
updated.push(selected);
|
|
49121
49301
|
writeFileSync19(knownFile, JSON.stringify(updated, null, 2), "utf8");
|
|
49122
49302
|
} catch {
|
package/package.json
CHANGED