open-agents-ai 0.184.6 → 0.184.8

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 (3) hide show
  1. package/README.md +0 -10
  2. package/dist/index.js +309 -82
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -26,16 +26,6 @@ An autonomous multi-turn tool-calling agent that reads your code, makes changes,
26
26
 
27
27
  An LLM is a high-bandwidth associative generative core — closer to a cortex-like prior than to a complete agent. Its weights contain broad latent structure, but they do not by themselves give you situated continuity, durable task state, calibrated action policies, or grounded memory management. Open Agents treats the model as one organ inside a larger organism. The framework provides the rest: sensors, effectors, memory stores, routing, gating, evaluation, and persistence.
28
28
 
29
- **Empirical proof** — 65 IQ-grade reasoning tasks (LSAT Logic Games, Bayesian probability, cryptarithmetic, constraint satisfaction, formal logic):
30
-
31
- | | With Framework (Full Organism) | Pure Reasoning (Cortex Only) |
32
- |---|---|---|
33
- | **4B model** | 65/65 (100%) | 15/15 (100%) |
34
- | **9B model** | 50/50 (100%) | 12/15 (80%) |
35
- | **30B model** | 20/20 (100%) | 11/15 (73%) |
36
-
37
- When the framework provides externalized computation (shell), persistent state (files), and verification loops (validators) — model size becomes irrelevant. A 4B model with the full agentic framework outperforms a 30B model reasoning alone.
38
-
39
29
  **What the framework provides:**
40
30
 
41
31
  | Layer | Biological Analog | Implementation |
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;
@@ -42644,21 +42767,29 @@ async function stepBanner(config, rl, availableRows) {
42644
42767
  return false;
42645
42768
  }
42646
42769
  async function stepHeader(config, rl, availableRows) {
42770
+ function msgDetail() {
42771
+ return config.header.message || "(none set \u2014 press Enter to edit)";
42772
+ }
42773
+ function linkDetail() {
42774
+ return config.header.linkUrl ? `${config.header.linkUrl} [${config.header.linkText || "link"}]` : "(none set \u2014 press Enter to edit)";
42775
+ }
42647
42776
  const items = [
42648
42777
  { key: "hdr", label: "Header Content" },
42649
42778
  {
42650
42779
  key: "message_toggle",
42651
42780
  label: `${config.header.messageEnabled ? "[x]" : "[ ]"} Header Message`,
42652
- detail: config.header.message || "(none set)"
42781
+ detail: msgDetail()
42653
42782
  },
42654
42783
  {
42655
42784
  key: "link_toggle",
42656
42785
  label: `${config.header.linkEnabled ? "[x]" : "[ ]"} Link`,
42657
- detail: config.header.linkUrl ? `${config.header.linkUrl} [${config.header.linkText || "link"}]` : "(none set)"
42786
+ detail: linkDetail()
42658
42787
  },
42659
42788
  { key: "sep", label: "" },
42660
42789
  { key: "next", label: selectColors.green(" Next Step \u2192") }
42661
42790
  ];
42791
+ const msgIdx = 1;
42792
+ const linkIdx = 2;
42662
42793
  const result = await tuiSelect({
42663
42794
  items,
42664
42795
  title: "Step 3/5 \u2014 Header Text & Links",
@@ -42679,31 +42810,52 @@ async function stepHeader(config, rl, availableRows) {
42679
42810
  }
42680
42811
  }
42681
42812
  return false;
42813
+ },
42814
+ // Use onCustomKey + helpers.getInput() for proper inline text capture
42815
+ // (same pattern as TTS clone rename in voice list)
42816
+ customKeyHint: " e edit space toggle",
42817
+ onCustomKey: (item, key, helpers) => {
42818
+ if ((key === "e" || key === "E") && item.key === "message_toggle") {
42819
+ config.header.messageEnabled = true;
42820
+ helpers.getInput("Header message:", config.header.message).then((text) => {
42821
+ if (text !== null && text.trim()) {
42822
+ config.header.message = text.trim().slice(0, 80);
42823
+ helpers.updateItem(msgIdx, {
42824
+ label: `[x] Header Message`,
42825
+ detail: msgDetail()
42826
+ });
42827
+ }
42828
+ helpers.render();
42829
+ });
42830
+ return true;
42831
+ }
42832
+ if ((key === "e" || key === "E") && item.key === "link_toggle") {
42833
+ config.header.linkEnabled = true;
42834
+ helpers.getInput("Link URL:", config.header.linkUrl).then((url) => {
42835
+ if (url !== null && url.trim()) {
42836
+ config.header.linkUrl = url.trim();
42837
+ helpers.getInput("Link text:", config.header.linkText).then((text) => {
42838
+ if (text !== null && text.trim()) {
42839
+ config.header.linkText = text.trim();
42840
+ }
42841
+ helpers.updateItem(linkIdx, {
42842
+ label: `[x] Link`,
42843
+ detail: linkDetail()
42844
+ });
42845
+ helpers.render();
42846
+ });
42847
+ } else {
42848
+ helpers.render();
42849
+ }
42850
+ });
42851
+ return true;
42852
+ }
42853
+ return false;
42682
42854
  }
42683
42855
  });
