omnius 1.0.150 → 1.0.152

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 CHANGED
@@ -11718,17 +11718,44 @@ async function loadNexusClientClass() {
11718
11718
  }
11719
11719
 
11720
11720
  const NexusClient = await loadNexusClientClass();
11721
+ function _envTruthy(name) {
11722
+ var v = String(process.env[name] || '').toLowerCase();
11723
+ return v === '1' || v === 'true' || v === 'yes' || v === 'on';
11724
+ }
11725
+ function _envList(name) {
11726
+ return String(process.env[name] || '')
11727
+ .split(',')
11728
+ .map(function(v) { return v.trim(); })
11729
+ .filter(Boolean);
11730
+ }
11731
+ function _envRole() {
11732
+ var role = String(process.env.OMNIUS_NEXUS_ROLE || 'full').toLowerCase();
11733
+ return role === 'light' || role === 'storage' || role === 'full' ? role : 'full';
11734
+ }
11735
+ var _nexusSignalingServer = process.env.OMNIUS_NEXUS_SIGNALING_SERVER || 'https://openagents.nexus';
11736
+ var _nexusNatsServers = _envList('OMNIUS_NEXUS_NATS_SERVERS');
11737
+ var _nexusManifestUrls = _envList('OMNIUS_NEXUS_MANIFEST_URLS');
11721
11738
  var nexusOpts = {
11722
11739
  keyStorePath: keyPath,
11723
11740
  agentName,
11724
11741
  agentType,
11725
- role: 'light',
11742
+ role: _envRole(),
11743
+ cachePath: nexusDir,
11744
+ signalingServer: _nexusSignalingServer,
11745
+ manifestUrls: _nexusManifestUrls,
11726
11746
  enableMdns: true,
11727
11747
  enablePubsubDiscovery: true,
11728
11748
  enableNats: true,
11729
- natsServers: ['wss://demo.nats.io:8443'],
11749
+ natsServers: _nexusNatsServers.length > 0 ? _nexusNatsServers : ['wss://demo.nats.io:8443'],
11730
11750
  enableCircuitRelay: true,
11751
+ enableAutoNAT: true,
11752
+ enableDcutr: true,
11753
+ enableUpnpNat: true,
11754
+ enableRelayServer: true,
11755
+ filterPrivateAddresses: true,
11731
11756
  usePublicBootstrap: true,
11757
+ enableNkn: _envTruthy('OMNIUS_NEXUS_ENABLE_NKN'),
11758
+ nknIdentifier: process.env.OMNIUS_NEXUS_NKN_IDENTIFIER || ('omnius-' + agentName),
11732
11759
  trustPolicy: { denylist: [], allowlist: [] },
11733
11760
  };
