agentopia 1.1.2 → 1.1.3

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/bin/agentopia.js CHANGED
@@ -1,2 +1,26 @@
1
1
  #!/usr/bin/env node
2
+
3
+ const args = process.argv.slice(2);
4
+ for (let i = 0; i < args.length; i++) {
5
+ if (args[i] === '--port' && args[i + 1]) process.env.AGENTOPIA_PORT = args[++i];
6
+ else if (args[i] === '--host' && args[i + 1]) process.env.AGENTOPIA_HOST = args[++i];
7
+ else if (args[i] === '--db' && args[i + 1]) process.env.AGENTOPIA_DB_PATH = args[++i];
8
+ else if (args[i] === '--no-auth') process.env.AGENTOPIA_NO_AUTH = 'true';
9
+ else if (args[i] === '--help' || args[i] === '-h') {
10
+ console.log(`
11
+ Agentopia - Multi-Agent Collaboration Platform
12
+
13
+ Usage: agentopia [options]
14
+
15
+ Options:
16
+ --port <port> Server port (default: 4567)
17
+ --host <host> Bind address (default: 0.0.0.0)
18
+ --db <path> SQLite database path (default: ./agentopia.db)
19
+ --no-auth Disable authentication
20
+ -h, --help Show this help message
21
+ `);
22
+ process.exit(0);
23
+ }
24
+ }
25
+
2
26
  require('../dist/index.js');
@@ -1,6 +1,5 @@
1
- import * as pty from 'node-pty';
2
1
  export interface PtySession {
3
- pty: pty.IPty;
2
+ pty: import('node-pty').IPty;
4
3
  agentId: string;
5
4
  createdAt: number;
6
5
  outputBuffer: string;
@@ -1 +1 @@
1
- {"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../../src/services/terminal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAQhC,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB;AA6DD;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,OAAO,EACnB,IAAI,GAAE,MAAY,EAClB,IAAI,GAAE,MAAW,GAChB,UAAU,CA+FZ;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAWvD;AAED,wBAAgB,kBAAkB,IAAI,IAAI,CAIzC;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAErE"}
1
+ {"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../../src/services/terminal.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,OAAO,UAAU,EAAE,IAAI,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB;AA6DD;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,OAAO,EACnB,IAAI,GAAE,MAAY,EAClB,IAAI,GAAE,MAAW,GAChB,UAAU,CAmGZ;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAWvD;AAED,wBAAgB,kBAAkB,IAAI,IAAI,CAIzC;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAErE"}
@@ -1,37 +1,4 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
36
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
4
  };
@@ -42,12 +9,19 @@ exports.killPtySession = killPtySession;
42
9
  exports.killAllPtySessions = killAllPtySessions;
43
10
  exports.getPtyOutputBuffer = getPtyOutputBuffer;
44
11
  exports.getPtySession = getPtySession;
45
- const pty = __importStar(require("node-pty"));
46
12
  const path_1 = __importDefault(require("path"));
47
13
  const os_1 = __importDefault(require("os"));
48
14
  const database_1 = require("../db/database");
49
15
  const config_1 = require("../config");
50
16
  const logger_1 = __importDefault(require("../logger"));
17
+ // node-pty is optional — interactive terminal is disabled when unavailable
18
+ let pty = null;
19
+ try {
20
+ pty = require('node-pty');
21
+ }
22
+ catch {
23
+ logger_1.default.warn('node-pty not available — interactive terminal features disabled');
24
+ }
51
25
  // Map of agentId -> active PTY session
52
26
  const ptySessions = new Map();
53
27
  const PTY_OUTPUT_BUFFER_MAX = 200000;
