open-agents-ai 0.103.76 → 0.103.78

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 (2) hide show
  1. package/dist/index.js +81 -6
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -12224,6 +12224,21 @@ async function handleCmd(cmd) {
12224
12224
  const room = rooms.get(args.room_id);
12225
12225
  if (!room) { writeResp(id, { ok: false, output: 'Not in room: ' + args.room_id + '. Join it first.' }); return; }
12226
12226
  const msgId = await room.send(args.message, { format: 'text/plain' });
12227
+ // Relay to NATS for frontend visibility (public room messages)
12228
+ if (_natsConn && _natsCodec) {
12229
+ try {
12230
+ _natsConn.publish('nexus.rooms.chat', _natsCodec.encode(JSON.stringify({
12231
+ type: 'nexus.room.message',
12232
+ roomId: args.room_id,
12233
+ peerId: nexus.peerId,
12234
+ agentName: agentName,
12235
+ content: String(args.message).slice(0, 500),
12236
+ timestamp: Date.now(),
12237
+ })));
12238
+ } catch (natsRelayErr) {
12239
+ dlog('NATS chat relay error: ' + (natsRelayErr.message || natsRelayErr));
12240
+ }
12241
+ }
12227
12242
  writeResp(id, { ok: true, output: 'Message sent (id: ' + msgId + ')' });
12228
12243
  break;
12229
12244
  }