11734
11761
  if (hasX402Key) {
@@ -12100,6 +12127,24 @@ function writeStatus(extra = {}) {
12100
12127
  rooms: [...rooms.keys()],
12101
12128
  capabilities: caps,
12102
12129
  blockedPeers,
12130
+ networkStack: {
12131
+ role: nexusOpts.role,
12132
+ signalingServer: nexusOpts.signalingServer,
12133
+ cachePath: nexusOpts.cachePath,
12134
+ manifestUrls: nexusOpts.manifestUrls || [],
12135
+ natsServers: nexusOpts.natsServers || [],
12136
+ discovery: {
12137
+ publicBootstrap: nexusOpts.usePublicBootstrap !== false,
12138
+ pubsub: nexusOpts.enablePubsubDiscovery !== false,
12139
+ mdns: nexusOpts.enableMdns !== false,
12140
+ circuitRelay: nexusOpts.enableCircuitRelay !== false,
12141
+ autoNAT: nexusOpts.enableAutoNAT !== false,
12142
+ dcutr: nexusOpts.enableDcutr !== false,
12143
+ upnpNAT: nexusOpts.enableUpnpNat !== false,
12144
+ relayServer: nexusOpts.enableRelayServer !== false,
12145
+ nkn: nexusOpts.enableNkn === true,
12146
+ },
12147
+ },
12103
12148
  connectedAt: connected ? new Date().toISOString() : null,
12104
12149
  ...extra,
12105
12150
  };
@@ -12110,6 +12155,242 @@ function writeResp(id, result) {
12110
12155
  try { writeFileSync(respFile, JSON.stringify({ id, ...result }, null, 2)); } catch {}
12111
12156
  }
12112
12157
 
12158
+ const capabilityRecordsFile = join(nexusDir, 'capability-records.json');
12159
+ const sponsorMeshCacheFile = join(nexusDir, 'sponsor-mesh-cache.json');
12160
+ var _capabilityPointerSeq = {};
12161
+ var _meshDiscoveryInstalled = false;
12162
+
12163
+ function _readJson(path, fallback) {
12164
+ try {
12165
+ if (!existsSync(path)) return fallback;
12166
+ var raw = readFileSync(path, 'utf8');
12167
+ return raw.trim() ? JSON.parse(raw) : fallback;
12168
+ } catch { return fallback; }
12169
+ }
12170
+ function _writeJson(path, value) {
12171
+ try { writeFileSync(path, JSON.stringify(value, null, 2)); } catch {}
12172
+ }
12173
+ async function _dhtPutBounded(dht, key, value, label) {
12174
+ var op = (async function() {
12175
+ for await (var _ of dht.put(key, value)) {}
12176
+ })().catch(function(err) {
12177
+ dlog('DHT put failed for ' + label + ': ' + (err.message || err));
12178
+ });
12179
+ var timedOut = await Promise.race([
12180
+ op.then(function() { return false; }),
12181
+ new Promise(function(resolve) { setTimeout(function() { resolve(true); }, 2500); }),
12182
+ ]);
12183
+ if (timedOut) dlog('DHT put deferred for ' + label);
12184
+ }
12185
+ function _sanitizeCapabilityKey(name) {
12186
+ return String(name || '').replace(/[^a-zA-Z0-9._:-]/g, '_');
12187
+ }
12188
+ function _capabilityDefinition(name, details) {
12189
+ return {
12190
+ name: String(name || ''),
12191
+ protocol: '/nexus/invoke/1.1.0',
12192
+ description: String((details && details.description) || 'Omnius capability'),
12193
+ pricing: String((details && details.pricing) || 'free'),
12194
+ rateLimit: String((details && details.rateLimit) || ''),
12195
+ };
12196
+ }
12197
+ function _rememberCapabilityRecord(record) {
12198
+ if (!record || !record.capability || !record.peerId) return;
12199
+ var all = _readJson(capabilityRecordsFile, {});
12200
+ all[record.capability + ':' + record.peerId] = record;
12201
+ _writeJson(capabilityRecordsFile, all);
12202
+ }
12203
+ function _rememberSponsorRecord(record) {
12204
+ if (!record) return;
12205
+ var key = record.peerId || record.libp2pPeerId || record.tunnelUrl || record.name;
12206
+ if (!key) return;
12207
+ var all = _readJson(sponsorMeshCacheFile, {});
12208
+ all[key] = Object.assign({}, record, { lastSeen: Date.now() });
12209
+ _writeJson(sponsorMeshCacheFile, all);
12210
+ }
12211
+ function _readFreshSponsorMeshCache(maxAgeMs) {
12212
+ var all = _readJson(sponsorMeshCacheFile, {});
12213
+ var fresh = [];
12214
+ var changed = false;
12215
+ var now = Date.now();
12216
+ for (var key of Object.keys(all)) {
12217
+ var rec = all[key];
12218
+ var ts = rec.lastSeen || rec.timestamp || 0;
12219
+ if (rec.status === 'active' && now - ts < maxAgeMs) {
12220
+ fresh.push(rec);
12221
+ } else {
12222
+ delete all[key];
12223
+ changed = true;
12224
+ }
12225
+ }
12226
+ if (changed) _writeJson(sponsorMeshCacheFile, all);
12227
+ return fresh;
12228
+ }
12229
+ function _extractSponsorFromMeshMessage(msg) {
12230
+ var payload = msg && msg.payload ? msg.payload : msg;
12231
+ if (!payload) return null;
12232
+ if (payload.sponsor && payload.sponsor.type === 'sponsor.announce') return payload.sponsor;
12233
+ if (payload.record && payload.record.sponsor && payload.record.sponsor.type === 'sponsor.announce') return payload.record.sponsor;
12234
+ if (payload.record && payload.record.type === 'sponsor.announce') return payload.record;
12235
+ if (payload.type === 'sponsor.announce') return payload;
12236
+ return null;
12237
+ }
12238
+ async function _publishAgentProfileSnapshot() {
12239
+ try {
12240
+ if (!connected || !nexus.network || !nexus.network.dht || !nexus.network.dht.registry) return;
12241
+ var node = nexus.network.node;
12242
+ var caps = typeof nexus.getRegisteredCapabilities === 'function' ? nexus.getRegisteredCapabilities() : [];
12243
+ var profile = {
12244
+ schema: 'nexus:agent-profile:v1',
12245
+ peerId: nexus.peerId,
12246
+ name: agentName,
12247
+ description: 'Omnius agent node',
12248
+ type: agentType,
12249
+ capabilities: caps.map(function(cap) { return _capabilityDefinition(cap, { description: 'Omnius registered capability' }); }),
12250
+ role: nexusOpts.role || 'full',
12251
+ transports: node && typeof node.getMultiaddrs === 'function' ? node.getMultiaddrs().map(function(a) { return a.toString(); }) : [],
12252
+ createdAt: Date.now(),
12253
+ updatedAt: Date.now(),
12254
+ previousVersion: null,
12255
+ };
12256
+ await Promise.race([
12257
+ nexus.network.dht.registry.publishProfile(profile),
12258
+ new Promise(function(resolve) { setTimeout(resolve, 2500); }),
12259
+ ]);
12260
+ } catch (err) {
12261
+ dlog('profile publish failed: ' + (err.message || err));
12262
+ }
12263
+ }
12264
+ async function _publishCapabilityRecord(name, details) {
12265
+ if (!connected) return;
12266
+ var capName = String(name || '');
12267
+ if (!capName) return;
12268
+ var now = Date.now();
12269
+ var peerId = nexus.peerId || '';
12270
+ var record = Object.assign({
12271
+ schema: 'omnius:nexus-capability:v1',
12272
+ capability: capName,
12273
+ peerId: peerId,
12274
+ agentName: agentName,
12275
+ agentType: agentType,
12276
+ protocol: '/nexus/invoke/1.1.0',
12277
+ transport: 'libp2p',
12278
+ status: 'active',
12279
+ timestamp: now,
12280
+ expiresAt: now + 60 * 60 * 1000,
12281
+ }, details || {});
12282
+ _rememberCapabilityRecord(record);
12283
+ if (record.sponsor) _rememberSponsorRecord(record.sponsor);
12284
+
12285
+ try {
12286
+ var proto = await import('open-agents-nexus');
12287
+ var pubsub = nexus.network && nexus.network.node && nexus.network.node.services ? nexus.network.node.services.pubsub : null;
12288
+ if (pubsub && proto.createMessage && proto.encodeMessage && proto.TOPICS) {
12289
+ var capTopic = proto.TOPICS.CAPABILITY_PREFIX + _sanitizeCapabilityKey(capName);
12290
+ var capPayload = {
12291
+ capabilities: [_capabilityDefinition(capName, details || {})],
12292
+ record: record,
12293
+ sponsor: record.sponsor || undefined,
12294
+ };
12295
+ var capMsg = proto.createMessage('capability', capTopic, peerId, capPayload);
12296
+ try { pubsub.subscribe(capTopic); } catch {}
12297
+ await pubsub.publish(capTopic, proto.encodeMessage(capMsg));
12298
+ var metaMsg = proto.createMessage('capability', proto.TOPICS.META, peerId, capPayload);
12299
+ try { pubsub.subscribe(proto.TOPICS.META); } catch {}
12300
+ await pubsub.publish(proto.TOPICS.META, proto.encodeMessage(metaMsg));
12301
+ }
12302
+ } catch (gsErr) {
12303
+ dlog('capability gossip publish failed for ' + capName + ': ' + (gsErr.message || gsErr));
12304
+ }
12305
+
12306
+ try {
12307
+ var dht = nexus.network && nexus.network.node && nexus.network.node.services ? nexus.network.node.services.dht : null;
12308
+ if (!dht) return;
12309
+ var payload = JSON.stringify(record);
12310
+ var valueText = payload;
12311
+ try {
12312
+ var signing = await import('open-agents-nexus/protocol/signing.js');
12313
+ var privateKey = nexus.identity && nexus.identity.privateKey;
12314
+ if (privateKey && signing.signEnvelope) {
12315
+ var seqKey = capName + ':' + peerId;
12316
+ _capabilityPointerSeq[seqKey] = (_capabilityPointerSeq[seqKey] || 0) + 1;
12317
+ var env = await signing.signEnvelope({
12318
+ schema: 'nexus:pointer-envelope:v1',
12319
+ kind: 'capability-pointer',
12320
+ issuer: peerId,
12321
+ cid: payload,
12322
+ seq: _capabilityPointerSeq[seqKey],
12323
+ issuedAt: now,
12324
+ expiresAt: now + 60 * 60 * 1000,
12325
+ }, privateKey);
12326
+ valueText = JSON.stringify(env);
12327
+ }
12328
+ } catch {}
12329
+ var keys = [
12330
+ '/nexus/capability/' + _sanitizeCapabilityKey(capName),
12331
+ '/nexus/capability/' + _sanitizeCapabilityKey(capName) + '/' + peerId,
12332
+ ];
12333
+ for (var ki = 0; ki < keys.length; ki++) {
12334
+ try {
12335
+ await _dhtPutBounded(dht, new TextEncoder().encode(keys[ki]), new TextEncoder().encode(valueText), keys[ki]);
12336
+ } catch (putErr) {
12337
+ dlog('DHT put failed for ' + keys[ki] + ': ' + (putErr.message || putErr));
12338
+ }
12339
+ }
12340
+ } catch (dhtErr) {
12341
+ dlog('capability DHT publish failed for ' + capName + ': ' + (dhtErr.message || dhtErr));
12342
+ }
12343
+ _publishAgentProfileSnapshot().catch(function(err) {
12344
+ dlog('profile snapshot publish failed: ' + (err.message || err));
12345
+ });
12346
+ }
12347
+ async function _readDhtCapabilityRecord(name) {
12348
+ var out = [];
12349
+ try {
12350
+ var dht = nexus.network && nexus.network.node && nexus.network.node.services ? nexus.network.node.services.dht : null;
12351
+ if (!dht) return out;
12352
+ var key = new TextEncoder().encode('/nexus/capability/' + _sanitizeCapabilityKey(name));
12353
+ for await (var event of dht.get(key)) {
12354
+ if (event.name !== 'VALUE') continue;
12355
+ var parsed = JSON.parse(new TextDecoder().decode(event.value));
12356
+ if (parsed && parsed.schema === 'nexus:pointer-envelope:v1' && parsed.cid) {
12357
+ out.push(JSON.parse(parsed.cid));
12358
+ } else {
12359
+ out.push(parsed);
12360
+ }
12361
+ }
12362
+ } catch (err) {
12363
+ dlog('DHT capability read failed for ' + name + ': ' + (err.message || err));
12364
+ }
12365
+ return out;
12366
+ }
12367
+ function _installMeshDiscoveryHandlers() {
12368
+ if (_meshDiscoveryInstalled) return;
12369
+ try {
12370
+ var pubsub = nexus.network && nexus.network.node && nexus.network.node.services ? nexus.network.node.services.pubsub : null;
12371
+ if (!pubsub) return;
12372
+ _meshDiscoveryInstalled = true;
12373
+ var topics = ['/nexus/meta', '/nexus/capability/sponsor_inference'];
12374
+ for (var ti = 0; ti < topics.length; ti++) {
12375
+ try { pubsub.subscribe(topics[ti]); } catch {}
12376
+ }
12377
+ pubsub.addEventListener('message', function(evt) {
12378
+ try {
12379
+ var detail = evt && evt.detail ? evt.detail : null;
12380
+ if (!detail || topics.indexOf(detail.topic) === -1) return;
12381
+ var msg = JSON.parse(new TextDecoder().decode(detail.data));
12382
+ var sponsor = _extractSponsorFromMeshMessage(msg);
12383
+ if (sponsor) _rememberSponsorRecord(sponsor);
12384
+ var rec = msg && msg.payload && msg.payload.record ? msg.payload.record : null;
12385
+ if (rec && rec.capability) _rememberCapabilityRecord(rec);
12386
+ } catch {}
12387
+ });
12388
+ dlog('mesh discovery handlers installed for ' + topics.join(','));
12389
+ } catch (err) {
12390
+ dlog('mesh discovery handler install failed: ' + (err.message || err));
12391
+ }
12392
+ }
12393
+
12113
12394
  // Collect CPU/GPU/memory metrics for piggybacking on inference responses.
12114
12395
  // Avoids separate invoke_capability round-trip that clogs the IPC.
12115
12396
  var _sysMetricsCache = null;
@@ -12427,7 +12708,16 @@ async function handleCmd(cmd) {
12427
12708
  } catch (gsErr) {
12428
12709
  dlog('sponsor_announce: GossipSub meta failed: ' + (gsErr.message || gsErr));
12429
12710
  }
12430
- writeResp(id, { ok: true, output: 'Sponsor announced: ' + sponsorData.name + ' (' + sponsorData.models.length + ' models) [NATS+KV+Room+GossipSub]' });
12711
+ _rememberSponsorRecord(sponsorData);
12712
+ await _publishCapabilityRecord('sponsor_inference', {
12713
+ description: 'Sponsored Omnius inference via ' + sponsorData.name,
12714
+ pricing: 'sponsored',
12715
+ rateLimit: String(sponsorData.limits.maxRequestsPerMinute) + '/min',
12716
+ sponsor: sponsorData,
12717
+ models: sponsorData.models,
12718
+ limits: sponsorData.limits,
12719
+ });
12720
+ writeResp(id, { ok: true, output: 'Sponsor announced: ' + sponsorData.name + ' (' + sponsorData.models.length + ' models) [DHT+GossipSub+NATS+KV+Room]' });
12431
12721
  break;
12432
12722
  }
