open-agents-ai 0.184.8 → 0.184.10

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 +543 -17
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -36017,6 +36017,21 @@ var init_expose = __esm({
36017
36017
  }
36018
36018
  url.searchParams.delete("key");
36019
36019
  const forwardPath = url.pathname + url.search;
36020
+ if (this._sponsorLimits) {
36021
+ const p = url.pathname.toLowerCase();
36022
+ const m = (req.method || "GET").toUpperCase();
36023
+ const allowed = p === "/api/chat" && m === "POST" || p === "/api/generate" && m === "POST" || p === "/api/tags" && m === "GET" || p === "/v1/chat/completions" && m === "POST" || p === "/v1/models" && m === "GET" || p === "/v1/system/metrics" && m === "GET";
36024
+ if (!allowed) {
36025
+ this._stats.activeConnections--;
36026
+ user.activeRequests--;
36027
+ this._stats.errors++;
36028
+ res.writeHead(403, { "Content-Type": "application/json" });
36029
+ res.end(JSON.stringify({
36030
+ error: "Forbidden \u2014 this endpoint is not available in sponsor mode."
36031
+ }));
36032
+ return;
36033
+ }
36034
+ }
36020
36035
  if (!this._fullAccess) {
36021
36036
  const p = url.pathname.toLowerCase();
36022
36037
  if (p === "/api/pull" || p === "/api/delete" || p === "/api/create" || p === "/api/copy" || p === "/api/push" || p === "/api/blobs") {
@@ -42566,6 +42581,388 @@ var init_neovim_mode = __esm({
42566
42581
  }
42567
42582
  });
42568
42583
 
42584
+ // packages/cli/dist/tui/sponsor-anims.js
42585
+ var sponsor_anims_exports = {};
42586
+ __export(sponsor_anims_exports, {
42587
+ ANIM_PRESETS: () => ANIM_PRESETS,
42588
+ generateCustomAnim: () => generateCustomAnim,
42589
+ generateCustomAnimWithFallback: () => generateCustomAnimWithFallback,
42590
+ getPreset: () => getPreset2,
42591
+ presetToBannerDesign: () => presetToBannerDesign,
42592
+ renderPreviewToString: () => renderPreviewToString
42593
+ });
42594
+ function emptyGrid(width, fg2 = -1, bg = -1) {
42595
+ return Array.from({ length: ROWS }, () => Array.from({ length: width }, () => ({ char: " ", fg: fg2, bg, bold: false })));
42596
+ }
42597
+ function setChar(grid, row, col, char, fg2, bold = false, bg = -1) {
42598
+ if (row >= 0 && row < ROWS && col >= 0 && col < grid[0].length) {
42599
+ grid[row][col] = { char, fg: fg2, bg, bold };
42600
+ }
42601
+ }
42602
+ function generateWave(width, frameCount = 12) {
42603
+ const chars = "\u2591\u2592\u2593\u2588\u2593\u2592\u2591";
42604
+ const colors = [27, 33, 39, 45, 51, 45, 39, 33];
42605
+ const frames = [];
42606
+ for (let f = 0; f < frameCount; f++) {
42607
+ const grid = emptyGrid(width);
42608
+ for (let c3 = 0; c3 < width; c3++) {
42609
+ const phase = (c3 + f * 2) % (chars.length * 2);
42610
+ const charIdx = phase < chars.length ? phase : chars.length * 2 - phase - 1;
42611
+ const colorIdx = (c3 + f) % colors.length;
42612
+ for (let r = 0; r < ROWS; r++) {
42613
+ const offset = r * 3;
42614
+ const ci = (charIdx + offset) % chars.length;
42615
+ setChar(grid, r, c3, chars[ci], colors[(colorIdx + r) % colors.length], false);
42616
+ }
42617
+ }
42618
+ frames.push({ grid, durationMs: 120 });
42619
+ }
42620
+ return frames;
42621
+ }
42622
+ function generatePulse(width, frameCount = 10) {
42623
+ const frames = [];
42624
+ const dot = "\u25CF";
42625
+ const colors = [236, 238, 240, 243, 246, 249, 252, 249, 246, 243];
42626
+ for (let f = 0; f < frameCount; f++) {
42627
+ const grid = emptyGrid(width);
42628
+ const centerX = Math.floor(width / 2);
42629
+ for (let r = 0; r < ROWS; r++) {
42630
+ for (let c3 = 0; c3 < width; c3++) {
42631
+ const dist = Math.abs(c3 - centerX) + Math.abs(r - 1);
42632
+ const phase = (dist + f * 2) % colors.length;
42633
+ if (dist % 3 === 0) {
42634
+ setChar(grid, r, c3, dot, colors[phase]);
42635
+ }
42636
+ }
42637
+ }
42638
+ frames.push({ grid, durationMs: 150 });
42639
+ }
42640
+ return frames;
42641
+ }
42642
+ function generateMatrix(width, frameCount = 15) {
42643
+ const frames = [];
42644
+ const chars = "\uFF8A\uFF90\uFF8B\uFF70\uFF73\uFF7C\uFF85\uFF93\uFF86\uFF7B\uFF9C\uFF82\uFF75\uFF98\uFF71\uFF8E\uFF83\uFF8F\uFF79\uFF92\uFF74\uFF76\uFF77\uFF91\uFF95\uFF97\uFF7E\uFF88\uFF7D\uFF80\uFF87\uFF8D0123456789";
42645
+ const greens = [22, 28, 34, 40, 46, 82, 118, 154, 190];
42646
+ const drops = Array.from({ length: width }, () => Math.floor(Math.random() * ROWS * 2));
42647
+ for (let f = 0; f < frameCount; f++) {
42648
+ const grid = emptyGrid(width);
42649
+ for (let c3 = 0; c3 < width; c3++) {
42650
+ const dropY = drops[c3] % (ROWS + 3);
42651
+ for (let r = 0; r < ROWS; r++) {
42652
+ const dist = dropY - r;
42653
+ if (dist >= 0 && dist < greens.length) {
42654
+ const ch = chars[Math.floor(Math.random() * chars.length)];
42655
+ const brightness = greens[Math.min(dist, greens.length - 1)];
42656
+ setChar(grid, r, c3, ch, brightness, dist === 0);
42657
+ }
42658
+ }
42659
+ drops[c3] = (drops[c3] + 1) % (ROWS + 6);
42660
+ }
42661
+ frames.push({ grid, durationMs: 100 });
42662
+ }
42663
+ return frames;
42664
+ }
42665
+ function generateSparkle(width, frameCount = 12) {
42666
+ const frames = [];
42667
+ const sparkles = ["\u2726", "\u2727", "\xB7", "\u02D9", "\u207A", "\u2735", "\u2605"];
42668
+ const colors = [226, 220, 214, 208, 202, 196, 231];
42669
+ for (let f = 0; f < frameCount; f++) {
42670
+ const grid = emptyGrid(width);
42671
+ const seed = f * 7919;
42672
+ for (let i = 0; i < Math.floor(width * ROWS * 0.15); i++) {
42673
+ const hash = (seed + i * 1301) * 16807 % 2147483647;
42674
+ const c3 = hash % width;
42675
+ const r = Math.floor(hash / width) % ROWS;
42676
+ const si = hash / (width * ROWS) % sparkles.length;
42677
+ const ci = hash / (width * ROWS * sparkles.length) % colors.length;
42678
+ setChar(grid, r, c3, sparkles[Math.floor(si)], colors[Math.floor(ci)]);
42679
+ }
42680
+ frames.push({ grid, durationMs: 200 });
42681
+ }
42682
+ return frames;
42683
+ }
42684
+ function generateRadar(width, frameCount = 16) {
42685
+ const frames = [];
42686
+ const centerX = Math.floor(width / 2);
42687
+ const centerY = 1;
42688
+ for (let f = 0; f < frameCount; f++) {
42689
+ const grid = emptyGrid(width);
42690
+ const angle = f / frameCount * Math.PI * 2;
42691
+ for (let c3 = 0; c3 < width; c3++) {
42692
+ for (let r = 0; r < ROWS; r++) {
42693
+ const dx = (c3 - centerX) / (width / 6);
42694
+ const dy = (r - centerY) * 2;
42695
+ const cellAngle = Math.atan2(dy, dx);
42696
+ const dist = Math.sqrt(dx * dx + dy * dy);
42697
+ let angleDiff = cellAngle - angle;
42698
+ while (angleDiff < -Math.PI)
42699
+ angleDiff += Math.PI * 2;
42700
+ while (angleDiff > Math.PI)
42701
+ angleDiff -= Math.PI * 2;
42702
+ if (Math.abs(angleDiff) < 0.4 && dist > 0.2 && dist < 3) {
42703
+ const brightness = Math.max(0, 1 - Math.abs(angleDiff) / 0.4);
42704
+ const colorIdx = Math.floor(brightness * 5);
42705
+ const colors = [22, 28, 34, 40, 46];
42706
+ setChar(grid, r, c3, "\u2588", colors[colorIdx]);
42707
+ } else if (dist < 0.3) {
42708
+ setChar(grid, r, c3, "\u25C9", 46, true);
42709
+ }
42710
+ }
42711
+ }
42712
+ frames.push({ grid, durationMs: 80 });
42713
+ }
42714
+ return frames;
42715
+ }
42716
+ function generateCircuit(width, frameCount = 10) {
42717
+ const frames = [];
42718
+ const hChars = ["\u2500", "\u2501", "\u2550"];
42719
+ const vChars = ["\u2502", "\u2503"];
42720
+ const nodes = ["\u25CF", "\u25C6", "\u25A0"];
42721
+ const colors = [33, 39, 45, 51, 87, 123];
42722
+ for (let f = 0; f < frameCount; f++) {
42723
+ const grid = emptyGrid(width);
42724
+ const activeCol = f * 5 % width;
42725
+ for (let r = 0; r < ROWS; r++) {
42726
+ for (let c3 = 0; c3 < width; c3++) {
42727
+ const seed = (r * 1e3 + c3) * 16807 % 2147483647;
42728
+ if (seed % 7 === 0) {
42729
+ const color = colors[(c3 + f) % colors.length];
42730
+ const isActive = Math.abs(c3 - activeCol) < 8;
42731
+ if (seed % 21 === 0) {
42732
+ setChar(grid, r, c3, nodes[seed % nodes.length], isActive ? 231 : color, isActive);
42733
+ } else {
42734
+ setChar(grid, r, c3, hChars[seed % hChars.length], isActive ? 231 : color);
42735
+ }
42736
+ }
42737
+ }
42738
+ }
42739
+ frames.push({ grid, durationMs: 130 });
42740
+ }
42741
+ return frames;
42742
+ }
42743
+ function generateFire(width, frameCount = 12) {
42744
+ const frames = [];
42745
+ const fireChars = ["\u2591", "\u2592", "\u2593", "\u2588"];
42746
+ const colors = [52, 88, 124, 160, 196, 202, 208, 214, 220, 226];
42747
+ for (let f = 0; f < frameCount; f++) {
42748
+ const grid = emptyGrid(width);
42749
+ for (let c3 = 0; c3 < width; c3++) {
42750
+ for (let r = 0; r < ROWS; r++) {
42751
+ const seed = (c3 * 7 + r * 13 + f * 31) * 16807 % 2147483647;
42752
+ const intensity = seed % 100 / 100;
42753
+ const heightFactor = 1 - r / ROWS;
42754
+ const combined = intensity * heightFactor;
42755
+ if (combined > 0.2) {
42756
+ const ci = Math.floor(combined * (colors.length - 1));
42757
+ const chi = Math.floor(combined * (fireChars.length - 1));
42758
+ setChar(grid, r, c3, fireChars[chi], colors[ci]);
42759
+ }
42760
+ }
42761
+ }
42762
+ frames.push({ grid, durationMs: 100 });
42763
+ }
42764
+ return frames;
42765
+ }
42766
+ function getPreset2(id) {
42767
+ return ANIM_PRESETS.find((p) => p.id === id);
42768
+ }
42769
+ function presetToBannerDesign(presetId, sponsorName, message) {
42770
+ const preset = getPreset2(presetId);
42771
+ const width = process.stdout.columns ?? 80;
42772
+ const frames = preset ? preset.generate(width) : generateWave(width);
42773
+ if (sponsorName) {
42774
+ const nameText = ` \u2726 ${sponsorName}`;
42775
+ for (const frame of frames) {
42776
+ for (let i = 0; i < nameText.length && i < width; i++) {
42777
+ setChar(frame.grid, 0, i, nameText[i], 231, true);
42778
+ }
42779
+ }
42780
+ }
42781
+ if (message) {
42782
+ const msgText = ` ${message}`;
42783
+ for (const frame of frames) {
42784
+ for (let i = 0; i < msgText.length && i < width; i++) {
42785
+ setChar(frame.grid, 2, i, msgText[i], 252);
42786
+ }
42787
+ }
42788
+ }
42789
+ return {
42790
+ id: `sponsor-${presetId}-${Date.now()}`,
42791
+ name: `Sponsor: ${sponsorName}`,
42792
+ type: "sponsor",
42793
+ frames,
42794
+ alignment: ["left", "left", "left"],
42795
+ flowSpeed: [0, 0, 0],
42796
+ author: sponsorName,
42797
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
42798
+ };
42799
+ }
42800
+ function renderPreviewToString(presetId, width, sponsorName, message) {
42801
+ const preset = getPreset2(presetId);
42802
+ const frames = preset ? preset.generate(width, 1) : generateWave(width, 1);
42803
+ const frame = frames[0];
42804
+ if (sponsorName) {
42805
+ const nameText = ` \u2726 ${sponsorName}`;
42806
+ for (let i = 0; i < nameText.length && i < width; i++) {
42807
+ setChar(frame.grid, 0, i, nameText[i], 231, true);
42808
+ }
42809
+ }
42810
+ if (message) {
42811
+ const msgText = ` ${message}`;
42812
+ for (let i = 0; i < msgText.length && i < width; i++) {
42813
+ setChar(frame.grid, 2, i, msgText[i], 252);
42814
+ }
42815
+ }
42816
+ const lines = [];
42817
+ for (let r = 0; r < ROWS; r++) {
42818
+ let line = "";
42819
+ for (let col = 0; col < width; col++) {
42820
+ const cell = frame.grid[r][col];
42821
+ let seq = "";
42822
+ if (cell.fg >= 0)
42823
+ seq += `\x1B[38;5;${cell.fg}m`;
42824
+ if (cell.bg >= 0)
42825
+ seq += `\x1B[48;5;${cell.bg}m`;
42826
+ if (cell.bold)
42827
+ seq += `\x1B[1m`;
42828
+ line += seq + cell.char + "\x1B[0m";
42829
+ }
42830
+ lines.push(line);
42831
+ }
42832
+ return lines.join("\n");
42833
+ }
42834
+ async function generateCustomAnim(prompt, ollamaUrl, model, width = process.stdout.columns ?? 80, frameCount = 8) {
42835
+ const genWidth = 40;
42836
+ const systemPrompt = `Generate ${frameCount} animation frames for a terminal banner. Each frame: 3 rows, each row exactly ${genWidth} characters. Use: \u2591\u2592\u2593\u2588\u25CF\u2605\u2726\u25A0\xB7 and spaces. Respond ONLY with a JSON array.
42837
+
42838
+ EXAMPLE for 2 frames of a "wave" animation:
42839
+ [["\u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588","\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593","\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592"],["\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593","\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592","\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591 \u2591\u2592\u2593\u2588\u2593\u2592\u2591"]]
42840
+
42841
+ RULES: Each row EXACTLY ${genWidth} chars. Pad with spaces. Each frame is ["row1","row2","row3"]. Output ONLY the JSON array, nothing else.`;
42842
+ try {
42843
+ const resp = await fetch(`${ollamaUrl}/api/chat`, {
42844
+ method: "POST",
42845
+ headers: { "Content-Type": "application/json" },
42846
+ body: JSON.stringify({
42847
+ model,
42848
+ messages: [
42849
+ { role: "system", content: systemPrompt },
42850
+ { role: "user", content: `Generate animation: ${prompt}` }
42851
+ ],
42852
+ stream: false,
42853
+ think: false,
42854
+ options: { temperature: 0.7, num_predict: 4096 }
42855
+ }),
42856
+ signal: AbortSignal.timeout(6e4)
42857
+ });
42858
+ if (!resp.ok)
42859
+ return null;
42860
+ const data = await resp.json();
42861
+ const content = data.message?.content || "";
42862
+ let jsonStr = content;
42863
+ jsonStr = jsonStr.replace(/^```(?:json)?\s*\n?/, "").replace(/\n?```\s*$/, "");
42864
+ const jsonMatch = jsonStr.match(/\[[\s\S]*\]/);
42865
+ if (!jsonMatch)
42866
+ return null;
42867
+ let rawFrames;
42868
+ try {
42869
+ rawFrames = JSON.parse(jsonMatch[0]);
42870
+ } catch {
42871
+ let repaired = jsonMatch[0];
42872
+ const opens = (repaired.match(/\[/g) || []).length;
42873
+ const closes = (repaired.match(/\]/g) || []).length;
42874
+ for (let i = 0; i < opens - closes; i++)
42875
+ repaired += '"]';
42876
+ try {
42877
+ rawFrames = JSON.parse(repaired);
42878
+ } catch {
42879
+ return null;
42880
+ }
42881
+ }
42882
+ if (!Array.isArray(rawFrames) || rawFrames.length === 0)
42883
+ return null;
42884
+ const normalizedFrames = [];
42885
+ for (const item of rawFrames) {
42886
+ if (!Array.isArray(item))
42887
+ continue;
42888
+ if (item.length > 0 && Array.isArray(item[0])) {
42889
+ for (const inner of item) {
42890
+ if (Array.isArray(inner) && inner.every((s) => typeof s === "string")) {
42891
+ normalizedFrames.push(inner);
42892
+ }
42893
+ }
42894
+ } else if (item.every((s) => typeof s === "string")) {
42895
+ normalizedFrames.push(item);
42896
+ }
42897
+ }
42898
+ if (normalizedFrames.length === 0)
42899
+ return null;
42900
+ const frames = [];
42901
+ const defaultColor = 252;
42902
+ for (const rawFrame of normalizedFrames) {
42903
+ if (rawFrame.length < ROWS)
42904
+ continue;
42905
+ const grid = emptyGrid(width);
42906
+ for (let r = 0; r < ROWS; r++) {
42907
+ const srcLine = rawFrame[r] || "";
42908
+ for (let c3 = 0; c3 < width; c3++) {
42909
+ const srcIdx = c3 % Math.max(srcLine.length, 1);
42910
+ const ch = srcLine[srcIdx] ?? " ";
42911
+ if (ch !== " ") {
42912
+ setChar(grid, r, c3, ch, defaultColor);
42913
+ }
42914
+ }
42915
+ }
42916
+ frames.push({ grid, durationMs: 120 });
42917
+ }
42918
+ return frames.length > 0 ? frames : null;
42919
+ } catch {
42920
+ return null;
42921
+ }
42922
+ }
42923
+ async function generateCustomAnimWithFallback(prompt, ollamaUrl, preferredModel, width = process.stdout.columns ?? 80, frameCount = 8, onStatus) {
42924
+ onStatus?.(`Generating animation with ${preferredModel}...`);
42925
+ const result1 = await generateCustomAnim(prompt, ollamaUrl, preferredModel, width, frameCount);
42926
+ if (result1)
42927
+ return { frames: result1, source: "llm" };
42928
+ if (!preferredModel.includes("4b")) {
42929
+ onStatus?.("Retrying with smaller model for reliable output...");
42930
+ try {
42931
+ const resp = await fetch(`${ollamaUrl}/api/tags`, { signal: AbortSignal.timeout(5e3) });
42932
+ if (resp.ok) {
42933
+ const data = await resp.json();
42934
+ const small = (data.models || []).find((m) => m.name.includes("4b") || m.name.includes("3b"));
42935
+ if (small) {
42936
+ const result2 = await generateCustomAnim(prompt, ollamaUrl, small.name, width, frameCount);
42937
+ if (result2)
42938
+ return { frames: result2, source: "fallback-model" };
42939
+ }
42940
+ }
42941
+ } catch {
42942
+ }
42943
+ }
42944
+ onStatus?.("LLM generation failed \u2014 using sparkle preset");
42945
+ const preset = getPreset2("sparkle");
42946
+ return { frames: preset.generate(width, frameCount), source: "preset" };
42947
+ }
42948
+ var ROWS, ANIM_PRESETS;
42949
+ var init_sponsor_anims = __esm({
42950
+ "packages/cli/dist/tui/sponsor-anims.js"() {
42951
+ "use strict";
42952
+ ROWS = 3;
42953
+ ANIM_PRESETS = [
42954
+ { id: "wave", name: "Wave", desc: "Flowing wave pattern", generate: generateWave },
42955
+ { id: "pulse", name: "Pulse", desc: "Pulsing dots expanding from center", generate: generatePulse },
42956
+ { id: "matrix", name: "Matrix", desc: "Falling matrix characters", generate: generateMatrix },
42957
+ { id: "sparkle", name: "Sparkle", desc: "Random sparkle particles", generate: generateSparkle },
42958
+ { id: "radar", name: "Radar", desc: "Rotating radar sweep", generate: generateRadar },
42959
+ { id: "circuit", name: "Circuit", desc: "Circuit board traces with flow", generate: generateCircuit },
42960
+ { id: "fire", name: "Fire", desc: "Animated fire effect", generate: generateFire },
42961
+ { id: "none", name: "No Animation", desc: "Static banner only", generate: (w) => [{ grid: emptyGrid(w), durationMs: 0 }] }
42962
+ ];
42963
+ }
42964
+ });
42965
+
42569
42966
  // packages/cli/dist/tui/sponsor-wizard.js
42570
42967
  var sponsor_wizard_exports = {};
42571
42968
  __export(sponsor_wizard_exports, {
@@ -42576,6 +42973,17 @@ __export(sponsor_wizard_exports, {
42576
42973
  });
42577
42974
  import { existsSync as existsSync40, readFileSync as readFileSync29, writeFileSync as writeFileSync17, mkdirSync as mkdirSync16 } from "node:fs";
42578
42975
  import { join as join56 } from "node:path";
42976
+ function colorPreview(code) {
42977
+ return `\x1B[38;5;${code}m\u2588\u2588\u2588\u2588\x1B[0m (${code})`;
42978
+ }
42979
+ function gradientPreview(start, end) {
42980
+ let s = "";
42981
+ for (let i = 0; i < 8; i++) {
42982
+ const cc = start + Math.round((end - start) * (i / 7));
42983
+ s += `\x1B[38;5;${cc}m\u2588\x1B[0m`;
42984
+ }
42985
+ return s;
42986
+ }
42579
42987
  function sponsorDir(projectDir) {
42580
42988
  return join56(projectDir, ".oa", "sponsor");
42581
42989
  }
@@ -42607,7 +43015,11 @@ function defaultConfig() {
42607
43015
  message: "",
42608
43016
  linkEnabled: false,
42609
43017
  linkUrl: "",
42610
- linkText: ""
43018
+ linkText: "",
43019
+ primaryColor: 214,
43020
+ gradientEnabled: false,
43021
+ gradientStart: 196,
43022
+ gradientEnd: 226
42611
43023
  },
42612
43024
  transport: { cloudflared: true, libp2p: false },
42613
43025
  rateLimits: {
@@ -42727,7 +43139,7 @@ async function stepBanner(config, rl, availableRows) {
42727
43139
  const items = [
42728
43140
  { key: "hdr", label: "Select Banner Animation" }
42729
43141
  ];
42730
- for (const preset of ANIM_PRESETS) {
43142
+ for (const preset of ANIM_PRESETS2) {
42731
43143
  items.push({
42732
43144
  key: preset.id,
42733
43145
  label: `${config.banner.preset === preset.id ? "(\u25CF)" : "( )"} ${preset.name}`,
@@ -42742,11 +43154,12 @@ async function stepBanner(config, rl, availableRows) {
42742
43154
  rl,
42743
43155
  skipKeys: ["hdr", "sep"],
42744
43156
  availableRows,
43157
+ customKeyHint: " p preview",
42745
43158
  onAction: (item, action) => {
42746
- if (action === "space" && ANIM_PRESETS.some((p) => p.id === item.key)) {
43159
+ if (action === "space" && ANIM_PRESETS2.some((p) => p.id === item.key)) {
42747
43160
  config.banner.preset = item.key;
42748
43161
  for (const it of items) {
42749
- const p = ANIM_PRESETS.find((pr) => pr.id === it.key);
43162
+ const p = ANIM_PRESETS2.find((pr) => pr.id === it.key);
42750
43163
  if (p) {
42751
43164
  it.label = `${config.banner.preset === p.id ? "(\u25CF)" : "( )"} ${p.name}`;
42752
43165
  }
@@ -42754,13 +43167,25 @@ async function stepBanner(config, rl, availableRows) {
42754
43167
  return true;
42755
43168
  }
42756
43169
  return false;
43170
+ },
43171
+ onCustomKey: (item, key, _helpers) => {
43172
+ if ((key === "p" || key === "P") && ANIM_PRESETS2.some((p) => p.id === item.key)) {
43173
+ const width = process.stdout.columns ?? 80;
43174
+ const preview = renderPreviewToString(item.key, width, config.header?.message || "Sponsor Preview", config.header?.linkText || void 0);
43175
+ process.stdout.write("\n" + preview + "\n\n");
43176
+ return true;
43177
+ }
43178
+ return false;
42757
43179
  }
42758
43180
  });
42759
43181
  if (!result.confirmed)
42760
43182
  return false;
43183
+ const previewWidth = process.stdout.columns ?? 80;
43184
+ const previewStr = renderPreviewToString(config.banner.preset, previewWidth, config.header?.message || "Sponsor Preview", config.header?.linkText || void 0);
43185
+ process.stdout.write("\n" + previewStr + "\n\n");
42761
43186
  if (result.key === "next")
42762
43187
  return true;
42763
- if (ANIM_PRESETS.some((p) => p.id === result.key)) {
43188
+ if (ANIM_PRESETS2.some((p) => p.id === result.key)) {
42764
43189
  config.banner.preset = result.key;
42765
43190
  return true;
42766
43191
  }
@@ -42785,11 +43210,22 @@ async function stepHeader(config, rl, availableRows) {
42785
43210
  label: `${config.header.linkEnabled ? "[x]" : "[ ]"} Link`,
42786
43211
  detail: linkDetail()
42787
43212
  },
43213
+ {
43214
+ key: "color_primary",
43215
+ label: ` Primary color: ${colorPreview(config.header.primaryColor || 214)}`,
43216
+ detail: "Press 'e' to cycle through color presets"
43217
+ },
43218
+ {
43219
+ key: "color_gradient",
43220
+ label: ` Gradient: ${config.header.gradientEnabled ? "[x] " + gradientPreview(config.header.gradientStart || 196, config.header.gradientEnd || 226) : "[ ] disabled"}`
43221
+ },
42788
43222
  { key: "sep", label: "" },
42789
43223
  { key: "next", label: selectColors.green(" Next Step \u2192") }
42790
43224
  ];
42791
43225
  const msgIdx = 1;
42792
43226
  const linkIdx = 2;
43227
+ const colorPrimaryIdx = 3;
43228
+ const colorGradientIdx = 4;
42793
43229
  const result = await tuiSelect({
42794
43230
  items,
42795
43231
  title: "Step 3/5 \u2014 Header Text & Links",
@@ -42808,6 +43244,11 @@ async function stepHeader(config, rl, availableRows) {
42808
43244
  item.label = `${config.header.linkEnabled ? "[x]" : "[ ]"} Link`;
42809
43245
  return true;
42810
43246
  }
43247
+ if (item.key === "color_gradient") {
43248
+ config.header.gradientEnabled = !config.header.gradientEnabled;
43249
+ item.label = ` Gradient: ${config.header.gradientEnabled ? "[x] " + gradientPreview(config.header.gradientStart || 196, config.header.gradientEnd || 226) : "[ ] disabled"}`;
43250
+ return true;
43251
+ }
42811
43252
  }
42812
43253
  return false;
42813
43254
  },
@@ -42829,6 +43270,30 @@ async function stepHeader(config, rl, availableRows) {
42829
43270
  });
42830
43271
  return true;
42831
43272
  }
43273
+ if ((key === "e" || key === "E") && item.key === "color_primary") {
43274
+ const currentIdx = COLOR_PRESETS.findIndex((p) => p.code === (config.header.primaryColor || 214));
43275
+ const nextIdx = (currentIdx + 1) % COLOR_PRESETS.length;
43276
+ config.header.primaryColor = COLOR_PRESETS[nextIdx].code;
43277
+ helpers.updateItem(colorPrimaryIdx, {
43278
+ label: ` Primary color: ${colorPreview(config.header.primaryColor)}`,
43279
+ detail: `Press 'e' to cycle through color presets \u2014 ${COLOR_PRESETS[nextIdx].name}`
43280
+ });
43281
+ helpers.render();
43282
+ return true;
43283
+ }
43284
+ if ((key === "e" || key === "E") && item.key === "color_gradient") {
43285
+ const currentIdx = GRADIENT_PRESETS.findIndex((p) => p.start === (config.header.gradientStart || 196) && p.end === (config.header.gradientEnd || 226));
43286
+ const nextIdx = (currentIdx + 1) % GRADIENT_PRESETS.length;
43287
+ const preset = GRADIENT_PRESETS[nextIdx];
43288
+ config.header.gradientStart = preset.start;
43289
+ config.header.gradientEnd = preset.end;
43290
+ config.header.gradientEnabled = true;
43291
+ helpers.updateItem(colorGradientIdx, {
43292
+ label: ` Gradient: [x] ${gradientPreview(preset.start, preset.end)}`
43293
+ });
43294
+ helpers.render();
43295
+ return true;
43296
+ }
42832
43297
  if ((key === "e" || key === "E") && item.key === "link_toggle") {
42833
43298
  config.header.linkEnabled = true;
42834
43299
  helpers.getInput("Link URL:", config.header.linkUrl).then((url) => {
@@ -43051,13 +43516,33 @@ async function runSponsorWizard(ctx) {
43051
43516
  renderInfo("Toggle: /sponsor status | Pause: /sponsor pause | Remove: /sponsor remove");
43052
43517
  return config;
43053
43518
  }
43054
- var ANIM_PRESETS;
43519
+ var COLOR_PRESETS, GRADIENT_PRESETS, ANIM_PRESETS2;
43055
43520
  var init_sponsor_wizard = __esm({
43056
43521
  "packages/cli/dist/tui/sponsor-wizard.js"() {
43057
43522
  "use strict";
43058
43523
  init_tui_select();
43059
43524
  init_render();
43060
- ANIM_PRESETS = [
43525
+ init_sponsor_anims();
43526
+ COLOR_PRESETS = [
43527
+ { name: "Amber", code: 214 },
43528
+ { name: "Cyan", code: 51 },
43529
+ { name: "Green", code: 46 },
43530
+ { name: "Red", code: 196 },
43531
+ { name: "Purple", code: 135 },
43532
+ { name: "Blue", code: 33 },
43533
+ { name: "Pink", code: 198 },
43534
+ { name: "White", code: 231 },
43535
+ { name: "Gold", code: 220 }
43536
+ ];
43537
+ GRADIENT_PRESETS = [
43538
+ { name: "Fire", start: 196, end: 226 },
43539
+ { name: "Ocean", start: 21, end: 51 },
43540
+ { name: "Forest", start: 22, end: 46 },
43541
+ { name: "Sunset", start: 196, end: 214 },
43542
+ { name: "Neon", start: 198, end: 51 },
43543
+ { name: "Ice", start: 33, end: 231 }
43544
+ ];
43545
+ ANIM_PRESETS2 = [
43061
43546
  { id: "wave", name: "Wave", desc: "Flowing wave pattern" },
43062
43547
  { id: "pulse", name: "Pulse", desc: "Pulsing dots" },
43063
43548
  { id: "matrix", name: "Matrix", desc: "Falling characters" },
@@ -49185,8 +49670,9 @@ async function handleSponsoredEndpoint(ctx, local) {
49185
49670
  sponsors.push({
49186
49671
  name: ns.name || "Unknown Sponsor",
49187
49672
  url: ns.tunnelUrl || "",
49673
+ peerId: ns.peerId || void 0,
49188
49674
  authKey: ns.authKey || "",
49189
- models: ns.models || [],
49675
+ models: Array.isArray(ns.models) ? ns.models : (ns.models || "").split(",").filter(Boolean),
49190
49676
  limits: {
49191
49677
  rpm: ns.limits?.maxRequestsPerMinute || 60,
49192
49678
  tpd: ns.limits?.maxTokensPerDay || 1e5
@@ -49246,11 +49732,22 @@ async function handleSponsoredEndpoint(ctx, local) {
49246
49732
  { key: "hdr", label: "Available Sponsored Endpoints" }
49247
49733
  ];
49248
49734
  for (const sp of sponsors) {
49249
- const modelList = sp.models.length > 0 ? sp.models.slice(0, 3).join(", ") + (sp.models.length > 3 ? ` +${sp.models.length - 3}` : "") : "probing...";
49735
+ const transport = sp.url ? "tunnel" : sp.peerId ? "p2p" : "?";
49736
+ let modelLine;
49737
+ if (sp.models.length > 0) {
49738
+ const shown = sp.models.slice(0, 5).join(", ");
49739
+ const extra = sp.models.length > 5 ? `, +${sp.models.length - 5} more` : "";
49740
+ modelLine = `${sp.models.length} models: ${shown}${extra}`;
49741
+ } else {
49742
+ modelLine = "probing...";
49743
+ }
49744
+ const tpdLabel = sp.limits.tpd >= 1e3 ? (sp.limits.tpd / 1e3).toFixed(0) + "K" : String(sp.limits.tpd);
49745
+ const limitsLine = `${sp.limits.rpm} req/min, ${tpdLabel} tokens/day`;
49250
49746
  items.push({
49251
- key: sp.url,
49252
- label: ` ${sp.name} (${sp.source})`,
49253
- detail: ` Models: ${modelList} | ${sp.limits.rpm} req/min, ${sp.limits.tpd >= 1e3 ? (sp.limits.tpd / 1e3).toFixed(0) + "K" : sp.limits.tpd} tokens/day`
49747
+ key: sp.url || sp.peerId || sp.name,
49748
+ label: ` ${sp.name} (${sp.source}, ${transport})`,
49749
+ detail: ` ${modelLine}
49750
+ ${limitsLine}`
49254
49751
  });
49255
49752
  }
49256
49753
  items.push({ key: "sep", label: "" });
@@ -49267,7 +49764,18 @@ async function handleSponsoredEndpoint(ctx, local) {
49267
49764
  title: "Sponsored Endpoints",
49268
49765
  rl: ctx.rl,
49269
49766
  skipKeys: ["hdr", "sep"],
49270
- availableRows: ctx.availableContentRows?.()
49767
+ availableRows: ctx.availableContentRows?.(),
49768
+ renderRow: (item, focused, _isActive) => {
49769
+ if (item.key === "hdr")
49770
+ return selectColors.bold(item.label);
49771
+ const prefix = focused ? selectColors.orange("\u276F ") : " ";
49772
+ if (item.detail) {
49773
+ const detailLines = item.detail.split("\n");
49774
+ return `${prefix}${item.label}
49775
+ ` + detailLines.map((l) => ` ${selectColors.dim(l)}`).join("\n");
49776
+ }
49777
+ return `${prefix}${item.label}`;
49778
+ }
49271
49779
  });
49272
49780
  if (!result.confirmed || !result.key) {
49273
49781
  renderInfo("Cancelled.");
@@ -49277,15 +49785,30 @@ async function handleSponsoredEndpoint(ctx, local) {
49277
49785
  renderInfo("Use: /endpoint <tunnel-url> --auth <key>");
49278
49786
  return;
49279
49787
  }
49280
- const selected = sponsors.find((s) => s.url === result.key);
49788
+ const selectedKey = result.key;
49789
+ const selected = sponsors.find((s) => (s.url || s.peerId || s.name) === selectedKey);
49281
49790
  if (!selected)
49282
49791
  return;
49283
- const endpointArg = selected.authKey ? `${selected.url} --auth ${selected.authKey}` : selected.url;
49284
- await handleEndpoint(endpointArg, ctx, local);
49792
+ if (selected.url && selected.url.startsWith("http")) {
49793
+ const endpointArg = selected.authKey ? `${selected.url} --auth ${selected.authKey}` : selected.url;
49794
+ await handleEndpoint(endpointArg, ctx, local);
49795
+ } else if (selected.peerId) {
49796
+ await handlePeerEndpoint(selected.peerId, selected.authKey || void 0, ctx, local);
49797
+ } else {
49798
+ renderError("Sponsor has no reachable endpoint (no tunnel URL or peer ID).");
49799
+ return;
49800
+ }
49801
+ if (selected.banner?.preset && ctx.setBanner) {
49802
+ const { presetToBannerDesign: presetToBannerDesign2 } = await Promise.resolve().then(() => (init_sponsor_anims(), sponsor_anims_exports));
49803
+ const bannerDesign = presetToBannerDesign2(selected.banner.preset, selected.name, selected.banner.message);
49804
+ ctx.setBanner(bannerDesign);
49805
+ renderInfo("Banner updated with sponsor branding.");
49806
+ }
49807
+ const saveKey = selected.url || selected.peerId || selected.name;
49285
49808
  try {
49286
49809
  mkdirSync18(sponsorDir2, { recursive: true });
49287
49810
  const existing = existsSync42(knownFile) ? JSON.parse(readFileSync31(knownFile, "utf8")) : [];
49288
- const updated = existing.filter((s) => s.url !== selected.url);
49811
+ const updated = existing.filter((s) => (s.url || s.peerId || s.name) !== saveKey);
49289
49812
  updated.push(selected);
49290
49813
  writeFileSync19(knownFile, JSON.stringify(updated, null, 2), "utf8");
49291
49814
  } catch {
@@ -63953,6 +64476,9 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
63953
64476
  showPrompt() {
63954
64477
  showPrompt();
63955
64478
  },
64479
+ setBanner: (design) => {
64480
+ banner.setDesign(design);
64481
+ },
63956
64482
  retireCarousel() {
63957
64483
  if (!carouselRetired && carousel.isRunning) {
63958
64484
  carousel.stop();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.184.8",
3
+ "version": "0.184.10",
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",