42684
42856
  if (!result.confirmed)
42685
42857
  return false;
42686
- if (result.key === "next")
42687
- return true;
42688
- if (result.key === "message_toggle") {
42689
- config.header.messageEnabled = true;
42690
- const msg = await promptLine(rl, "Header message: ");
42691
- if (msg)
42692
- config.header.message = msg.slice(0, 80);
42693
- return stepHeader(config, rl, availableRows);
42694
- }
42695
- if (result.key === "link_toggle") {
42696
- config.header.linkEnabled = true;
42697
- const url = await promptLine(rl, "Link URL: ");
42698
- if (url) {
42699
- config.header.linkUrl = url;
42700
- const text = await promptLine(rl, "Link text: ");
42701
- if (text)
42702
- config.header.linkText = text;
42703
- }
42704
- return stepHeader(config, rl, availableRows);
42705
- }
42706
- return false;
42858
+ return result.key === "next";
42707
42859
  }
42708
42860
  async function stepTransport(config, rl, availableRows) {
42709
42861
  const items = [
@@ -42734,12 +42886,16 @@ async function stepTransport(config, rl, availableRows) {
42734
42886
  { key: "sep", label: "" },
42735
42887
  { key: "next", label: selectColors.green(" Next Step \u2192") }
42736
42888
  ];
42889
+ const rpmIdx = items.findIndex((i) => i.key === "rpm");
42890
+ const tpdIdx = items.findIndex((i) => i.key === "tpd");
42891
+ const concIdx = items.findIndex((i) => i.key === "conc");
42737
42892
  const result = await tuiSelect({
42738
42893
  items,
42739
42894
  title: "Step 4/5 \u2014 Transport & Rate Limits",
42740
42895
  rl,
42741
42896
  skipKeys: ["hdr_transport", "hdr_limits", "sep"],
42742
42897
  availableRows,
42898
+ customKeyHint: " e edit space toggle",
42743
42899
  onAction: (item, action) => {
42744
42900
  if (action === "space") {
42745
42901
  if (item.key === "cf_toggle") {
@@ -42754,6 +42910,42 @@ async function stepTransport(config, rl, availableRows) {
42754
42910
  }
42755
42911
  }
42756
42912
  return false;
42913
+ },
42914
+ onCustomKey: (item, key, helpers) => {
42915
+ if ((key === "e" || key === "E") && item.key === "rpm") {
42916
+ helpers.getInput("Max req/min:", String(config.rateLimits.maxRequestsPerMinute)).then((val) => {
42917
+ if (val !== null) {
42918
+ const n = parseInt(val, 10);
42919
+ if (!isNaN(n) && n > 0)
42920
+ config.rateLimits.maxRequestsPerMinute = n;
42921
+ }
42922
+ helpers.updateItem(rpmIdx, { label: ` Max requests/min: ${config.rateLimits.maxRequestsPerMinute}` });
42923
+ });
42924
+ return true;
42925
+ }
42926
+ if ((key === "e" || key === "E") && item.key === "tpd") {
42927
+ helpers.getInput("Max tokens/day:", String(config.rateLimits.maxTokensPerDay)).then((val) => {
42928
+ if (val !== null) {
42929
+ const n = parseInt(val, 10);
42930
+ if (!isNaN(n) && n > 0)
42931
+ config.rateLimits.maxTokensPerDay = n;
42932
+ }
42933
+ helpers.updateItem(tpdIdx, { label: ` Max tokens/day: ${config.rateLimits.maxTokensPerDay.toLocaleString()}` });
42934
+ });
42935
+ return true;
42936
+ }
42937
+ if ((key === "e" || key === "E") && item.key === "conc") {
42938
+ helpers.getInput("Max concurrent:", String(config.rateLimits.maxConcurrent)).then((val) => {
42939
+ if (val !== null) {
42940
+ const n = parseInt(val, 10);
42941
+ if (!isNaN(n) && n > 0)
42942
+ config.rateLimits.maxConcurrent = n;
42943
+ }
42944
+ helpers.updateItem(concIdx, { label: ` Max concurrent: ${config.rateLimits.maxConcurrent}` });
42945
+ });
42946
+ return true;
42947
+ }
42948
+ return false;
42757
42949
  }
42758
42950
  });
42759
42951
  if (!result.confirmed)
@@ -42765,27 +42957,6 @@ async function stepTransport(config, rl, availableRows) {
42765
42957
  }
42766
42958
  return true;
42767
42959
  }
42768
- if (result.key === "rpm") {
42769
- const val = await promptLine(rl, "Max requests per minute: ");
42770
- const n = parseInt(val, 10);
42771
- if (!isNaN(n) && n > 0)
42772
- config.rateLimits.maxRequestsPerMinute = n;
42773
- return stepTransport(config, rl, availableRows);
42774
- }
42775
- if (result.key === "tpd") {
42776
- const val = await promptLine(rl, "Max tokens per day: ");
42777
- const n = parseInt(val, 10);
42778
- if (!isNaN(n) && n > 0)
42779
- config.rateLimits.maxTokensPerDay = n;
42780
- return stepTransport(config, rl, availableRows);
42781
- }
42782
- if (result.key === "conc") {
42783
- const val = await promptLine(rl, "Max concurrent requests: ");
42784
- const n = parseInt(val, 10);
42785
- if (!isNaN(n) && n > 0)
42786
- config.rateLimits.maxConcurrent = n;
42787
- return stepTransport(config, rl, availableRows);
42788
- }
42789
42960
  return false;
42790
42961
  }
42791
42962
  async function stepReview(config, rl, availableRows) {
@@ -42880,16 +43051,6 @@ async function runSponsorWizard(ctx) {
42880
43051
  renderInfo("Toggle: /sponsor status | Pause: /sponsor pause | Remove: /sponsor remove");
42881
43052
  return config;
42882
43053
  }
42883
- function promptLine(rl, prompt) {
42884
- return new Promise((resolve35) => {
42885
- process.stdout.write(prompt);
42886
- const handler = (line) => {
42887
- rl.removeListener("line", handler);
42888
- resolve35(line.trim());
42889
- };
42890
- rl.on("line", handler);
42891
- });
42892
- }
42893
43054
  var ANIM_PRESETS;
42894
43055
  var init_sponsor_wizard = __esm({
42895
43056
  "packages/cli/dist/tui/sponsor-wizard.js"() {
@@ -47198,6 +47359,28 @@ async function handleSlashCommand(input, ctx) {
47198
47359
  renderError(`P2P start failed: ${err instanceof Error ? err.message : String(err)}`);
47199
47360
  }
47200
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
+ }
47201
47384
  }
47202
47385
  });
47203
47386
  if (result) {
@@ -48968,20 +49151,75 @@ async function handleEndpoint(arg, ctx, local = false) {
48968
49151
  async function handleSponsoredEndpoint(ctx, local) {
48969
49152
  process.stdout.write(`
48970
49153
  ${c2.dim("Scanning for sponsored inference endpoints...")}
48971
-
48972
49154
  `);
48973
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
+ authKey: ns.authKey || "",
49189
+ models: ns.models || [],
49190
+ limits: {
49191
+ rpm: ns.limits?.maxRequestsPerMinute || 60,
49192
+ tpd: ns.limits?.maxTokensPerDay || 1e5
49193
+ },
49194
+ source: "nexus",
49195
+ banner: { preset: ns.banner?.preset, message: ns.message }
49196
+ });
49197
+ }
49198
+ if (nexusSponsors.length > 0) {
49199
+ process.stdout.write(` ${c2.green("\u25CF")} Found ${nexusSponsors.length} sponsor(s) on nexus mesh
49200
+ `);
49201
+ }
49202
+ } catch {
49203
+ }
49204
+ }
49205
+ } catch (nexusErr) {
49206
+ process.stdout.write(` ${c2.dim("Nexus unavailable: " + (nexusErr instanceof Error ? nexusErr.message : String(nexusErr)).slice(0, 60))}
49207
+ `);
49208
+ }
49209
+ }
48974
49210
  const gateway = ctx.getExposeGateway?.();