12433
12723
  // NX-05 + NX-06: Register sponsor_inference capability for P2P inference relay.
@@ -12488,6 +12778,12 @@ async function handleCmd(cmd) {
12488
12778
  stream.write({ type: 'invoke.error', error: String(rsiErr.message || rsiErr) });
12489
12779
  }
12490
12780
  });
12781
+ await _publishCapabilityRecord('sponsor_inference', {
12782
+ description: 'Sponsored Omnius inference relay',
12783
+ pricing: 'sponsored',
12784
+ rateLimit: 'sponsor-policy',
12785
+ models: _rsiAllowedModels || [],
12786
+ });
12491
12787
  writeResp(id, { ok: true, output: 'Registered sponsor_inference capability (P2P relay active)' });
12492
12788
  break;
12493
12789
  }
@@ -12517,7 +12813,31 @@ async function handleCmd(cmd) {
12517
12813
  dlog('sponsor_discover: KV fetch failed: ' + (kvErr.message || kvErr));
12518
12814
  }
12519
12815
 
12520
- // ── Source 2: NATS live announcements (if connected) ──
12816
+ // ── Source 2: Nexus mesh cache + DHT capability pointer ──
12817
+ try {
12818
+ var meshSponsors = _readFreshSponsorMeshCache(10 * 60 * 1000);
12819
+ for (var mi = 0; mi < meshSponsors.length; mi++) foundSponsors.push(meshSponsors[mi]);
12820
+ dlog('sponsor_discover: mesh cache returned ' + meshSponsors.length + ' sponsor(s)');
12821
+ } catch (meshErr) {
12822
+ dlog('sponsor_discover: mesh cache failed: ' + (meshErr.message || meshErr));
12823
+ }
12824
+ try {
12825
+ var dhtCaps = await _readDhtCapabilityRecord('sponsor_inference');
12826
+ var dhtCount = 0;
12827
+ for (var di = 0; di < dhtCaps.length; di++) {
12828
+ var capRec = dhtCaps[di];
12829
+ var spRec = capRec && capRec.sponsor ? capRec.sponsor : null;
12830
+ if (spRec && spRec.status === 'active') {
12831
+ foundSponsors.push(spRec);
12832
+ dhtCount++;
12833
+ }
12834
+ }
12835
+ dlog('sponsor_discover: DHT sponsor_inference returned ' + dhtCount + ' sponsor(s)');
12836
+ } catch (dhtDiscErr) {
12837
+ dlog('sponsor_discover: DHT sponsor read failed: ' + (dhtDiscErr.message || dhtDiscErr));
12838
+ }
12839
+
12840
+ // ── Source 3: NATS live announcements (if connected) ──
12521
12841
  if (_natsConn && _natsCodec) {
12522
12842
 
12523
12843
  // Also check sponsors room inbox for cached messages
@@ -13067,7 +13387,12 @@ async function handleCmd(cmd) {
13067
13387
  stream.close();
13068
13388
  });