@@ -107,6 +81,9 @@ function needsShellExecution(template) {
107
81
  * If `newSession` is true, kill any existing session first.
108
82
  */
109
83
  function getOrCreatePtySession(agentId, newSession, cols = 120, rows = 30) {
84
+ if (!pty) {
85
+ throw new Error('Interactive terminal is not available (node-pty not installed). Install with: npm install node-pty');
86
+ }
110
87
  if (!newSession && ptySessions.has(agentId)) {
111
88
  return ptySessions.get(agentId);
112
89
  }
@@ -1 +1 @@
1
- {"version":3,"file":"terminal.js","sourceRoot":"","sources":["../../src/services/terminal.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"terminal.js","sourceRoot":"","sources":["../../src/services/terminal.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentopia",
3
- "version": "1.1.2",
3
+ "version": "1.1.3",
4
4
  "description": "Multi-Agent Collaboration Platform",
5
5
  "repository": {
6
6
  "type": "git",
@@ -392,6 +392,9 @@
392
392
  if (!editorEl) return;
393
393
  const existing = editorEl.querySelector('.files-preview-iframe');
394
394
  if (existing) existing.remove();
395
+ // Also remove rich previews (docx/xlsx/pptx/sqlite)
396
+ const richPreview = editorEl.querySelector('.files-rich-preview');
397
+ if (richPreview) richPreview.remove();
395
398
  // Restore Monaco editor visibility if hidden
396
399
  if (this.state.editor) {
397
400
  this.state.editor.getDomNode().style.display = '';
@@ -499,6 +502,225 @@
499
502
  }
500
503
  }
501
504
 
505
+ showRichPreview(filePath, label, contentHtml) {
506
+ const editorEl = this.el('editorId');
507
+ if (!editorEl) return;
508
+ if (this.state.editor) this.state.editor.getDomNode().style.display = 'none';
509
+ const existing = editorEl.querySelector('.files-rich-preview');
510
+ if (existing) existing.remove();
511
+ const container = document.createElement('div');
512
+ container.className = 'files-rich-preview';
513
+ container.style.cssText = 'width:100%;height:100%;overflow:auto;background:#fff;color:#222;padding:16px;box-sizing:border-box;font-size:14px;';
514
+ container.innerHTML = contentHtml;
515
+ editorEl.appendChild(container);
516
+ this.state.previewMode = label;
517
+ this.updateSaveButton();
518
+ this.setStatus(`Preview: ${filePath}`);
519
+ this.showBanner(`${label} preview: ${filePath}`, '');
520
+ this.renderTree();
521
+ this.applyMobileEditorFocus(true);
522
+ }
523
+
524
+ removeRichPreview() {
525
+ const editorEl = this.el('editorId');
526
+ if (!editorEl) return;
527
+ const existing = editorEl.querySelector('.files-rich-preview');
528
+ if (existing) existing.remove();
529
+ if (this.state.editor) this.state.editor.getDomNode().style.display = '';
530
+ }
531
+
532
+ async loadOfficeLib(mode) {
533
+ if (mode === 'docx') {
534
+ if (!window._mammothLoaded) {
535
+ await this._loadScript('https://cdn.jsdelivr.net/npm/mammoth@1.8.0/mammoth.browser.min.js');
536
+ window._mammothLoaded = true;
537
+ }
538
+ } else if (mode === 'xlsx') {
539
+ if (!window.XLSX) {
540
+ await this._loadScript('https://cdn.jsdelivr.net/npm/xlsx@0.18.5/dist/xlsx.full.min.js');
541
+ }
542
+ }
543
+ }
544
+
545
+ _loadScript(url) {
546
+ return new Promise((resolve, reject) => {
547
+ const s = document.createElement('script');
548
+ s.src = url;
549
+ s.onload = resolve;
550
+ s.onerror = () => reject(new Error('Failed to load ' + url));
551
+ document.head.appendChild(s);
552
+ });
553
+ }
554
+
555
+ async showOfficePreview(filePath, mode) {
556
+ this.setStatus(`Loading ${mode.toUpperCase()} preview...`);
557
+ try {
558
+ await this.loadOfficeLib(mode);
559
+ const downloadUrl = `/api/agents/${this.getAgentId()}/files/download?path=${encodeURIComponent(filePath)}`;
560
+ const res = await fetch(downloadUrl, { headers: typeof apiHeaders === 'function' ? apiHeaders() : {} });
561
+ if (!res.ok) throw new Error('Failed to download file');
562
+ const arrayBuffer = await res.arrayBuffer();
563
+
564
+ let html = '';
565
+ if (mode === 'docx') {
566
+ const result = await mammoth.convertToHtml({ arrayBuffer });
567
+ html = '<div style="max-width:800px;margin:0 auto;line-height:1.6">' + result.value + '</div>';
568
+ if (result.messages && result.messages.length > 0) {
569
+ html += '<div style="margin-top:16px;padding:8px;background:#fff3cd;border-radius:4px;font-size:12px;color:#856404">' +
570
+ result.messages.map(m => m.message).join('<br>') + '</div>';
571
+ }
572
+ } else if (mode === 'xlsx') {
573
+ const workbook = XLSX.read(arrayBuffer, { type: 'array' });
574
+ html = '<div>';
575
+ // Sheet tabs
576
+ if (workbook.SheetNames.length > 1) {
577
+ html += '<div style="margin-bottom:12px;display:flex;gap:4px;flex-wrap:wrap">';
578
+ workbook.SheetNames.forEach((name, i) => {
579
+ html += '<button onclick="this.closest(\'.files-rich-preview\').querySelectorAll(\'.xlsx-sheet\').forEach((s,j)=>{s.style.display=j===' + i + '?\'block\':\'none\'});this.parentElement.querySelectorAll(\'button\').forEach((b,j)=>{b.style.background=j===' + i + '?\'#0366d6\':\'#e1e4e8\';b.style.color=j===' + i + '?\'#fff\':\'#222\'})" style="padding:4px 12px;border:none;border-radius:4px;cursor:pointer;font-size:12px;' + (i === 0 ? 'background:#0366d6;color:#fff' : 'background:#e1e4e8;color:#222') + '">' + name + '</button>';
580
+ });
581
+ html += '</div>';
582
+ }
583
+ workbook.SheetNames.forEach((name, i) => {
584
+ const sheet = workbook.Sheets[name];
585
+ const sheetHtml = XLSX.utils.sheet_to_html(sheet, { editable: false });
586
+ html += '<div class="xlsx-sheet" style="display:' + (i === 0 ? 'block' : 'none') + ';overflow-x:auto">' + sheetHtml + '</div>';
587
+ });
588
+ html += '</div>';
589
+ // Style the generated tables
590
+ html += '<style>.files-rich-preview table{border-collapse:collapse;font-size:13px;min-width:100%}.files-rich-preview td,.files-rich-preview th{border:1px solid #d0d7de;padding:4px 8px;text-align:left;white-space:nowrap}.files-rich-preview tr:first-child td,.files-rich-preview th{background:#f6f8fa;font-weight:600}</style>';
591
+ } else if (mode === 'pptx') {
592
+ // Basic PPTX info — extract slide count from [Content_Types].xml inside the zip
593
+ html = await this._renderPptxPreview(arrayBuffer);
594
+ }
595
+
596
+ this.removeRichPreview();
597
+ this.removePreviewIframe();
598
+ this.showRichPreview(filePath, mode.toUpperCase(), html);
599
+ } catch (error) {
600
+ this.setStatus(error.message || 'Preview failed');
601
+ this.showBanner(error.message || 'Preview failed', 'error');
602
+ }
603
+ }
604
+
605
+ async _renderPptxPreview(arrayBuffer) {
606
+ // Use JSZip to extract slide info from PPTX
607
+ if (!window.JSZip) {
608
+ await this._loadScript('https://cdn.jsdelivr.net/npm/jszip@3.10.1/dist/jszip.min.js');
609
+ }
610
+ const zip = await JSZip.loadAsync(arrayBuffer);
611
+ const slideFiles = Object.keys(zip.files).filter(f => /^ppt\/slides\/slide\d+\.xml$/.test(f)).sort();
612
+ const slideCount = slideFiles.length;
613
+
614
+ let html = '<div style="max-width:800px;margin:0 auto">';
615
+ html += '<div style="margin-bottom:16px;font-size:16px;font-weight:600">PowerPoint Presentation — ' + slideCount + ' slide' + (slideCount !== 1 ? 's' : '') + '</div>';
616
+
617
+ // Extract text content from each slide
618
+ for (let i = 0; i < slideFiles.length; i++) {
619
+ const xmlContent = await zip.file(slideFiles[i]).async('string');
620
+ // Extract text between <a:t> tags
621
+ const textMatches = xmlContent.match(/<a:t>([^<]*)<\/a:t>/g) || [];
622
+ const texts = textMatches.map(m => m.replace(/<\/?a:t>/g, '')).filter(t => t.trim());
623
+
624
+ html += '<div style="border:1px solid #d0d7de;border-radius:8px;padding:16px;margin-bottom:12px;background:#f6f8fa">';
625
+ html += '<div style="font-size:12px;color:#656d76;margin-bottom:8px;font-weight:600">Slide ' + (i + 1) + '</div>';
626
+ if (texts.length > 0) {
627
+ html += '<div style="line-height:1.5">' + texts.map(t => '<div>' + t.replace(/</g, '&lt;').replace(/>/g, '&gt;') + '</div>').join('') + '</div>';
628
+ } else {
629
+ html += '<div style="color:#8b949e;font-style:italic">No text content</div>';
630
+ }
631
+ html += '</div>';
632
+ }
633
+ html += '</div>';
634
+ return html;
635
+ }
636
+
637
+ async showSqlitePreview(filePath) {
638
+ this.setStatus('Loading SQLite preview...');
639
+ try {
640
+ const baseUrl = `/api/agents/${this.getAgentId()}/files/sqlite?path=${encodeURIComponent(filePath)}`;
641
+ const res = await fetch(baseUrl, { headers: typeof apiHeaders === 'function' ? apiHeaders() : {} });
642
+ if (!res.ok) {
643
+ const err = await res.json().catch(() => ({}));
644
+ throw new Error(err.error || 'Failed to load SQLite file');
645
+ }
646
+ const data = await res.json();
647
+ const tables = data.tables || [];
648
+
649
+ let html = '<div style="max-width:100%;margin:0 auto" id="sqlite-preview-root">';
650
+ html += '<div style="margin-bottom:16px;font-size:16px;font-weight:600">SQLite Database — ' + tables.length + ' table' + (tables.length !== 1 ? 's' : '') + '</div>';
651
+ html += '<div style="display:flex;gap:4px;flex-wrap:wrap;margin-bottom:16px">';
652
+ tables.forEach((t, i) => {
653
+ html += '<button data-table="' + t.name + '" onclick="window[\'' + this.apiName + '\']._sqliteLoadTable(this)" style="padding:4px 12px;border:none;border-radius:4px;cursor:pointer;font-size:12px;' + (i === 0 ? 'background:#0366d6;color:#fff' : 'background:#e1e4e8;color:#222') + '">' + t.name + ' (' + t.rowCount + ')</button>';
654
+ });
655
+ html += '</div>';
656
+ html += '<div id="sqlite-table-content" style="overflow-x:auto"></div>';
657
+ html += '</div>';
658
+
659
+ this.removeRichPreview();
660
+ this.removePreviewIframe();
661
+ this.showRichPreview(filePath, 'SQLite', html);
662
+
663
+ // Store state for table loading
664
+ this._sqliteFilePath = filePath;
665
+ // Expose for onclick
666
+ window[this.apiName]._sqliteLoadTable = (btn) => this._sqliteLoadTable(btn);
667
+
668
+ // Load first table automatically
669
+ if (tables.length > 0) {
670
+ const firstBtn = this.el('editorId')?.querySelector('button[data-table]');
671
+ if (firstBtn) this._sqliteLoadTable(firstBtn);
672
+ }
673
+ } catch (error) {
674
+ this.setStatus(error.message || 'SQLite preview failed');
675
+ this.showBanner(error.message || 'SQLite preview failed', 'error');
676
+ }
677
+ }
678
+
679
+ async _sqliteLoadTable(btn) {
680
+ const tableName = btn.dataset.table;
681
+ if (!tableName) return;
682
+
683
+ // Update tab button styles
684
+ const container = btn.parentElement;
685
+ if (container) {
686
+ container.querySelectorAll('button').forEach(b => {
687
+ b.style.background = b === btn ? '#0366d6' : '#e1e4e8';
688
+ b.style.color = b === btn ? '#fff' : '#222';
689
+ });
690
+ }
691
+
692
+ const contentEl = document.getElementById('sqlite-table-content');
693
+ if (!contentEl) return;
694
+ contentEl.innerHTML = '<div style="color:#656d76;padding:8px">Loading...</div>';
695
+
696
+ try {
697
+ const url = `/api/agents/${this.getAgentId()}/files/sqlite?path=${encodeURIComponent(this._sqliteFilePath)}&table=${encodeURIComponent(tableName)}&limit=200`;
698
+ const res = await fetch(url, { headers: typeof apiHeaders === 'function' ? apiHeaders() : {} });
699
+ if (!res.ok) throw new Error('Failed to load table');
700
+ const data = await res.json();
701
+
702
+ let html = '<div style="font-size:12px;color:#656d76;margin-bottom:8px">' + data.totalRows + ' rows total (showing ' + data.rows.length + ')</div>';
703
+ html += '<table style="border-collapse:collapse;font-size:13px;min-width:100%"><thead><tr>';
704
+ data.columns.forEach(col => {
705
+ html += '<th style="border:1px solid #d0d7de;padding:4px 8px;background:#f6f8fa;font-weight:600;white-space:nowrap">' + col.name + '<span style="color:#8b949e;font-weight:400;margin-left:4px;font-size:11px">' + col.type + '</span></th>';
706
+ });
707
+ html += '</tr></thead><tbody>';
708
+ data.rows.forEach(row => {
709
+ html += '<tr>';
710
+ data.columns.forEach(col => {
711
+ const val = row[col.name];
712
+ const display = val === null ? '<span style="color:#8b949e">NULL</span>' : String(val).length > 200 ? String(val).slice(0, 200) + '…' : String(val).replace(/</g, '&lt;').replace(/>/g, '&gt;');
713
+ html += '<td style="border:1px solid #d0d7de;padding:4px 8px;white-space:nowrap;max-width:400px;overflow:hidden;text-overflow:ellipsis">' + display + '</td>';
714
+ });
715
+ html += '</tr>';
716
+ });
717
+ html += '</tbody></table>';
718
+ contentEl.innerHTML = html;
719
+ } catch (error) {
720
+ contentEl.innerHTML = '<div style="color:#f85149;padding:8px">' + (error.message || 'Failed to load table') + '</div>';
721
+ }
722
+ }
723
+
502
724
  async activate() {
503
725
  this.updateWorkingDirectoryState();
504
726