@@ -13478,6 +13493,24 @@ process.on('unhandledRejection', (reason) => {
13478
13493
  nexus.on('message', ({ roomId, message }) => {
13479
13494
  // Already handled by per-room listener, but log globally
13480
13495
  console.log('[msg] ' + roomId + ' from ' + (message?.sender || '?').slice(0, 16));
13496
+ // Relay received messages to NATS for frontend visibility
13497
+ if (_natsConn && _natsCodec && message && message.sender !== nexus.peerId) {
13498
+ try {
13499
+ var _msgContent = '';
13500
+ if (message.payload && message.payload.content) _msgContent = String(message.payload.content).slice(0, 500);
13501
+ else if (typeof message.content === 'string') _msgContent = message.content.slice(0, 500);
13502
+ if (_msgContent) {
13503
+ _natsConn.publish('nexus.rooms.chat', _natsCodec.encode(JSON.stringify({
13504
+ type: 'nexus.room.message',
13505
+ roomId: roomId,
13506
+ peerId: message.sender || '',
13507
+ agentName: message.senderName || (message.sender ? message.sender.slice(0, 12) : 'anon'),
13508
+ content: _msgContent,
13509
+ timestamp: message.timestamp || Date.now(),
13510
+ })));
13511
+ }
13512
+ } catch {}
13513
+ }
13481
13514
  });
13482
13515
  nexus.on('dm', ({ from, content, format, messageId }) => {
13483
13516
  // Log DMs to inbox/dm/
@@ -30667,13 +30700,43 @@ async function fetchOllamaModels(baseUrl) {
30667
30700
  }
30668
30701
  const data = await resp.json();
30669
30702
  const models = data.models ?? [];
30670
- return models.map((m) => ({
30703
+ const result = models.map((m) => ({
30671
30704
  name: m.name,
30672
30705
  size: formatBytes(m.size),
30673
30706
  sizeBytes: m.size,
30674
30707
  modified: formatRelativeTime(m.modified_at),
30675
- parameterSize: m.details?.parameter_size
30708
+ parameterSize: m.details?.parameter_size,
30709
+ contextLength: void 0
30676
30710
  })).sort((a, b) => b.sizeBytes - a.sizeBytes);
30711
+ const normalized = normalizeBaseUrl(baseUrl);
30712
+ const showResults = await Promise.allSettled(result.map((m) => fetch(`${normalized}/api/show`, {
30713
+ method: "POST",
30714
+ headers: { "Content-Type": "application/json" },
30715
+ body: JSON.stringify({ name: m.name }),
30716
+ signal: AbortSignal.timeout(5e3)
30717
+ }).then((r) => r.ok ? r.json() : null)));
30718
+ for (let i = 0; i < result.length; i++) {
30719
+ const sr = showResults[i];
30720
+ if (sr?.status !== "fulfilled" || !sr.value)
30721
+ continue;
30722
+ const show = sr.value;
30723
+ if (show.parameters) {
30724
+ const match = show.parameters.match(/num_ctx\s+(\d+)/);
30725
+ if (match) {
30726
+ result[i].contextLength = parseInt(match[1], 10);
30727
+ continue;
30728
+ }
30729
+ }
30730
+ if (show.model_info) {
30731
+ for (const [key, value] of Object.entries(show.model_info)) {
30732
+ if (key.endsWith(".context_length") && typeof value === "number") {
30733
+ result[i].contextLength = value;
30734
+ break;
30735
+ }
30736
+ }
30737
+ }
30738
+ }
30739
+ return result;
30677
30740
  }
30678
30741
  async function fetchOpenAIModels(baseUrl, apiKey) {
30679
30742
  const normalized = normalizeBaseUrl(baseUrl);
@@ -30693,10 +30756,11 @@ async function fetchOpenAIModels(baseUrl, apiKey) {
30693
30756
  const models = data.data ?? [];
30694
30757
  return models.map((m) => ({
30695
30758
  name: m.id,
30696
- size: m.context_length ? `${Math.round(m.context_length / 1024)}K ctx` : m.max_model_len ? `${Math.round(m.max_model_len / 1024)}K ctx` : "",
30759
+ size: "",
30697
30760
  sizeBytes: 0,
30698
30761
  modified: m.created ? formatRelativeTime(new Date(m.created * 1e3).toISOString()) : "",
30699
- parameterSize: m.owned_by ?? void 0
30762
+ parameterSize: m.owned_by ?? void 0,
30763
+ contextLength: m.context_length ?? m.max_model_len ?? void 0
30700
30764
  })).sort((a, b) => a.name.localeCompare(b.name));
30701
30765
  }
30702
30766
  async function fetchPeerModels(peerId, authKey) {
@@ -31036,6 +31100,13 @@ function formatBytes(bytes) {
31036
31100
  }
31037
31101
  return `${size.toFixed(1)} ${units[i] ?? "B"}`;
31038
31102
  }
31103
+ function formatContextLength(tokens) {
31104
+ if (tokens >= 1e6)
31105
+ return `${(tokens / 1e6).toFixed(1)}M ctx`;
31106
+ if (tokens >= 1024)
31107
+ return `${Math.round(tokens / 1024)}K ctx`;
31108
+ return `${tokens} ctx`;
31109
+ }
31039
31110
  function formatRelativeTime(iso) {
31040
31111
  const now = Date.now();
31041
31112
  const then = new Date(iso).getTime();
@@ -35161,15 +35232,18 @@ async function showModelPicker(ctx, local = false) {
35161
35232
  const items = [];
35162
35233
  const history = loadUsageHistory("model", ctx.repoRoot);
35163
35234
  const liveModelNames = new Set(models.map((m) => m.name));
35235
+ const modelMap = new Map(models.map((m) => [m.name, m]));
35164
35236
  if (history.length > 0) {
35165
35237
  items.push({ key: "__header_recent__", label: c2.dim("\u2500\u2500 Recent \u2500\u2500"), detail: "" });
35166
35238
  for (const h of history.slice(0, 8)) {
35167
35239
  const uses = h.localUses > 0 ? `${h.useCount} uses (${h.localUses} local)` : `${h.useCount} uses`;
35168
35240
  const available = liveModelNames.has(h.value) ? "" : c2.yellow(" [offline]");
35241
+ const meta = modelMap.get(h.value);
35242
+ const ctx2 = meta?.contextLength ? ` ${formatContextLength(meta.contextLength)}` : "";
35169
35243
  items.push({
35170
35244
  key: h.value,
35171
35245
  label: h.value,
35172
- detail: `${uses}${available}`
35246
+ detail: `${uses}${ctx2}${available}`
35173
35247
  });
35174
35248
  }
35175
35249
  items.push({ key: "__header_available__", label: c2.dim("\u2500\u2500 Available \u2500\u2500"), detail: "" });
@@ -35178,10 +35252,11 @@ async function showModelPicker(ctx, local = false) {
35178
35252
  for (const m of models) {
35179
35253
  if (history.length > 0 && historyKeys.has(m.name))
35180
35254
  continue;
35255
+ const ctx2 = m.contextLength ? formatContextLength(m.contextLength) : "";
35181
35256
  items.push({
35182
35257
  key: m.name,
35183
35258
  label: m.name,
35184
- detail: [m.parameterSize, m.size, m.modified].filter(Boolean).join(" ")
35259
+ detail: [m.parameterSize, ctx2, m.size, m.modified].filter(Boolean).join(" ")
35185
35260
  });
35186
35261
  }
35187
35262
  const result = await tuiSelect({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.103.76",
3
+ "version": "0.103.78",
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",