13069
13389
  writeStatus();
13070
- writeResp(id, { ok: true, output: 'Capability registered: ' + name + '. Now advertised via NATS.' });
13390
+ await _publishCapabilityRecord(name, {
13391
+ description: String(args.description || 'Omnius registered capability'),
13392
+ pricing: String(args.pricing || 'free'),
13393
+ rateLimit: String(args.rate_limit || ''),
13394
+ });
13395
+ writeResp(id, { ok: true, output: 'Capability registered: ' + name + '. Advertised via DHT/GossipSub/NATS.' });
13071
13396
  break;
13072
13397
  }
13073
13398
  case 'unregister_capability': {
@@ -14067,6 +14392,23 @@ async function handleCmd(cmd) {
14067
14392
  }
14068
14393
  }
14069
14394
 
14395
+ for (var pci = 0; pci < pricingMenu.length; pci++) {
14396
+ var capPricing = pricingMenu[pci];
14397
+ await _publishCapabilityRecord('inference:' + capPricing.model.replace(/[^a-zA-Z0-9._-]/g, '_'), {
14398
+ description: 'Omnius inference model ' + capPricing.model,
14399
+ pricing: capPricing.pricing && capPricing.pricing.input_per_1m_tokens === 0
14400
+ ? 'free'
14401
+ : JSON.stringify(capPricing.pricing || {}),
14402
+ rateLimit: _sponsorLimits
14403
+ ? String(_sponsorLimits.maxRequestsPerMinute) + '/min'
14404
+ : 'provider-policy',
14405
+ model: capPricing.model,
14406
+ modelDetails: capPricing,
14407
+ passthrough: isPassthrough,
14408
+ limits: _sponsorLimits,
14409
+ });
14410
+ }
14411
+
14070
14412
  // Register system_metrics capability — returns CPU/GPU/memory utilization
