open-agents-ai 0.154.0 → 0.156.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 (2) hide show
  1. package/dist/index.js +188 -6
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -56581,8 +56581,15 @@ var init_status_bar = __esm({
56581
56581
  };
56582
56582
  active = false;
56583
56583
  scrollRegionTop = 1;
56584
+ // ── Agent View Multiplexing (WO-NA1) ──
56585
+ // Each agent (main + sub-agents) has its own content buffer.
56586
+ // The TUI displays ONE view at a time; tab buttons switch between them.
56587
+ /** Single agent view with independent content buffer */
56588
+ _agentViews = /* @__PURE__ */ new Map();
56589
+ _activeViewId = "main";
56584
56590
  // Virtual scrollback buffer — stores content lines for Page Up/Down scrolling.
56585
56591
  // Since we're in alternate screen buffer, there's no native scrollback.
56592
+ // NOTE: _contentLines is now a reference to the ACTIVE view's buffer.
56586
56593
  _contentLines = [];
56587
56594
  _contentScrollOffset = 0;
56588
56595
  // 0 = live (bottom), >0 = scrolled back
@@ -57168,6 +57175,18 @@ var init_status_bar = __esm({
57168
57175
  activate(scrollRegionTop) {
57169
57176
  this.scrollRegionTop = scrollRegionTop ?? 1;
57170
57177
  this.active = true;
57178
+ if (!this._agentViews.has("main")) {
57179
+ this._agentViews.set("main", {
57180
+ id: "main",
57181
+ label: "main",
57182
+ type: "main",
57183
+ contentLines: this._contentLines,
57184
+ scrollOffset: 0,
57185
+ status: "running",
57186
+ taskSummary: "",
57187
+ startedAt: Date.now()
57188
+ });
57189
+ }
57171
57190
  this._prevTermRows = process.stdout.rows ?? 24;
57172
57191
  this._prevTermCols = process.stdout.columns ?? 80;
57173
57192
  this.applyScrollRegion();
@@ -57288,8 +57307,16 @@ var init_status_bar = __esm({
57288
57307
  return;
57289
57308
  }
57290
57309
  const rows = process.stdout.rows ?? 24;
57310
+ const pos = this.rowPositions(rows);
57311
+ if (type === "press" && pos.tabBarRow > 0 && row === pos.tabBarRow) {
57312
+ const viewId = this.hitTestTabBar(col);
57313
+ if (viewId)
57314
+ this.switchToView(viewId);
57315
+ return;
57316
+ }
57291
57317
  const fh = this._currentFooterHeight;
57292
- const footerStart = rows - fh + 1;
57318
+ const tabBarH = this.hasSubAgents ? 1 : 0;
57319
+ const footerStart = rows - fh - tabBarH + 1;
57293
57320
  if (row >= footerStart)
57294
57321
  return;
57295
57322
  if (type === "press") {
@@ -57342,6 +57369,148 @@ var init_status_bar = __esm({
57342
57369
  this.renderFooterAndPositionInput();
57343
57370
  }, 1500);
57344
57371
  }
57372
+ // ── Agent View Management (WO-NA1) ────────────────────────────
57373
+ /** Register a new sub-agent view with its own content buffer */
57374
+ registerAgentView(id, label, type, taskSummary) {
57375
+ this._agentViews.set(id, {
57376
+ id,
57377
+ label,
57378
+ type,
57379
+ contentLines: [],
57380
+ scrollOffset: 0,
57381
+ status: "running",
57382
+ taskSummary: taskSummary ?? "",
57383
+ startedAt: Date.now()
57384
+ });
57385
+ if (this.active) {
57386
+ this.applyScrollRegion();
57387
+ this.renderFooterAndPositionInput();
57388
+ }
57389
+ }
57390
+ /** Remove a sub-agent view */
57391
+ unregisterAgentView(id) {
57392
+ this._agentViews.delete(id);
57393
+ if (this._activeViewId === id)
57394
+ this.switchToView("main");
57395
+ if (this.active) {
57396
+ this.applyScrollRegion();
57397
+ this.renderFooterAndPositionInput();
57398
+ }
57399
+ }
57400
+ /** Update a sub-agent's status */
57401
+ updateAgentViewStatus(id, status) {
57402
+ const view = this._agentViews.get(id);
57403
+ if (!view)
57404
+ return;
57405
+ view.status = status;
57406
+ if (status === "completed" || status === "failed")
57407
+ view.completedAt = Date.now();
57408
+ if (this.active)
57409
+ this.renderAgentTabs();
57410
+ }
57411
+ /** Switch which agent's content buffer is displayed */
57412
+ switchToView(id) {
57413
+ const view = this._agentViews.get(id);
57414
+ if (!view)
57415
+ return;
57416
+ const current = this._agentViews.get(this._activeViewId);
57417
+ if (current)
57418
+ current.scrollOffset = this._contentScrollOffset;
57419
+ this._activeViewId = id;
57420
+ this._contentLines = view.contentLines;
57421
+ this._contentScrollOffset = view.scrollOffset;
57422
+ this.repaintContent();
57423
+ this.renderAgentTabs();
57424
+ }
57425
+ /** Write content to a specific agent's buffer (called from sub-agent event handler) */
57426
+ writeToAgentView(id, text) {
57427
+ const view = this._agentViews.get(id);
57428
+ if (!view)
57429
+ return;
57430
+ const lines = text.split("\n");
57431
+ view.contentLines.push(...lines);
57432
+ if (view.contentLines.length > this._contentMaxLines) {
57433
+ view.contentLines.splice(0, view.contentLines.length - this._contentMaxLines);
57434
+ }
57435
+ if (this._activeViewId === id && this.active && this.writeDepth === 0) {
57436
+ this.repaintContent();
57437
+ }
57438
+ }
57439
+ /** Get the currently active view ID */
57440
+ get activeViewId() {
57441
+ return this._activeViewId;
57442
+ }
57443
+ /** Get all agent views (for external access) */
57444
+ getAgentViews() {
57445
+ return Array.from(this._agentViews.values()).map((v) => ({
57446
+ id: v.id,
57447
+ label: v.label,
57448
+ type: v.type,
57449
+ status: v.status,
57450
+ taskSummary: v.taskSummary
57451
+ }));
57452
+ }
57453
+ /** Whether the tab bar should be visible (more than just main) */
57454
+ get hasSubAgents() {
57455
+ return this._agentViews.size > 1;
57456
+ }
57457
+ // ── Agent Tab Bar (WO-NA2) ───────────────────────────────────
57458
+ /** Render the agent tab bar between input row and braille row */
57459
+ renderAgentTabs() {
57460
+ if (!this.active || !this.hasSubAgents)
57461
+ return;
57462
+ const rows = process.stdout.rows ?? 24;
57463
+ const pos = this.rowPositions(rows);
57464
+ if (pos.tabBarRow < 0)
57465
+ return;
57466
+ const w = process.stdout.columns ?? 80;
57467
+ let buf = `\x1B[${pos.tabBarRow};1H${PANEL_BG_SEQ}\x1B[2K`;
57468
+ let col = 2;
57469
+ for (const view of this._agentViews.values()) {
57470
+ const isActive = view.id === this._activeViewId;
57471
+ if (view.id === "main" && this._activeViewId === "main")
57472
+ continue;
57473
+ const icon = view.status === "running" ? "\u25CF" : (
57474
+ // ●
57475
+ view.status === "completed" ? "\u2713" : (
57476
+ // ✓
57477
+ view.status === "failed" ? "\u2717" : (
57478
+ // ✗
57479
+ view.status === "paused" ? "\u25CB" : "?"
57480
+ )
57481
+ )
57482
+ );
57483
+ const label = ` ${view.label} ${icon} `;
57484
+ const bg = isActive ? 238 : 236;
57485
+ const fg2 = isActive ? 252 : 245;
57486
+ buf += `\x1B[${pos.tabBarRow};${col}H`;
57487
+ buf += `\x1B]8;;oa-view:${view.id}\x07`;
57488
+ buf += `\x1B[38;5;${fg2}m\x1B[48;5;${bg}m${label}\x1B[0m${PANEL_BG_SEQ}`;
57489
+ buf += `\x1B]8;;\x07`;
57490
+ col += label.length + 1;
57491
+ if (col >= w - 5)
57492
+ break;
57493
+ }
57494
+ buf += RESET;
57495
+ this.termWrite(buf);
57496
+ }
57497
+ /** Hit-test the tab bar for click events. Returns view ID or null. */
57498
+ hitTestTabBar(col) {
57499
+ if (!this.hasSubAgents)
57500
+ return null;
57501
+ let testCol = 2;
57502
+ for (const view of this._agentViews.values()) {
57503
+ if (view.id === "main" && this._activeViewId === "main")
57504
+ continue;
57505
+ const icon = view.status === "running" ? "\u25CF" : view.status === "completed" ? "\u2713" : view.status === "failed" ? "\u2717" : "\u25CB";
57506
+ const label = ` ${view.label} ${icon} `;
57507
+ const endCol = testCol + label.length - 1;
57508
+ if (col >= testCol && col <= endCol)
57509
+ return view.id;
57510
+ testCol = endCol + 2;
57511
+ }
57512
+ return null;
57513
+ }
57345
57514
  /** Render header buttons overlay on banner row 3 */
57346
57515
  renderHeaderButtons() {
57347
57516
  if (!this.active)
@@ -58008,12 +58177,16 @@ ${CONTENT_BG_SEQ}`);
58008
58177
  rowPositions(rows) {
58009
58178
  const fh = this._currentFooterHeight;
58010
58179
  const inputLines = fh - 2;
58180
+ const tabBarH = this.hasSubAgents ? 1 : 0;
58181
+ const totalFooter = fh + tabBarH;
58011
58182
  return {
58012
- scrollEnd: Math.max(rows - fh, this.scrollRegionTop + 1),
58013
- inputStartRow: rows - fh + 1,
58183
+ scrollEnd: Math.max(rows - totalFooter, this.scrollRegionTop + 1),
58184
+ inputStartRow: rows - totalFooter + 1,
58014
58185
  // input at TOP of footer
58015
- bufferRow: rows - fh + 1 + inputLines,
58016
- // braille below input
58186
+ tabBarRow: tabBarH > 0 ? rows - 2 : -1,
58187
+ // tab bar ABOVE braille (if visible)
58188
+ bufferRow: rows - 1,
58189
+ // braille always at N-1
58017
58190
  metricsRow: rows,
58018
58191
  // metrics at BOTTOM
58019
58192
  // Legacy (unused but keeps TS happy for any remaining refs)
@@ -58122,6 +58295,9 @@ ${CONTENT_BG_SEQ}`);
58122
58295
  buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${prefix}${inputWrap.lines[i]}${RESET}`;
58123
58296
  }
58124
58297
  const cursorTermRow = pos.inputStartRow + inputWrap.cursorRow;
58298
+ if (pos.tabBarRow > 0) {
58299
+ buf += `\x1B[${pos.tabBarRow};1H${PANEL_BG_SEQ}\x1B[2K${RESET}`;
58300
+ }
58125
58301
  buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildBufferContent(w)}${RESET}`;
58126
58302
  buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET}`;
58127
58303
  buf += `\x1B[?7h\x1B[${cursorTermRow};${inputWrap.cursorCol}H\x1B[?25h`;
@@ -58153,9 +58329,15 @@ ${CONTENT_BG_SEQ}`);
58153
58329
  const rows = process.stdout.rows ?? 24;
58154
58330
  const w = getTermWidth();
58155
58331
  const pos = this.rowPositions(rows);
58156
- const buf = `\x1B7\x1B[?7l\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildBufferContent(w)}${RESET}\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET}\x1B[?7h\x1B8` + // DEC restore cursor
58332
+ let buf = "\x1B7\x1B[?7l";
58333
+ if (pos.tabBarRow > 0) {
58334
+ buf += `\x1B[${pos.tabBarRow};1H${PANEL_BG_SEQ}\x1B[2K${RESET}`;
58335
+ }
58336
+ buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildBufferContent(w)}${RESET}\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET}\x1B[?7h\x1B8` + // DEC restore cursor
58157
58337
  (this.writeDepth === 0 ? "\x1B[?25h" : "");
58158
58338
  this.termWrite(buf);
58339
+ if (pos.tabBarRow > 0)
58340
+ this.renderAgentTabs();
58159
58341
  }
58160
58342
  /**
58161
58343
  * Render the input rows during an active content write (streaming).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.154.0",
3
+ "version": "0.156.0",
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",