48975
- if (gateway && gateway.isActive && gateway.tunnelUrl) {
48976
- sponsors.push({
48977
- name: "Local Gateway",
48978
- url: gateway.tunnelUrl,
48979
- authKey: gateway.authKey,
48980
- models: [],
48981
- // would need to probe
48982
- limits: { rpm: 60, tpd: 1e5 },
48983
- source: "local"
48984
- });
49211
+ if (gateway && gateway.isActive) {
49212
+ const gwUrl = gateway.tunnelUrl || `http://127.0.0.1:${gateway._proxyPort || 11434}`;
49213
+ if (!sponsors.some((s) => s.url === gwUrl)) {
49214
+ sponsors.push({
49215
+ name: "Local Gateway",
49216
+ url: gwUrl,
49217
+ authKey: gateway.authKey,
49218
+ models: [],
49219
+ limits: { rpm: 60, tpd: 1e5 },
49220
+ source: "local"
49221
+ });
49222
+ }
48985
49223
  }
48986
49224
  const sponsorDir2 = join58(ctx.repoRoot ?? process.cwd(), ".oa", "sponsor");
48987
49225
  const knownFile = join58(sponsorDir2, "known-sponsors.json");
@@ -48989,30 +49227,19 @@ async function handleSponsoredEndpoint(ctx, local) {
48989
49227
  if (existsSync42(knownFile)) {
48990
49228
  const saved = JSON.parse(readFileSync31(knownFile, "utf8"));
48991
49229
  for (const s of saved) {
48992
- try {
48993
- const probe = await fetch(`${s.url}/api/tags`, {
48994
- headers: s.authKey ? { Authorization: `Bearer ${s.authKey}` } : {},
48995
- signal: AbortSignal.timeout(5e3)
48996
- });
48997
- if (probe.ok) {
48998
- const data = await probe.json();
48999
- s.models = (data.models || []).map((m) => m.name);
49000
- sponsors.push(s);
49001
- }
49002
- } catch {
49230
+ if (!sponsors.some((sp) => sp.url === s.url)) {
49231
+ sponsors.push({ ...s, source: "saved" });
49003
49232
  }
49004
49233
  }
49005
49234
  }
49006
49235
  } catch {
49007
49236
  }
49237
+ process.stdout.write("\n");
49008
49238
  if (sponsors.length === 0) {
49009
- renderInfo("No sponsored endpoints found.");
49010
- renderInfo("");
49011
- renderInfo("To connect to a sponsor, use:");
49012
- renderInfo(" /endpoint <tunnel-url> --auth <key>");
49239
+ renderInfo("No sponsored endpoints found on the nexus mesh.");
49013
49240
  renderInfo("");
49014
- renderInfo("Or add a known sponsor URL:");
49015
- renderInfo(" /endpoint sponsor add <url> --auth <key>");
49241
+ renderInfo("Make sure the nexus is connected (/nexus) and sponsors are online.");
49242
+ renderInfo("Or connect directly: /endpoint <tunnel-url> --auth <key>");
49016
49243
  return;
49017
49244
  }
49018
49245
  const items = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.184.6",
3
+ "version": "0.184.8",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) \u2014 interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",