14071
14413
  if (typeof nexus.registerCapability === 'function') {
14072
14414
  nexus.registerCapability('system_metrics', async (request, stream) => {
@@ -14174,6 +14516,11 @@ async function handleCmd(cmd) {
14174
14516
  try { stream.close(); } catch {}
14175
14517
  });
14176
14518
  dlog('system_metrics capability registered');
14519
+ await _publishCapabilityRecord('system_metrics', {
14520
+ description: 'Provider CPU/GPU/RAM/disk and sponsor gateway metrics',
14521
+ pricing: 'free',
14522
+ rateLimit: 'provider-policy',
14523
+ });
14177
14524
  }
14178
14525
 
14179
14526
  // Register __list_capabilities — allows remote peers to discover available models
@@ -14198,6 +14545,19 @@ async function handleCmd(cmd) {
14198
14545
  stream.close();
14199
14546
  });
14200
14547
  dlog('__list_capabilities capability registered');
14548
+ await _publishCapabilityRecord('__list_capabilities', {
14549
+ description: 'Live provider capability and model list',
14550
+ pricing: 'free',
14551
+ rateLimit: 'provider-policy',
14552
+ models: pricingMenu.map(function(pm) {
14553
+ return {
14554
+ name: pm.model,
14555
+ parameterSize: pm.parameterSize || '',
14556
+ family: pm.family || '',
14557
+ quantization: pm.quantization || '',
14558
+ };
14559
+ }),
14560
+ });
14201
14561
  }
14202
14562
 
14203
14563
  // Write pricing menu to file
@@ -14469,6 +14829,8 @@ process.on('unhandledRejection', (reason) => {
14469
14829
  await node.start();
14470
14830
  }
14471
14831
  connected = true;
14832
+ _installMeshDiscoveryHandlers();
14833
+ await _publishAgentProfileSnapshot();
14472
14834
 
14473
14835
  // Register this nexus dir in the global registry so the API daemon
14474
14836
  // (and any other consumer) can discover us regardless of cwd.
@@ -14620,6 +14982,11 @@ process.on('unhandledRejection', (reason) => {
14620
14982
  try { stream.close(); } catch {}
14621
14983
  });
14622
14984
  dlog('http_tunnel capability registered (api hint: ' + apiPortHintPath + ')');
14985
+ await _publishCapabilityRecord('http_tunnel', {
14986
+ description: 'Omnius API HTTP tunnel over direct Nexus invoke streams',
14987
+ pricing: 'share-key',
14988
+ rateLimit: 'api-policy',
14989
+ });
14623
14990
  }
14624
14991
 
14625
14992
  // Monkey-patch node.dialProtocol AND node.dial to convert string multiaddrs
@@ -17495,6 +17862,17 @@ ${earlyError ? "\n" + earlyError : ""}${earlyOutput ? "\n" + earlyOutput : ""}`;
17495
17862
  ` Capabilities: ${(status.capabilities || []).length ? (status.capabilities || []).join(", ") : "none"}`,
17496
17863
  ` Blocked peers: ${(status.blockedPeers || []).length || 0}`
17497
17864
  ];
17865
+ if (status.networkStack) {
17866
+ const ns = status.networkStack;
17867
+ const disc = ns.discovery || {};
17868
+ const enabled2 = Object.entries(disc).filter(([, value2]) => value2 === true).map(([key]) => key).join(", ");
17869
+ lines.push(` Network role: ${ns.role || "full"}`);
17870
+ lines.push(` Discovery: ${enabled2 || "none"}`);
17871
+ lines.push(` Signaling: ${ns.signalingServer || "n/a"}`);
17872
+ if (Array.isArray(ns.manifestUrls) && ns.manifestUrls.length > 0) {
17873
+ lines.push(` Bootstrap manifests: ${ns.manifestUrls.length}`);
17874
+ }
17875
+ }
17498
17876
  const walletPath = join23(this.nexusDir, "wallet.enc");
17499
17877
  if (existsSync21(walletPath)) {
17500
17878
  try {
@@ -581489,23 +581867,57 @@ ${CONTENT_BG_SEQ}`);
581489
581867
  const w = termWidth ?? getTermWidth();
581490
581868
  return Math.max(1, w - this.promptWidth - 2);
581491
581869
  }
581870
+ wrapPlainInputText(text, availWidth) {
581871
+ const width = Math.max(1, availWidth);
581872
+ const rawLines = [];
581873
+ const charPositions = [];
581874
+ const pushWrappedSegment = (segment, segmentStart2) => {
581875
+ if (segment.length === 0) {
581876
+ charPositions.push(segmentStart2);
581877
+ rawLines.push("");
581878
+ return;
581879
+ }
581880
+ let offset = 0;
581881
+ while (offset < segment.length) {
581882
+ const remaining = segment.slice(offset);
581883
+ if (remaining.length <= width) {
581884
+ charPositions.push(segmentStart2 + offset);
581885
+ rawLines.push(remaining);
581886
+ break;
581887
+ }
581888
+ let breakAt = width;
581889
+ const lastSpace = remaining.lastIndexOf(" ", width);
581890
+ if (lastSpace > 0 && lastSpace >= width * 0.3) {
581891
+ breakAt = lastSpace + 1;
581892
+ }
581893
+ charPositions.push(segmentStart2 + offset);
581894
+ rawLines.push(remaining.slice(0, breakAt));
581895
+ offset += breakAt;
581896
+ }
581897
+ };
581898
+ if (text.length === 0) {
581899
+ pushWrappedSegment("", 0);
581900
+ return { rawLines, charPositions };
581901
+ }
581902
+ let segmentStart = 0;
581903
+ while (segmentStart <= text.length) {
581904
+ const newlineAt = text.indexOf("\n", segmentStart);
581905
+ const segmentEnd = newlineAt === -1 ? text.length : newlineAt;
581906
+ pushWrappedSegment(text.slice(segmentStart, segmentEnd), segmentStart);
581907
+ if (newlineAt === -1) break;
581908
+ segmentStart = newlineAt + 1;
581909
+ if (segmentStart === text.length) {
581910
+ pushWrappedSegment("", segmentStart);
581911
+ break;
581912
+ }
581913
+ }
581914
+ return { rawLines, charPositions };
581915
+ }
581492
581916
  computeInputLineCount(termWidth) {
581493
581917
  if (!this.inputStateProvider) return 1;
581494
581918
  const availWidth = this.inputTextWidth(termWidth);
581495
581919
  const { line } = this.inputStateProvider();
581496
- if (line.length <= availWidth) return 1;
581497
- let count = 0;
581498
- let remaining = line;
581499
- while (remaining.length > 0) {
581500
- count++;
581501
- if (remaining.length <= availWidth) break;
581502
- let breakAt = availWidth;
581503
- const lastSpace = remaining.lastIndexOf(" ", availWidth);
581504
- if (lastSpace > 0 && lastSpace >= availWidth * 0.3)
581505
- breakAt = lastSpace + 1;
581506
- remaining = remaining.slice(breakAt);
581507
- }
581508
- return Math.max(1, count);
581920
+ return Math.max(1, this.wrapPlainInputText(line, availWidth).rawLines.length);
581509
581921
  }
581510
581922
  /** Update _currentFooterHeight based on current input + suggestions. Returns true if height changed. */
581511
581923
  updateFooterHeight(termWidth) {
@@ -581565,8 +581977,9 @@ ${CONTENT_BG_SEQ}`);
581565
581977
  const inputState = this.inputStateProvider?.();
581566
581978
  const fullLine = inputState?.line ?? "";
581567
581979
  const cursorPos = inputState?.cursor ?? 0;
581980
+ const hasExplicitLineBreak = fullLine.includes("\n");
581568
581981
  const ghost = this.getGhostText(fullLine, cursorPos);
581569
- if (fullLine.length <= availWidth) {
581982
+ if (!hasExplicitLineBreak && fullLine.length <= availWidth) {
581570
581983
  let displayLine;
581571
581984
  if (ghost) {
581572
581985
  displayLine = fullLine + `\x1B[7m\x1B[38;5;${TEXT_DIM}m${ghost[0]}\x1B[0m${PANEL_BG_SEQ}\x1B[38;5;${TEXT_DIM}m${ghost.slice(1)}\x1B[0m${PANEL_BG_SEQ}`;
@@ -581581,28 +581994,7 @@ ${CONTENT_BG_SEQ}`);
581581
581994
  cursorCol: Math.min(Math.max(1, termWidth - 1), this.promptWidth + cursorPos + 2)
581582
581995
  };
581583
581996
  }
581584
- const rawLines = [];
581585
- let remaining = fullLine;
581586
- const charPositions = [];
581587
- while (remaining.length > 0) {
581588
- if (remaining.length <= availWidth) {
581589
- charPositions.push(fullLine.length - remaining.length);
581590
- rawLines.push(remaining);
581591
- break;
581592
- }
581593
- let breakAt = availWidth;
581594
- const lastSpace = remaining.lastIndexOf(" ", availWidth);
581595
- if (lastSpace > 0 && lastSpace >= availWidth * 0.3) {
581596
- breakAt = lastSpace + 1;
581597
- }
581598
- charPositions.push(fullLine.length - remaining.length);
581599
- rawLines.push(remaining.slice(0, breakAt));
581600
- remaining = remaining.slice(breakAt);
581601
- }
581602
- if (rawLines.length === 0) {
581603
- rawLines.push("");
581604
- charPositions.push(0);
581605
- }
581997
+ const { rawLines, charPositions } = this.wrapPlainInputText(fullLine, availWidth);
581606
581998
  let cursorLineIdx = rawLines.length - 1;
581607
581999
  let cursorColInLine = cursorPos;
581608
582000
  for (let i2 = 0; i2 < charPositions.length; i2++) {
@@ -633486,27 +633878,48 @@ var init_direct_input = __esm({
633486
633878
  * and rawLines (text of each line). Matches wrapInput logic in status-bar.ts.
633487
633879
  */
633488
633880
  _computeWrappedLines(availWidth) {
633881
+ const width = Math.max(1, availWidth);
633489
633882
  const rawLines = [];
633490
633883
  const charPositions = [];
633491
- let remaining = this.line;
633492
- while (remaining.length > 0) {
633493
- if (remaining.length <= availWidth) {
633494
- charPositions.push(this.line.length - remaining.length);
633495
- rawLines.push(remaining);
633496
- break;
633884
+ const pushWrappedSegment = (segment, segmentStart2) => {
633885
+ if (segment.length === 0) {
633886
+ charPositions.push(segmentStart2);
633887
+ rawLines.push("");
633888
+ return;
633497
633889
  }
633498
- let breakAt = availWidth;
633499
- const lastSpace = remaining.lastIndexOf(" ", availWidth);
633500
- if (lastSpace > 0 && lastSpace >= availWidth * 0.3) {
633501
- breakAt = lastSpace + 1;
633890
+ let offset = 0;
633891
+ while (offset < segment.length) {
633892
+ const remaining = segment.slice(offset);
633893
+ if (remaining.length <= width) {
633894
+ charPositions.push(segmentStart2 + offset);
633895
+ rawLines.push(remaining);
633896
+ break;
633897
+ }
633898
+ let breakAt = width;
633899
+ const lastSpace = remaining.lastIndexOf(" ", width);
633900
+ if (lastSpace > 0 && lastSpace >= width * 0.3) {
633901
+ breakAt = lastSpace + 1;
633902
+ }
633903
+ charPositions.push(segmentStart2 + offset);
633904
+ rawLines.push(remaining.slice(0, breakAt));
633905
+ offset += breakAt;
633906
+ }
633907
+ };
633908
+ if (this.line.length === 0) {
633909
+ pushWrappedSegment("", 0);
633910
+ return { charPositions, rawLines };
633911
+ }
633912
+ let segmentStart = 0;
633913
+ while (segmentStart <= this.line.length) {
633914
+ const newlineAt = this.line.indexOf("\n", segmentStart);
633915
+ const segmentEnd = newlineAt === -1 ? this.line.length : newlineAt;
633916
+ pushWrappedSegment(this.line.slice(segmentStart, segmentEnd), segmentStart);
633917
+ if (newlineAt === -1) break;
633918
+ segmentStart = newlineAt + 1;
633919
+ if (segmentStart === this.line.length) {
633920
+ pushWrappedSegment("", segmentStart);
633921
+ break;
633502
633922
  }
633503
- charPositions.push(this.line.length - remaining.length);
633504
- rawLines.push(remaining.slice(0, breakAt));
633505
- remaining = remaining.slice(breakAt);
633506
- }
633507
- if (rawLines.length === 0) {
633508
- rawLines.push("");
633509
- charPositions.push(0);
633510
633923
  }
633511
633924
  return { charPositions, rawLines };
633512
633925
  }
@@ -633692,6 +634105,10 @@ var init_direct_input = __esm({
633692
634105
  this.cursor = this.line.length;
633693
634106
  return;
633694
634107
  case "~":
634108
+ if (this._isShiftEnterCSI(params)) {
634109
+ this._insertText("\n");
634110
+ return;
634111
+ }
633695
634112
  if (params === "3") {
633696
634113
  if (this.cursor < this.line.length) {
633697
634114
  this.line = this.line.slice(0, this.cursor) + this.line.slice(this.cursor + 1);
@@ -633713,6 +634130,10 @@ var init_direct_input = __esm({
633713
634130
  const modifiers = parseInt(parts[1] ?? "1");
633714
634131
  const hasCtrl = modifiers - 1 & 4;
633715
634132
  const hasShift = modifiers - 1 & 1;
634133
+ if (hasShift && (codepoint === 10 || codepoint === 13)) {
634134
+ this._insertText("\n");
634135
+ return;
634136
+ }
633716
634137
  if (hasCtrl && hasShift) {
633717
634138
  if (codepoint === 67) {
633718
634139
  this.emit("ctrl-shift-c");
@@ -633731,6 +634152,22 @@ var init_direct_input = __esm({
633731
634152
  }
633732
634153
  }
633733
634154
  }
634155
+ _isShiftEnterCSI(params) {
634156
+ const parts = params.split(";").map((part) => parseInt(part, 10));
634157
+ if (parts.length === 2) {
634158
+ const [codepoint, modifiers] = parts;
634159
+ return (codepoint === 10 || codepoint === 13) && modifiers === 2;
634160
+ }
634161
+ if (parts.length === 3) {
634162
+ const [prefix, modifiers, codepoint] = parts;
634163
+ return prefix === 27 && modifiers === 2 && (codepoint === 10 || codepoint === 13);
634164
+ }
634165
+ return false;
634166
+ }
634167
+ _insertText(text) {
634168
+ this.line = this.line.slice(0, this.cursor) + text + this.line.slice(this.cursor);
634169
+ this.cursor += text.length;
634170
+ }
633734
634171
  /** Handle SS3 sequence: \x1BO {final} (some terminals use this for arrows/Home/End) */
633735
634172
  _handleSS3(final2) {
633736
634173
  switch (final2) {
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.150",
3
+ "version": "1.0.152",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.150",
9
+ "version": "1.0.152",
10
10
  "bundleDependencies": [
11
11
  "image-to-ascii"
12
12
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.150",
3
+ "version": "1.0.152",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",