From 2df77b62f9d8e3422a020af348549683fdc4fffd Mon Sep 17 00:00:00 2001 From: Vaayne Date: Thu, 31 Jul 2025 14:31:53 +0800 Subject: [PATCH] fix init shell with command --- cagents/python-cli-web-poc/README.md | 90 -- cagents/python-cli-web-poc/package-lock.json | 857 ----------------- cagents/python-cli-web-poc/package.json | 17 - cagents/python-cli-web-poc/public/index.html | 46 - cagents/python-cli-web-poc/public/script.js | 281 ------ .../public/style-enhanced.css | 884 ------------------ cagents/python-cli-web-poc/public/style.css | 341 ------- cagents/python-cli-web-poc/server.js | 179 ---- cagents/python-cli-web-poc/simple-calc.py | 29 - cagents/python-cli-web-poc/test-script.py | 39 - src/main/ipc.ts | 4 +- src/main/services/MCPService.ts | 2 +- .../agent}/commandExecutor.ts | 32 +- src/main/{services/mcp => utils}/shell-env.ts | 0 src/renderer/src/Router.tsx | 4 +- src/renderer/src/components/app/Sidebar.tsx | 6 +- src/renderer/src/hooks/usePocCommand.ts | 2 +- src/renderer/src/hooks/usePocMessages.ts | 2 +- .../CherryAgentPage.tsx} | 81 +- .../components/PocCommandInput.tsx | 15 +- .../components/PocHeader.tsx | 0 .../components/PocMessageBubble.tsx | 3 +- .../components/PocMessageList.tsx | 2 +- .../components/PocStatusBar.tsx | 0 .../DisplaySettings/SidebarIconsManager.tsx | 5 +- .../src/services/AgentCommandService.ts | 28 +- src/renderer/src/store/settings.ts | 13 +- .../types.ts => types/cherryAgent.ts} | 0 src/renderer/src/types/index.ts | 1 + 29 files changed, 127 insertions(+), 2836 deletions(-) delete mode 100644 cagents/python-cli-web-poc/README.md delete mode 100644 cagents/python-cli-web-poc/package-lock.json delete mode 100644 cagents/python-cli-web-poc/package.json delete mode 100644 cagents/python-cli-web-poc/public/index.html delete mode 100644 cagents/python-cli-web-poc/public/script.js delete mode 100644 cagents/python-cli-web-poc/public/style-enhanced.css delete mode 100644 cagents/python-cli-web-poc/public/style.css delete mode 100644 cagents/python-cli-web-poc/server.js delete mode 100644 cagents/python-cli-web-poc/simple-calc.py delete mode 100644 cagents/python-cli-web-poc/test-script.py rename src/main/{poc => services/agent}/commandExecutor.ts (89%) rename src/main/{services/mcp => utils}/shell-env.ts (100%) rename src/renderer/src/pages/{command-poc/CommandPocPage.tsx => cherry-agent/CherryAgentPage.tsx} (63%) rename src/renderer/src/pages/{command-poc => cherry-agent}/components/PocCommandInput.tsx (94%) rename src/renderer/src/pages/{command-poc => cherry-agent}/components/PocHeader.tsx (100%) rename src/renderer/src/pages/{command-poc => cherry-agent}/components/PocMessageBubble.tsx (98%) rename src/renderer/src/pages/{command-poc => cherry-agent}/components/PocMessageList.tsx (98%) rename src/renderer/src/pages/{command-poc => cherry-agent}/components/PocStatusBar.tsx (100%) rename src/renderer/src/{pages/command-poc/types.ts => types/cherryAgent.ts} (100%) diff --git a/cagents/python-cli-web-poc/README.md b/cagents/python-cli-web-poc/README.md deleted file mode 100644 index 16006545c..000000000 --- a/cagents/python-cli-web-poc/README.md +++ /dev/null @@ -1,90 +0,0 @@ -# Python CLI Web Interface POC - -A proof-of-concept web interface for running Python CLI applications with real-time input/output interaction. - -## Features - -- **Web-based Terminal**: Chat-like interface for running Python commands -- **Real-time I/O**: Bidirectional communication with Python processes -- **Interactive Input**: Support for Python scripts that require user input -- **Process Management**: Start, monitor, and kill Python processes -- **WebSocket Communication**: Low-latency real-time updates - -## Quick Start - -1. **Install dependencies**: - ```bash - npm install - ``` - -2. **Start the server**: - ```bash - npm start - ``` - -3. **Open your browser**: - - Navigate to `http://localhost:3000` - - The interface will load automatically - -## Usage Examples - -### Basic Python Commands -```bash -python --version -python -c "print('Hello World')" -``` - -### Interactive Scripts -```bash -python test-script.py -python simple-calc.py -``` - -### Test Scripts Included - -- **`test-script.py`**: Demonstrates user input, output streaming, and interactive features -- **`simple-calc.py`**: Simple calculator that takes mathematical expressions - -## How It Works - -1. **Frontend**: HTML/CSS/JS interface that looks like a terminal/chat -2. **WebSocket**: Real-time bidirectional communication -3. **Node.js Backend**: Spawns Python processes and manages I/O -4. **Process Management**: Each command runs in its own Python process - -## Architecture - -``` -┌─────────────────┐ WebSocket ┌──────────────────┐ spawn() ┌─────────────┐ -│ Web Browser │ ◄─────────────► │ Node.js Server │ ◄──────────► │ Python │ -│ (Frontend) │ │ (Backend) │ │ Process │ -└─────────────────┘ └──────────────────┘ └─────────────┘ -``` - -## Key Files - -- `server.js` - Node.js server with WebSocket support -- `public/index.html` - Web interface -- `public/script.js` - Frontend JavaScript logic -- `public/style.css` - Interface styling -- `test-script.py` - Sample interactive Python script - -## Development - -The POC supports: -- ✅ Running Python commands -- ✅ Real-time output streaming -- ✅ Interactive input handling -- ✅ Process termination -- ✅ Error handling -- ✅ Connection status monitoring -- ✅ Auto-reconnection - -## Limitations - -This is a POC with basic security. For production use, consider: -- Input sanitization -- Process sandboxing -- Authentication/authorization -- Resource limits -- Proper error handling \ No newline at end of file diff --git a/cagents/python-cli-web-poc/package-lock.json b/cagents/python-cli-web-poc/package-lock.json deleted file mode 100644 index 223b988a9..000000000 --- a/cagents/python-cli-web-poc/package-lock.json +++ /dev/null @@ -1,857 +0,0 @@ -{ - "name": "python-cli-web-poc", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "python-cli-web-poc", - "version": "1.0.0", - "dependencies": { - "express": "^4.18.2", - "ws": "^8.14.2" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "license": "MIT" - }, - "node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "license": "MIT" - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "license": "MIT" - }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT" - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", - "license": "MIT", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", - "proxy-addr": "~2.0.7", - "qs": "6.13.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "license": "MIT" - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "license": "MIT", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "license": "MIT" - }, - "node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", - "license": "MIT", - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "license": "ISC" - }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - } - } -} diff --git a/cagents/python-cli-web-poc/package.json b/cagents/python-cli-web-poc/package.json deleted file mode 100644 index 0cb5d2880..000000000 --- a/cagents/python-cli-web-poc/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "python-cli-web-poc", - "version": "1.0.0", - "description": "POC for running Python CLI apps through web interface", - "main": "server.js", - "scripts": { - "start": "node server.js", - "dev": "node server.js" - }, - "dependencies": { - "express": "^4.18.2", - "ws": "^8.14.2" - }, - "engines": { - "node": ">=14.0.0" - } -} \ No newline at end of file diff --git a/cagents/python-cli-web-poc/public/index.html b/cagents/python-cli-web-poc/public/index.html deleted file mode 100644 index a2774f493..000000000 --- a/cagents/python-cli-web-poc/public/index.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - Python CLI Web Interface - - - -
-
-

Python CLI Web Interface

-
- -
- - Disconnected -
-
-
- -
-
- -
-
- - - -
- - -
-
-
- - - - diff --git a/cagents/python-cli-web-poc/public/script.js b/cagents/python-cli-web-poc/public/script.js deleted file mode 100644 index 82f6d6de1..000000000 --- a/cagents/python-cli-web-poc/public/script.js +++ /dev/null @@ -1,281 +0,0 @@ -class PythonWebInterface { - constructor() { - this.ws = null - this.currentSessionId = null - this.isConnected = false - this.isRunning = false - - this.initializeElements() - this.setupEventListeners() - this.connect() - } - - initializeElements() { - this.statusIndicator = document.getElementById('status-indicator') - this.statusText = document.getElementById('status-text') - this.output = document.getElementById('output') - this.commandInput = document.getElementById('command-input') - this.userInput = document.getElementById('user-input') - this.userInputContainer = document.getElementById('user-input-container') - this.runBtn = document.getElementById('run-btn') - this.killBtn = document.getElementById('kill-btn') - this.sendBtn = document.getElementById('send-btn') - this.themeToggle = document.getElementById('theme-toggle') - - // Initialize theme - this.initializeTheme() - } - - setupEventListeners() { - this.runBtn.addEventListener('click', () => this.runCommand()) - this.killBtn.addEventListener('click', () => this.killSession()) - this.sendBtn.addEventListener('click', () => this.sendInput()) - this.themeToggle.addEventListener('click', () => this.toggleTheme()) - - this.commandInput.addEventListener('keypress', (e) => { - if (e.key === 'Enter' && !this.isRunning) { - this.runCommand() - } - }) - - this.userInput.addEventListener('keypress', (e) => { - if (e.key === 'Enter') { - this.sendInput() - } - }) - - // Listen for system theme changes - if (window.matchMedia) { - const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)') - mediaQuery.addEventListener('change', () => { - if (!localStorage.getItem('theme-preference')) { - this.updateTheme(mediaQuery.matches ? 'dark' : 'light') - } - }) - } - } - - connect() { - const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:' - const wsUrl = `${protocol}//${window.location.host}` - - this.ws = new WebSocket(wsUrl) - - this.ws.onopen = () => { - this.isConnected = true - this.updateStatus('Connected', true) - this.addSystemMessage('Connected to server') - } - - this.ws.onclose = () => { - this.isConnected = false - this.updateStatus('Disconnected', false) - this.addSystemMessage('Disconnected from server. Attempting to reconnect...') - - // Attempt to reconnect after 3 seconds - setTimeout(() => { - if (!this.isConnected) { - this.connect() - } - }, 3000) - } - - this.ws.onerror = (error) => { - this.addErrorMessage('WebSocket error occurred') - } - - this.ws.onmessage = (event) => { - this.handleMessage(JSON.parse(event.data)) - } - } - - handleMessage(data) { - switch (data.type) { - case 'command_started': - this.isRunning = true - this.currentSessionId = data.sessionId - this.updateUIState() - this.showUserInput() - this.addSystemMessage(`Started: ${data.command}`) - break - - case 'output': - this.addOutput(data.data, data.stream === 'stderr') - break - - case 'command_finished': - this.isRunning = false - this.currentSessionId = null - this.updateUIState() - this.hideUserInput() - this.addSystemMessage(`Process finished with exit code: ${data.exitCode}`) - break - - case 'error': - this.addErrorMessage(data.message) - this.isRunning = false - this.currentSessionId = null - this.updateUIState() - this.hideUserInput() - break - } - } - - runCommand() { - const command = this.commandInput.value.trim() - if (!command || !this.isConnected || this.isRunning) return - - this.addCommandMessage(command) - - const sessionId = 'session_' + Date.now() - this.ws.send( - JSON.stringify({ - type: 'run_command', - command: command, - sessionId: sessionId - }) - ) - - this.commandInput.value = '' - } - - sendInput() { - const input = this.userInput.value - if (!input || !this.currentSessionId) return - - this.addInputMessage(input) - - this.ws.send( - JSON.stringify({ - type: 'send_input', - input: input, - sessionId: this.currentSessionId - }) - ) - - this.userInput.value = '' - } - - killSession() { - if (this.currentSessionId) { - this.ws.send( - JSON.stringify({ - type: 'kill_session', - sessionId: this.currentSessionId - }) - ) - } - } - - updateStatus(text, connected) { - this.statusText.textContent = text - this.statusIndicator.className = connected ? 'status-connected' : 'status-disconnected' - } - - updateUIState() { - this.runBtn.disabled = !this.isConnected || this.isRunning - this.killBtn.disabled = !this.isRunning - this.commandInput.disabled = !this.isConnected || this.isRunning - } - - showUserInput() { - this.userInputContainer.style.display = 'flex' - this.userInput.focus() - } - - hideUserInput() { - this.userInputContainer.style.display = 'none' - } - - addMessage(content, className) { - const messageDiv = document.createElement('div') - messageDiv.className = `message ${className}` - - const timestamp = document.createElement('div') - timestamp.className = 'timestamp' - timestamp.textContent = new Date().toLocaleTimeString() - - const contentDiv = document.createElement('pre') - contentDiv.textContent = content - - messageDiv.appendChild(timestamp) - messageDiv.appendChild(contentDiv) - - this.output.appendChild(messageDiv) - this.scrollToBottom() - } - - addCommandMessage(command) { - this.addMessage(`$ ${command}`, 'command') - } - - addInputMessage(input) { - this.addMessage(`> ${input}`, 'command') - } - - addOutput(data, isError = false) { - this.addMessage(data, isError ? 'error' : 'output') - } - - addSystemMessage(message) { - this.addMessage(message, 'system') - } - - addErrorMessage(message) { - this.addMessage(`Error: ${message}`, 'error') - } - - scrollToBottom() { - this.output.scrollTop = this.output.scrollHeight - } - - // Theme Management - Cherry Studio Style - initializeTheme() { - const savedTheme = localStorage.getItem('theme-preference') - const systemPrefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches - - let theme - if (savedTheme) { - theme = savedTheme - } else { - theme = systemPrefersDark ? 'dark' : 'light' - } - - this.updateTheme(theme) - } - - toggleTheme() { - const currentTheme = document.documentElement.getAttribute('theme-mode') || 'dark' - const newTheme = currentTheme === 'dark' ? 'light' : 'dark' - - localStorage.setItem('theme-preference', newTheme) - this.updateTheme(newTheme) - - // Add feedback animation - this.themeToggle.style.transform = 'scale(0.9)' - setTimeout(() => { - this.themeToggle.style.transform = 'scale(1)' - }, 150) - } - - updateTheme(theme) { - document.documentElement.setAttribute('theme-mode', theme) - - // Update theme toggle icon - if (this.themeToggle) { - this.themeToggle.textContent = theme === 'dark' ? '☀️' : '🌙' - this.themeToggle.setAttribute('aria-label', `Switch to ${theme === 'dark' ? 'light' : 'dark'} theme`) - this.themeToggle.title = `Switch to ${theme === 'dark' ? 'light' : 'dark'} theme` - } - - // Detect OS for header styling - if (navigator.platform.includes('Mac')) { - document.body.setAttribute('os', 'darwin') - } - } -} - -// Initialize the interface when the page loads -document.addEventListener('DOMContentLoaded', () => { - new PythonWebInterface() -}) diff --git a/cagents/python-cli-web-poc/public/style-enhanced.css b/cagents/python-cli-web-poc/public/style-enhanced.css deleted file mode 100644 index 4a8924882..000000000 --- a/cagents/python-cli-web-poc/public/style-enhanced.css +++ /dev/null @@ -1,884 +0,0 @@ -/* Cherry Studio Design System CSS Variables */ -:root { - /* Colors - Dark Theme (Default) */ - --color-white: #ffffff; - --color-white-soft: rgba(255, 255, 255, 0.8); - --color-white-mute: rgba(255, 255, 255, 0.94); - - --color-black: #181818; - --color-black-soft: #222222; - --color-black-mute: #333333; - - --color-gray-1: #515c67; - --color-gray-2: #414853; - --color-gray-3: #32363f; - - --color-text-1: rgba(255, 255, 245, 0.9); - --color-text-2: rgba(235, 235, 245, 0.6); - --color-text-3: rgba(235, 235, 245, 0.38); - - --color-background: var(--color-black); - --color-background-soft: var(--color-black-soft); - --color-background-mute: var(--color-black-mute); - --color-background-opacity: rgba(34, 34, 34, 0.7); - --inner-glow-opacity: 0.3; - - --color-primary: #00b96b; - --color-primary-soft: #00b96b99; - --color-primary-mute: #00b96b33; - - --color-text: var(--color-text-1); - --color-text-secondary: rgba(235, 235, 245, 0.7); - --color-icon: #ffffff99; - --color-icon-white: #ffffff; - --color-border: #ffffff19; - --color-border-soft: #ffffff10; - --color-border-mute: #ffffff05; - --color-error: #f44336; - --color-success: #52c41a; - --color-warning: #faad14; - --color-link: #338cff; - --color-code-background: #323232; - --color-hover: rgba(40, 40, 40, 1); - --color-active: rgba(55, 55, 55, 1); - --color-frame-border: #333; - --color-group-background: var(--color-background-soft); - - --color-reference: #404040; - --color-reference-text: #ffffff; - --color-reference-background: #0b0e12; - - --color-list-item: rgba(255, 255, 255, 0.1); - --color-list-item-hover: rgba(255, 255, 255, 0.05); - - --modal-background: #111111; - - --color-highlight: rgba(0, 0, 0, 1); - --color-background-highlight: rgba(255, 255, 0, 0.9); - --color-background-highlight-accent: rgba(255, 150, 50, 0.9); - - --navbar-background-mac: rgba(20, 20, 20, 0.55); - --navbar-background: #1f1f1f; - - /* Typography */ - --font-family: Ubuntu, -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, Roboto, Oxygen, Cantarell, 'Open Sans', 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; - --font-family-mono: 'Cascadia Code', 'Fira Code', 'Consolas', Menlo, Courier, monospace; - --font-family-serif: serif, -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, Ubuntu, Roboto, Oxygen, Cantarell, 'Open Sans', 'Helvetica Neue', Arial, 'Noto Sans', 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; - - /* Sizing */ - --navbar-height: 44px; - --status-bar-height: 40px; - --input-bar-height: 100px; - --border-radius: 10px; - --border-radius-small: 6px; - --spacing-xs: 4px; - --spacing-sm: 8px; - --spacing-md: 12px; - --spacing-lg: 16px; - --spacing-xl: 24px; - --spacing-xxl: 32px; - --scrollbar-width: 5px; - - /* Chat styling */ - --chat-background: transparent; - --chat-background-user: rgba(255, 255, 255, 0.08); - --chat-background-assistant: transparent; - --chat-text-user: var(--color-black); - - --list-item-border-radius: 10px; - - --color-status-success: #52c41a; - --color-status-error: #ff4d4f; - --color-status-warning: #faad14; - - /* Scrollbar colors */ - --color-scrollbar-thumb-dark: rgba(255, 255, 255, 0.15); - --color-scrollbar-thumb-dark-hover: rgba(255, 255, 255, 0.2); - --color-scrollbar-thumb: var(--color-scrollbar-thumb-dark); - --color-scrollbar-thumb-hover: var(--color-scrollbar-thumb-dark-hover); - - /* Transitions */ - --transition-fast: 0.15s ease; - --transition-normal: 0.2s ease; - --transition-slow: 0.3s ease; -} - -/* Light Theme */ -[theme-mode='light'] { - --color-white: #ffffff; - --color-white-soft: rgba(0, 0, 0, 0.04); - --color-white-mute: #eee; - - --color-black: #1b1b1f; - --color-black-soft: #262626; - --color-black-mute: #363636; - - --color-gray-1: #8e8e93; - --color-gray-2: #aeaeb2; - --color-gray-3: #c7c7cc; - - --color-text-1: rgba(0, 0, 0, 1); - --color-text-2: rgba(0, 0, 0, 0.6); - --color-text-3: rgba(0, 0, 0, 0.38); - - --color-background: var(--color-white); - --color-background-soft: var(--color-white-soft); - --color-background-mute: var(--color-white-mute); - --color-background-opacity: rgba(243, 243, 243, 1); - --inner-glow-opacity: 0.1; - - --color-primary: #00b96b; - --color-primary-soft: #00b96b99; - --color-primary-mute: #00b96b33; - - --color-text: var(--color-text-1); - --color-text-secondary: rgba(0, 0, 0, 0.75); - --color-icon: #00000099; - --color-icon-white: #000000; - --color-border: #00000019; - --color-border-soft: #00000010; - --color-border-mute: #00000005; - --color-error: #f44336; - --color-link: #1677ff; - --color-code-background: #e3e3e3; - --color-hover: var(--color-white-mute); - --color-active: var(--color-white-soft); - --color-frame-border: #ddd; - --color-group-background: var(--color-white); - - --color-reference: #cfe1ff; - --color-reference-text: #000000; - --color-reference-background: #f1f7ff; - - --color-list-item: #fff; - --color-list-item-hover: #fafafa; - - --modal-background: var(--color-white); - - --color-highlight: initial; - --color-background-highlight: rgba(255, 255, 0, 0.5); - --color-background-highlight-accent: rgba(255, 150, 50, 0.5); - - --navbar-background-mac: rgba(255, 255, 255, 0.55); - --navbar-background: rgba(244, 244, 244); - - --chat-background: transparent; - --chat-background-user: rgba(0, 0, 0, 0.045); - --chat-background-assistant: transparent; - --chat-text-user: var(--color-text); - - /* Scrollbar colors for light theme */ - --color-scrollbar-thumb-light: rgba(0, 0, 0, 0.15); - --color-scrollbar-thumb-light-hover: rgba(0, 0, 0, 0.2); - --color-scrollbar-thumb: var(--color-scrollbar-thumb-light); - --color-scrollbar-thumb-hover: var(--color-scrollbar-thumb-light-hover); -} - -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -body { - font-family: var(--font-family); - background-color: var(--color-background); - color: var(--color-text); - height: 100vh; - overflow: hidden; - font-size: 14px; - line-height: 1.5; - transition: background-color var(--transition-normal), color var(--transition-normal); -} - -.container { - display: flex; - flex-direction: column; - height: 100vh; - position: relative; -} - -header { - background-color: var(--navbar-background); - padding: var(--spacing-lg) var(--spacing-xl); - border-bottom: 1px solid var(--color-border); - display: flex; - justify-content: space-between; - align-items: center; - height: var(--navbar-height); - backdrop-filter: blur(10px); - -webkit-backdrop-filter: blur(10px); - transition: background-color var(--transition-slow) linear, border-color var(--transition-normal); - position: relative; - z-index: 10; - box-shadow: 0 1px 0 var(--color-border-soft); -} - -/* macOS specific header styling */ -body[os='darwin'] header { - background-color: var(--navbar-background-mac); -} - -header h1 { - font-size: 1.25rem; - font-weight: 600; - color: var(--color-text); - margin: 0; - transition: color var(--transition-slow) linear; - font-family: var(--font-family); - letter-spacing: -0.01em; -} - -.header-controls { - display: flex; - align-items: center; - gap: var(--spacing-lg); -} - -.status { - display: flex; - align-items: center; - gap: var(--spacing-sm); - padding: var(--spacing-xs) var(--spacing-md); - background-color: var(--color-background-opacity); - border-radius: var(--border-radius-small); - border: 1px solid var(--color-border-soft); - transition: all var(--transition-normal); -} - -.status-connected { - color: var(--color-success); -} - -.status-disconnected { - color: var(--color-error); -} - -.status span:first-child { - font-size: 12px; - animation: pulse 2s infinite; -} - -.status span:last-child { - font-size: 13px; - font-weight: 500; - color: var(--color-text-secondary); -} - -@keyframes pulse { - 0%, 100% { opacity: 1; } - 50% { opacity: 0.5; } -} - -.chat-container { - flex: 1; - display: flex; - flex-direction: column; - overflow: hidden; - position: relative; -} - -.output-area { - flex: 1; - padding: var(--spacing-lg) var(--spacing-xl); - overflow-y: auto; - background-color: var(--color-background); - font-family: var(--font-family); - font-size: 14px; - line-height: 1.6; - scroll-behavior: smooth; - position: relative; -} - -.message { - margin-bottom: var(--spacing-lg); - padding: var(--spacing-md) var(--spacing-lg); - border-radius: var(--border-radius); - max-width: 100%; - word-wrap: break-word; - position: relative; - transition: all var(--transition-normal); - transform: translateZ(0); - will-change: transform; - animation: messageSlideIn 0.3s ease-out; - display: flow-root; -} - -.message:hover { - transform: translateY(-1px); - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); -} - -[theme-mode='light'] .message:hover { - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); -} - -.message + .message { - margin-top: var(--spacing-md); -} - -/* User/Command Messages - styled like Cherry Studio user messages */ -.message.command { - background-color: var(--chat-background-user); - color: var(--color-text); - margin-left: auto; - margin-right: 0; - text-align: right; - max-width: 85%; - font-family: var(--font-family-mono); - font-size: 14px; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); - border: 1px solid var(--color-border-soft); - align-self: flex-end; -} - -[theme-mode='light'] .message.command { - color: var(--chat-text-user); - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); -} - -.message.command::before { - content: "$ "; - opacity: 0.7; - font-weight: bold; - color: var(--color-primary); -} - -/* Assistant/Output Messages - styled like Cherry Studio assistant messages */ -.message.output { - background-color: var(--chat-background-assistant); - border-left: 4px solid var(--color-success); - border-radius: var(--border-radius); - font-family: var(--font-family-mono); - font-size: 14px; - position: relative; - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); - border: 1px solid var(--color-border-soft); - border-left: 4px solid var(--color-success); - padding-left: var(--spacing-xl); - color: var(--color-text); -} - -.message.output::before { - content: "✓"; - position: absolute; - left: -2px; - top: var(--spacing-md); - width: 16px; - height: 16px; - background-color: var(--color-success); - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - font-size: 10px; - color: white; - font-weight: bold; - z-index: 1; -} - -/* Error Messages */ -.message.error { - background-color: var(--chat-background-assistant); - border-left: 4px solid var(--color-error); - border-radius: var(--border-radius); - font-family: var(--font-family-mono); - font-size: 14px; - position: relative; - box-shadow: 0 1px 3px rgba(244, 67, 54, 0.1); - border: 1px solid var(--color-border-soft); - border-left: 4px solid var(--color-error); - padding-left: var(--spacing-xl); - color: var(--color-text); -} - -.message.error::before { - content: "✕"; - position: absolute; - left: -2px; - top: var(--spacing-md); - width: 16px; - height: 16px; - background-color: var(--color-error); - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - font-size: 10px; - color: white; - font-weight: bold; - z-index: 1; -} - -/* System Messages */ -.message.system { - background-color: var(--chat-background-assistant); - border-left: 4px solid var(--color-warning); - font-style: italic; - border-radius: var(--border-radius); - font-size: 14px; - position: relative; - box-shadow: 0 1px 3px rgba(255, 152, 0, 0.1); - border: 1px solid var(--color-border-soft); - border-left: 4px solid var(--color-warning); - color: var(--color-text-secondary); - padding-left: var(--spacing-xl); -} - -.message.system::before { - content: "i"; - position: absolute; - left: -2px; - top: var(--spacing-md); - width: 16px; - height: 16px; - background-color: var(--color-warning); - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - font-size: 12px; - color: white; - font-weight: bold; - font-style: normal; - z-index: 1; -} - -.message pre { - margin: 0; - white-space: pre-wrap; - word-break: break-word; - font-family: var(--font-family-mono); - font-size: 14px; - line-height: 1.5; - color: inherit; -} - -.message pre code { - font-family: var(--font-family-mono); - background: transparent; - padding: 0; - border-radius: 0; - color: inherit; -} - -/* Consistent with Cherry Studio's code styling */ -code { - color: var(--color-text); - font-family: var(--font-family-mono); - background-color: var(--color-code-background); - padding: 2px 4px; - border-radius: 4px; - font-size: 0.9em; -} - -.input-area { - background-color: var(--color-background-soft); - padding: var(--spacing-lg) var(--spacing-xl); - border-top: 1px solid var(--color-border); - backdrop-filter: blur(10px); - -webkit-backdrop-filter: blur(10px); - transition: all var(--transition-normal); - position: relative; - z-index: 5; -} - -.command-input-container, -.user-input-container { - display: flex; - gap: var(--spacing-md); - align-items: center; - position: relative; -} - -.user-input-container { - margin-top: var(--spacing-md); - padding-top: var(--spacing-md); - border-top: 1px solid var(--color-border-soft); -} - -input[type="text"] { - flex: 1; - padding: var(--spacing-md) var(--spacing-lg); - border: 1px solid var(--color-border); - border-radius: var(--border-radius); - background-color: var(--color-background-opacity); - color: var(--color-text); - font-size: 14px; - font-family: var(--font-family-mono); - transition: all var(--transition-normal); - backdrop-filter: blur(5px); - -webkit-backdrop-filter: blur(5px); -} - -input[type="text"]:focus { - outline: none; - border-color: var(--color-primary); - box-shadow: 0 0 0 3px var(--color-primary-mute); - background-color: var(--color-background); - transform: translateY(-1px); -} - -button { - padding: var(--spacing-md) var(--spacing-xl); - border: none; - border-radius: var(--border-radius); - font-size: 14px; - font-weight: 600; - cursor: pointer; - transition: all var(--transition-normal); - position: relative; - overflow: hidden; - font-family: var(--font-family); - min-width: 80px; - display: flex; - align-items: center; - justify-content: center; - gap: var(--spacing-xs); -} - -button::before { - content: ''; - position: absolute; - top: 0; - left: -100%; - width: 100%; - height: 100%; - background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent); - transition: left var(--transition-slow); -} - -button:hover::before { - left: 100%; -} - -#run-btn { - background-color: var(--color-success); - color: white; - box-shadow: 0 2px 8px rgba(82, 196, 26, 0.2); -} - -#run-btn:hover:not(:disabled) { - background-color: #45a049; - transform: translateY(-2px); - box-shadow: 0 4px 16px rgba(82, 196, 26, 0.3); -} - -#run-btn:active:not(:disabled) { - transform: translateY(0); - box-shadow: 0 2px 8px rgba(82, 196, 26, 0.2); -} - -#run-btn:disabled { - background-color: var(--color-gray-3); - cursor: not-allowed; - opacity: 0.6; - transform: none; - box-shadow: none; -} - -#kill-btn { - background-color: var(--color-error); - color: white; - box-shadow: 0 2px 8px rgba(244, 67, 54, 0.2); -} - -#kill-btn:hover:not(:disabled) { - background-color: #da190b; - transform: translateY(-2px); - box-shadow: 0 4px 16px rgba(244, 67, 54, 0.3); -} - -#kill-btn:active:not(:disabled) { - transform: translateY(0); - box-shadow: 0 2px 8px rgba(244, 67, 54, 0.2); -} - -#kill-btn:disabled { - background-color: var(--color-gray-3); - cursor: not-allowed; - opacity: 0.6; - transform: none; - box-shadow: none; -} - -#send-btn { - background-color: var(--color-primary); - color: white; - box-shadow: 0 2px 8px var(--color-primary-mute); -} - -#send-btn:hover:not(:disabled) { - background-color: #00a55e; - transform: translateY(-2px); - box-shadow: 0 4px 16px var(--color-primary-soft); -} - -#send-btn:active:not(:disabled) { - transform: translateY(0); - box-shadow: 0 2px 8px var(--color-primary-mute); -} - -#send-btn:disabled { - background-color: var(--color-gray-3); - cursor: not-allowed; - opacity: 0.6; - transform: none; - box-shadow: none; -} - -.timestamp { - font-size: 11px; - color: var(--color-text-3); - margin-bottom: var(--spacing-xs); - font-family: var(--font-family-mono); - opacity: 0.8; - transition: color var(--transition-normal); -} - -/* Cherry Studio Scrollbar Styling */ -::-webkit-scrollbar { - width: var(--scrollbar-width); - height: var(--scrollbar-width); -} - -::-webkit-scrollbar-track, -::-webkit-scrollbar-corner { - background: transparent; -} - -::-webkit-scrollbar-thumb { - border-radius: 10px; - background: var(--color-scrollbar-thumb); - transition: background-color var(--transition-normal); -} - -::-webkit-scrollbar-thumb:hover { - background: var(--color-scrollbar-thumb-hover); -} - -/* Firefox scrollbar */ -.output-area { - scrollbar-width: thin; - scrollbar-color: var(--color-scrollbar-thumb) transparent; -} - -/* Hide scrollbar for screenshot capability */ -.hide-scrollbar, -.hide-scrollbar * { - scrollbar-width: none !important; -} - -.hide-scrollbar::-webkit-scrollbar { - display: none !important; -} - -/* Theme Toggle Button */ -.theme-toggle { - background: none; - border: 1px solid var(--color-border); - color: var(--color-icon); - border-radius: 50%; - width: 36px; - height: 36px; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - transition: all var(--transition-normal); - font-size: 16px; - padding: 0; - min-width: 36px; -} - -.theme-toggle:hover { - background-color: var(--color-hover); - color: var(--color-text); - transform: scale(1.1); -} - -/* Loading states */ -.loading { - position: relative; - overflow: hidden; -} - -.loading::after { - content: ''; - position: absolute; - top: 0; - left: -100%; - width: 100%; - height: 100%; - background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent); - animation: loading-shine 1.5s infinite; -} - -@keyframes loading-shine { - 0% { left: -100%; } - 100% { left: 100%; } -} - -/* Cherry Studio Animation Effects */ -@keyframes messageSlideIn { - from { - opacity: 0; - transform: translateY(20px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -@keyframes animation-pulse { - 0% { - box-shadow: 0 0 0 0 rgba(var(--pulse-color), 0.5); - } - 70% { - box-shadow: 0 0 0 var(--pulse-size) rgba(var(--pulse-color), 0); - } - 100% { - box-shadow: 0 0 0 0 rgba(var(--pulse-color), 0); - } -} - -.animation-pulse { - --pulse-color: 0, 185, 107; - --pulse-size: 8px; - animation: animation-pulse 1.5s infinite; -} - -@keyframes flash { - 0%, 100% { - opacity: 1; - } - 50% { - opacity: 0.5; - } -} - -.loader { - width: 16px; - height: 16px; - border-radius: 50%; - background-color: var(--color-text); - box-shadow: 32px 0 var(--color-text), -32px 0 var(--color-text); - position: relative; - animation: flash 0.5s ease-out infinite alternate; -} - -/* Empty state */ -.output-area:empty::before { - content: 'Welcome to Python CLI Web Interface\AStart by entering a Python command below'; - white-space: pre; - display: block; - text-align: center; - color: var(--color-text-3); - font-style: italic; - margin-top: 25%; - line-height: 1.8; -} - -/* Enhanced Focus Indicators for Accessibility */ -*:focus { - outline: none; -} - -button:focus-visible, -input:focus-visible, -.theme-toggle:focus-visible { - outline: 2px solid var(--color-primary); - outline-offset: 2px; - border-radius: var(--border-radius); -} - -/* High contrast mode support */ -@media (prefers-contrast: high) { - :root { - --color-border: #666; - --color-border-soft: #444; - --color-text-secondary: rgba(255, 255, 255, 0.9); - } - - [theme-mode='light'] { - --color-border: #999; - --color-border-soft: #bbb; - --color-text-secondary: rgba(0, 0, 0, 0.9); - } -} - -/* Reduced motion support */ -@media (prefers-reduced-motion: reduce) { - * { - animation-duration: 0.01ms !important; - animation-iteration-count: 1 !important; - transition-duration: 0.01ms !important; - } - - .message { - animation: none; - } - - button::before { - transition: none; - } -} - -/* Responsive design */ -@media (max-width: 768px) { - header { - padding: var(--spacing-md) var(--spacing-lg); - } - - .output-area { - padding: var(--spacing-md) var(--spacing-lg); - } - - .input-area { - padding: var(--spacing-md) var(--spacing-lg); - } - - .command-input-container, - .user-input-container { - flex-direction: column; - gap: var(--spacing-sm); - } - - button { - width: 100%; - order: 1; - } - - input[type="text"] { - order: 0; - } - - .message { - margin-bottom: var(--spacing-md); - } - - .message.command { - max-width: 100%; - } -} - -@media (max-width: 480px) { - header h1 { - font-size: 1.1rem; - } - - .status { - font-size: 12px; - } - - button { - padding: var(--spacing-sm) var(--spacing-md); - font-size: 13px; - } - - input[type="text"] { - padding: var(--spacing-sm) var(--spacing-md); - font-size: 13px; - } -} \ No newline at end of file diff --git a/cagents/python-cli-web-poc/public/style.css b/cagents/python-cli-web-poc/public/style.css deleted file mode 100644 index c62d7ddce..000000000 --- a/cagents/python-cli-web-poc/public/style.css +++ /dev/null @@ -1,341 +0,0 @@ -/* Cherry Studio Design System CSS Variables */ -:root { - /* Colors - Dark Theme (Default) */ - --color-white: #ffffff; - --color-white-soft: rgba(255, 255, 255, 0.8); - --color-white-mute: rgba(255, 255, 255, 0.94); - - --color-black: #181818; - --color-black-soft: #222222; - --color-black-mute: #333333; - - --color-gray-1: #515c67; - --color-gray-2: #414853; - --color-gray-3: #32363f; - - --color-text-1: rgba(255, 255, 245, 0.9); - --color-text-2: rgba(235, 235, 245, 0.6); - --color-text-3: rgba(235, 235, 245, 0.38); - - --color-background: var(--color-black); - --color-background-soft: var(--color-black-soft); - --color-background-mute: var(--color-black-mute); - --color-background-opacity: rgba(34, 34, 34, 0.7); - - --color-primary: #00b96b; - --color-primary-soft: #00b96b99; - --color-primary-mute: #00b96b33; - - --color-text: var(--color-text-1); - --color-text-secondary: rgba(235, 235, 245, 0.7); - --color-icon: #ffffff99; - --color-border: #ffffff19; - --color-border-soft: #ffffff10; - --color-error: #f44336; - --color-success: #52c41a; - --color-warning: #faad14; - --color-link: #338cff; - --color-code-background: #323232; - --color-hover: rgba(40, 40, 40, 1); - --color-active: rgba(55, 55, 55, 1); - - /* Typography */ - --font-family: 'Segoe UI', 'SF Pro Display', -apple-system, BlinkMacSystemFont, sans-serif; - --font-family-mono: 'SF Mono', 'Monaco', 'Cascadia Code', 'Roboto Mono', 'Courier New', monospace; - --font-family-serif: 'Times New Roman', Times, serif; - - /* Sizing */ - --navbar-height: 44px; - --border-radius: 10px; - --border-radius-small: 6px; - --spacing-xs: 4px; - --spacing-sm: 8px; - --spacing-md: 12px; - --spacing-lg: 16px; - --spacing-xl: 24px; - --spacing-xxl: 32px; - - /* Transitions */ - --transition-fast: 0.15s ease; - --transition-normal: 0.2s ease; - --transition-slow: 0.3s ease; -} - -/* Light Theme */ -[theme-mode='light'] { - --color-white: #ffffff; - --color-white-soft: rgba(0, 0, 0, 0.04); - --color-white-mute: #eee; - - --color-black: #1b1b1f; - --color-black-soft: #262626; - --color-black-mute: #363636; - - --color-gray-1: #8e8e93; - --color-gray-2: #aeaeb2; - --color-gray-3: #c7c7cc; - - --color-text-1: rgba(0, 0, 0, 1); - --color-text-2: rgba(0, 0, 0, 0.6); - --color-text-3: rgba(0, 0, 0, 0.38); - - --color-background: var(--color-white); - --color-background-soft: var(--color-white-soft); - --color-background-mute: var(--color-white-mute); - --color-background-opacity: rgba(243, 243, 243, 1); - - --color-text: var(--color-text-1); - --color-text-secondary: rgba(0, 0, 0, 0.75); - --color-icon: #00000099; - --color-border: #00000019; - --color-border-soft: #00000010; - --color-link: #1677ff; - --color-code-background: #e3e3e3; - --color-hover: var(--color-white-mute); - --color-active: var(--color-white-soft); -} - -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -body { - font-family: var(--font-family); - background-color: var(--color-background); - color: var(--color-text); - height: 100vh; - overflow: hidden; - font-size: 14px; - line-height: 1.5; - transition: background-color var(--transition-normal), color var(--transition-normal); -} - -.container { - display: flex; - flex-direction: column; - height: 100vh; - position: relative; -} - -header { - background-color: var(--color-background-soft); - padding: var(--spacing-lg) var(--spacing-xl); - border-bottom: 1px solid var(--color-border); - display: flex; - justify-content: space-between; - align-items: center; - height: var(--navbar-height); - backdrop-filter: blur(10px); - -webkit-backdrop-filter: blur(10px); - transition: background-color var(--transition-normal), border-color var(--transition-normal); - position: relative; - z-index: 10; -} - -header h1 { - font-size: 1.25rem; - font-weight: 600; - color: var(--color-text); - margin: 0; - transition: color var(--transition-normal); -} - -.status { - display: flex; - align-items: center; - gap: var(--spacing-sm); - padding: var(--spacing-xs) var(--spacing-md); - background-color: var(--color-background-opacity); - border-radius: var(--border-radius-small); - border: 1px solid var(--color-border-soft); - transition: all var(--transition-normal); -} - -.status-connected { - color: var(--color-success); -} - -.status-disconnected { - color: var(--color-error); -} - -.status span:first-child { - font-size: 12px; - animation: pulse 2s infinite; -} - -.status span:last-child { - font-size: 13px; - font-weight: 500; - color: var(--color-text-secondary); -} - -@keyframes pulse { - 0%, 100% { opacity: 1; } - 50% { opacity: 0.5; } -} - -.chat-container { - flex: 1; - display: flex; - flex-direction: column; - overflow: hidden; - position: relative; -} - -.output-area { - flex: 1; - padding: var(--spacing-lg) var(--spacing-xl); - overflow-y: auto; - background-color: var(--color-background); - font-family: var(--font-family); - font-size: 14px; - line-height: 1.6; - scroll-behavior: smooth; - position: relative; -} - -.message { - margin-bottom: 1rem; - padding: 0.75rem 1rem; - border-radius: 8px; - max-width: 100%; - word-wrap: break-word; -} - -.message.command { - background-color: #0d7377; - color: white; - margin-left: auto; - margin-right: 0; - text-align: right; -} - -.message.output { - background-color: #2d2d2d; - border-left: 4px solid #4caf50; -} - -.message.error { - background-color: #2d2d2d; - border-left: 4px solid #f44336; -} - -.message.system { - background-color: #2d2d2d; - border-left: 4px solid #ff9800; - font-style: italic; -} - -.message pre { - margin: 0; - white-space: pre-wrap; - word-break: break-all; -} - -.input-area { - background-color: #2d2d2d; - padding: 1rem 2rem; - border-top: 1px solid #404040; -} - -.command-input-container, -.user-input-container { - display: flex; - gap: 0.5rem; - align-items: center; -} - -.user-input-container { - margin-top: 0.5rem; -} - -input[type="text"] { - flex: 1; - padding: 0.75rem 1rem; - border: 1px solid #404040; - border-radius: 4px; - background-color: #1e1e1e; - color: #ffffff; - font-size: 14px; - font-family: 'Courier New', monospace; -} - -input[type="text"]:focus { - outline: none; - border-color: #0d7377; - box-shadow: 0 0 0 2px rgba(13, 115, 119, 0.2); -} - -button { - padding: 0.75rem 1.5rem; - border: none; - border-radius: 4px; - font-size: 14px; - font-weight: 600; - cursor: pointer; - transition: background-color 0.2s; -} - -#run-btn { - background-color: #4caf50; - color: white; -} - -#run-btn:hover:not(:disabled) { - background-color: #45a049; -} - -#run-btn:disabled { - background-color: #666; - cursor: not-allowed; -} - -#kill-btn { - background-color: #f44336; - color: white; -} - -#kill-btn:hover:not(:disabled) { - background-color: #da190b; -} - -#kill-btn:disabled { - background-color: #666; - cursor: not-allowed; -} - -#send-btn { - background-color: #2196f3; - color: white; -} - -#send-btn:hover:not(:disabled) { - background-color: #1976d2; -} - -.timestamp { - font-size: 12px; - color: #888; - margin-bottom: 0.25rem; -} - -/* Scrollbar styling for webkit browsers */ -.output-area::-webkit-scrollbar { - width: 8px; -} - -.output-area::-webkit-scrollbar-track { - background: #1e1e1e; -} - -.output-area::-webkit-scrollbar-thumb { - background: #404040; - border-radius: 4px; -} - -.output-area::-webkit-scrollbar-thumb:hover { - background: #555; -} \ No newline at end of file diff --git a/cagents/python-cli-web-poc/server.js b/cagents/python-cli-web-poc/server.js deleted file mode 100644 index abc22ae63..000000000 --- a/cagents/python-cli-web-poc/server.js +++ /dev/null @@ -1,179 +0,0 @@ -const express = require('express') -const WebSocket = require('ws') -const { spawn } = require('child_process') -const path = require('path') -const http = require('http') - -const app = express() -const server = http.createServer(app) -const wss = new WebSocket.Server({ server }) - -const PORT = process.env.PORT || 3000 - -// Serve static files from public directory -app.use(express.static('public')) - -// Route for main page -app.get('/', (req, res) => { - res.redirect('/index.html') -}) - -// Store active Python processes -const activeSessions = new Map() - -wss.on('connection', (ws) => { - console.log('Client connected') - - ws.on('message', (message) => { - try { - const data = JSON.parse(message) - - switch (data.type) { - case 'run_command': - handlePythonCommand(ws, data.command, data.sessionId) - break - case 'send_input': - handleUserInput(ws, data.input, data.sessionId) - break - case 'kill_session': - killSession(data.sessionId) - break - } - } catch (error) { - ws.send( - JSON.stringify({ - type: 'error', - message: 'Invalid message format' - }) - ) - } - }) - - ws.on('close', () => { - console.log('Client disconnected') - // Clean up any active sessions for this client - for (let [sessionId, session] of activeSessions) { - if (session.ws === ws) { - killSession(sessionId) - } - } - }) -}) - -function handlePythonCommand(ws, command, sessionId) { - // Kill existing session if any - if (activeSessions.has(sessionId)) { - killSession(sessionId) - } - - // Parse command (simple split for POC) - const args = command.trim().split(' ') - const pythonCommand = args[0] === 'python' || args[0] === 'python3' ? args[0] : 'python3' - const scriptArgs = args[0] === 'python' || args[0] === 'python3' ? args.slice(1) : args - - try { - // Spawn Python process - const pythonProcess = spawn(pythonCommand, scriptArgs, { - stdio: ['pipe', 'pipe', 'pipe'] - }) - - // Store session - activeSessions.set(sessionId, { - process: pythonProcess, - ws: ws - }) - - // Send confirmation - ws.send( - JSON.stringify({ - type: 'command_started', - sessionId: sessionId, - command: command - }) - ) - - // Handle stdout - pythonProcess.stdout.on('data', (data) => { - ws.send( - JSON.stringify({ - type: 'output', - sessionId: sessionId, - data: data.toString(), - stream: 'stdout' - }) - ) - }) - - // Handle stderr - pythonProcess.stderr.on('data', (data) => { - ws.send( - JSON.stringify({ - type: 'output', - sessionId: sessionId, - data: data.toString(), - stream: 'stderr' - }) - ) - }) - - // Handle process exit - pythonProcess.on('close', (code) => { - ws.send( - JSON.stringify({ - type: 'command_finished', - sessionId: sessionId, - exitCode: code - }) - ) - activeSessions.delete(sessionId) - }) - - // Handle process error - pythonProcess.on('error', (error) => { - ws.send( - JSON.stringify({ - type: 'error', - sessionId: sessionId, - message: `Failed to start process: ${error.message}` - }) - ) - activeSessions.delete(sessionId) - }) - } catch (error) { - ws.send( - JSON.stringify({ - type: 'error', - sessionId: sessionId, - message: `Error running command: ${error.message}` - }) - ) - } -} - -function handleUserInput(ws, input, sessionId) { - const session = activeSessions.get(sessionId) - if (session && session.process) { - session.process.stdin.write(input + '\n') - } else { - ws.send( - JSON.stringify({ - type: 'error', - sessionId: sessionId, - message: 'No active session to send input to' - }) - ) - } -} - -function killSession(sessionId) { - const session = activeSessions.get(sessionId) - if (session && session.process) { - session.process.kill() - activeSessions.delete(sessionId) - } -} - -server.listen(PORT, () => { - console.log(`Server running on http://localhost:${PORT}`) - console.log('Open your browser and navigate to the URL above') -}) diff --git a/cagents/python-cli-web-poc/simple-calc.py b/cagents/python-cli-web-poc/simple-calc.py deleted file mode 100644 index 80194c2da..000000000 --- a/cagents/python-cli-web-poc/simple-calc.py +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env python3 -""" -Simple calculator for testing input/output -""" - -def main(): - print("🧮 Simple Calculator") - print("-" * 20) - print("Enter expressions like: 2 + 3, 10 * 5, etc.") - print("Type 'quit' to exit") - - while True: - try: - expression = input("Calculate: ").strip() - - if expression.lower() == 'quit': - print("👋 Goodbye!") - break - - # Simple evaluation (unsafe in production, but fine for POC) - result = eval(expression) - print(f"Result: {result}") - - except Exception as e: - print(f"❌ Error: {e}") - print("Please enter a valid mathematical expression") - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/cagents/python-cli-web-poc/test-script.py b/cagents/python-cli-web-poc/test-script.py deleted file mode 100644 index 16f3ce796..000000000 --- a/cagents/python-cli-web-poc/test-script.py +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env python3 -""" -Test Python script for the web CLI POC -Demonstrates various interactive features -""" - -import time -import sys - -def main(): - print("🐍 Python CLI Web Interface Test Script") - print("=" * 40) - - # Test basic output - print("Hello from Python!") - print("This is a test script to demonstrate the web interface.") - - # Test user input - name = input("What's your name? ") - print(f"Nice to meet you, {name}!") - - # Test multiple inputs - while True: - color = input("What's your favorite color? (or 'quit' to exit): ") - if color.lower() == 'quit': - break - print(f"🎨 {color} is a great choice!") - - # Test countdown with streaming output - print("\nStarting countdown...") - for i in range(5, 0, -1): - print(f"⏰ {i}...") - sys.stdout.flush() # Force output to be sent immediately - time.sleep(1) - - print("🎉 Done! Thanks for testing the Python CLI Web Interface!") - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/src/main/ipc.ts b/src/main/ipc.ts index c97c82030..5f0bf7b2f 100644 --- a/src/main/ipc.ts +++ b/src/main/ipc.ts @@ -10,11 +10,11 @@ import { SpanEntity, TokenUsage } from '@mcp-trace/trace-core' import { UpgradeChannel } from '@shared/config/constant' import { IpcChannel } from '@shared/IpcChannel' import { FileMetadata, Provider, Shortcut, ThemeMode } from '@types' +import { PocExecuteCommandRequest } from '@types' import { BrowserWindow, dialog, ipcMain, ProxyConfig, session, shell, systemPreferences, webContents } from 'electron' import { Notification } from 'src/renderer/src/types/notification' -import { PocExecuteCommandRequest } from '../renderer/src/pages/command-poc/types' -import { pocCommandExecutor } from './poc/commandExecutor' +import { pocCommandExecutor } from './services/agent/commandExecutor' import { apiServerService } from './services/ApiServerService' import appService from './services/AppService' import AppUpdater from './services/AppUpdater' diff --git a/src/main/services/MCPService.ts b/src/main/services/MCPService.ts index 0921a5b82..0f44dc301 100644 --- a/src/main/services/MCPService.ts +++ b/src/main/services/MCPService.ts @@ -34,11 +34,11 @@ import { EventEmitter } from 'events' import { memoize } from 'lodash' import { v4 as uuidv4 } from 'uuid' +import getLoginShellEnvironment from '../utils/shell-env' import { CacheService } from './CacheService' import DxtService from './DxtService' import { CallBackServer } from './mcp/oauth/callback' import { McpOAuthClientProvider } from './mcp/oauth/provider' -import getLoginShellEnvironment from './mcp/shell-env' import { windowService } from './WindowService' // Generic type for caching wrapped functions diff --git a/src/main/poc/commandExecutor.ts b/src/main/services/agent/commandExecutor.ts similarity index 89% rename from src/main/poc/commandExecutor.ts rename to src/main/services/agent/commandExecutor.ts index c12f20e1a..8083dc6ac 100644 --- a/src/main/poc/commandExecutor.ts +++ b/src/main/services/agent/commandExecutor.ts @@ -1,12 +1,12 @@ import { ChildProcess, spawn } from 'node:child_process' -import { platform } from 'node:os' import { loggerService } from '@logger' +import { isWin } from '@main/constant' +import getLoginShellEnvironment from '@main/utils/shell-env' import { IpcChannel } from '@shared/IpcChannel' +import { PocCommandOutput, PocExecuteCommandRequest } from '@types' import { BrowserWindow } from 'electron' -import { PocCommandOutput, PocExecuteCommandRequest } from '../../renderer/src/pages/command-poc/types' - const logger = loggerService.withContext('PocCommandExecutor') export interface PocRunningProcess { @@ -18,7 +18,7 @@ export interface PocRunningProcess { } /** - * PocCommandExecutor - POC implementation for cross-platform command execution + * ShellCommandExecutor - POC implementation for cross-platform command execution * * Features: * - Cross-platform shell detection (cmd on Windows, bash on Unix-like systems) @@ -27,8 +27,8 @@ export interface PocRunningProcess { * - Command interruption support * - Proper error handling and process cleanup */ -export class PocCommandExecutor { - private static instance: PocCommandExecutor | null = null +export class ShellCommandExecutor { + private static instance: ShellCommandExecutor | null = null private mainWindow: BrowserWindow | null = null private activeProcesses = new Map() @@ -37,11 +37,11 @@ export class PocCommandExecutor { logger.info('PocCommandExecutor initialized') } - public static getInstance(): PocCommandExecutor { - if (!PocCommandExecutor.instance) { - PocCommandExecutor.instance = new PocCommandExecutor() + public static getInstance(): ShellCommandExecutor { + if (!ShellCommandExecutor.instance) { + ShellCommandExecutor.instance = new ShellCommandExecutor() } - return PocCommandExecutor.instance + return ShellCommandExecutor.instance } public setMainWindow(mainWindow: BrowserWindow) { @@ -53,9 +53,7 @@ export class PocCommandExecutor { * Detects the appropriate shell for the current platform */ private getShellCommand(): { shell: string; args: string[] } { - const isWindows = platform() === 'win32' - - if (isWindows) { + if (isWin) { // Windows: Use cmd.exe with /c flag return { shell: 'cmd.exe', @@ -89,15 +87,17 @@ export class PocCommandExecutor { try { const { shell, args } = this.getShellCommand() const fullArgs = [...args, command] + // load login shell environment + const loginEnv = await getLoginShellEnvironment() // Spawn the child process const childProcess = spawn(shell, fullArgs, { cwd: workingDirectory, stdio: ['pipe', 'pipe', 'pipe'], env: { - ...process.env, + ...loginEnv, // Ensure UTF-8 encoding on Windows - ...(platform() === 'win32' ? { CHCP: '65001' } : {}) + ...(isWin ? { CHCP: '65001' } : {}) } }) @@ -242,4 +242,4 @@ export class PocCommandExecutor { } } -export const pocCommandExecutor = PocCommandExecutor.getInstance() +export const pocCommandExecutor = ShellCommandExecutor.getInstance() diff --git a/src/main/services/mcp/shell-env.ts b/src/main/utils/shell-env.ts similarity index 100% rename from src/main/services/mcp/shell-env.ts rename to src/main/utils/shell-env.ts diff --git a/src/renderer/src/Router.tsx b/src/renderer/src/Router.tsx index 8eeace0f7..2c879cef2 100644 --- a/src/renderer/src/Router.tsx +++ b/src/renderer/src/Router.tsx @@ -8,7 +8,7 @@ import TabsContainer from './components/Tab/TabContainer' import NavigationHandler from './handler/NavigationHandler' import { useNavbarPosition } from './hooks/useSettings' import AgentsPage from './pages/agents/AgentsPage' -import CommandPocPage from './pages/command-poc/CommandPocPage' +import CherryAgentPage from './pages/cherry-agent/CherryAgentPage' import FilesPage from './pages/files/FilesPage' import HomePage from './pages/home/HomePage' import KnowledgePage from './pages/knowledge/KnowledgePage' @@ -26,7 +26,7 @@ const Router: FC = () => { } /> } /> - } /> + } /> } /> } /> } /> diff --git a/src/renderer/src/components/app/Sidebar.tsx b/src/renderer/src/components/app/Sidebar.tsx index 5325b0a4b..4e0f87f28 100644 --- a/src/renderer/src/components/app/Sidebar.tsx +++ b/src/renderer/src/components/app/Sidebar.tsx @@ -146,7 +146,8 @@ const MainMenus: FC = () => { translate: , minapp: , knowledge: , - files: + files: , + cherryAgent: } const pathMap = { @@ -156,7 +157,8 @@ const MainMenus: FC = () => { translate: '/translate', minapp: '/apps', knowledge: '/knowledge', - files: '/files' + files: '/files', + cherryAgent: '/cherryAgent' } return sidebarIcons.visible.map((icon) => { diff --git a/src/renderer/src/hooks/usePocCommand.ts b/src/renderer/src/hooks/usePocCommand.ts index d5fb2f66b..f581ac9ae 100644 --- a/src/renderer/src/hooks/usePocCommand.ts +++ b/src/renderer/src/hooks/usePocCommand.ts @@ -1,6 +1,6 @@ import { loggerService } from '@logger' -import type { PocCommandExecution } from '@renderer/pages/command-poc/types' import { agentCommandService } from '@renderer/services/AgentCommandService' +import type { PocCommandExecution } from '@types' import { useCallback, useEffect, useRef, useState } from 'react' const logger = loggerService.withContext('UsePocCommand') diff --git a/src/renderer/src/hooks/usePocMessages.ts b/src/renderer/src/hooks/usePocMessages.ts index 2970c3fc8..9b71c90d1 100644 --- a/src/renderer/src/hooks/usePocMessages.ts +++ b/src/renderer/src/hooks/usePocMessages.ts @@ -1,6 +1,6 @@ import { loggerService } from '@logger' -import type { PocMessage } from '@renderer/pages/command-poc/types' import { agentCommandService } from '@renderer/services/AgentCommandService' +import type { PocMessage } from '@types' import { useCallback, useEffect, useState } from 'react' const logger = loggerService.withContext('UsePocMessages') diff --git a/src/renderer/src/pages/command-poc/CommandPocPage.tsx b/src/renderer/src/pages/cherry-agent/CherryAgentPage.tsx similarity index 63% rename from src/renderer/src/pages/command-poc/CommandPocPage.tsx rename to src/renderer/src/pages/cherry-agent/CherryAgentPage.tsx index 9f92f61f2..25fcdf266 100644 --- a/src/renderer/src/pages/command-poc/CommandPocPage.tsx +++ b/src/renderer/src/pages/cherry-agent/CherryAgentPage.tsx @@ -1,30 +1,17 @@ import { useCommandHistory } from '@renderer/hooks/useCommandHistory' import { usePocCommand } from '@renderer/hooks/usePocCommand' import { usePocMessages } from '@renderer/hooks/usePocMessages' +import { useNavbarPosition } from '@renderer/hooks/useSettings' import React, { useCallback, useEffect, useState } from 'react' import styled from 'styled-components' import PocCommandInput from './components/PocCommandInput' -import PocHeader from './components/PocHeader' import PocMessageList from './components/PocMessageList' import PocStatusBar from './components/PocStatusBar' -const PageContainer = styled.div` - display: flex; - flex-direction: column; - height: 100vh; - width: 100%; - background: var(--color-background); -` +const CherryAgentPage: React.FC = () => { + const { isLeftNavbar } = useNavbarPosition() -const ContentArea = styled.div` - flex: 1; - display: flex; - flex-direction: column; - overflow: hidden; -` - -const CommandPocPage: React.FC = () => { // Initialize hooks const messagesHook = usePocMessages() const commandHook = usePocCommand() @@ -32,7 +19,7 @@ const CommandPocPage: React.FC = () => { // Local state for command count tracking const [commandCount, setCommandCount] = useState(0) - const [currentWorkingDirectory] = useState(process.cwd()) + const [currentWorkingDirectory] = useState('/Users/weliu') // Handle command execution const handleExecuteCommand = useCallback( @@ -79,19 +66,55 @@ const CommandPocPage: React.FC = () => { }, [commandHook]) return ( - - - - - - + {/*{isLeftNavbar && ( + - - + )}*/} + + + + + + + + ) } -export default CommandPocPage +const Container = styled.div` + display: flex; + flex: 1; + flex-direction: column; + [navbar-position='left'] & { + max-width: calc(100vw - var(--sidebar-width)); + } + [navbar-position='top'] & { + max-width: 100vw; + } +` + +const ContentContainer = styled.div` + display: flex; + flex: 1; + flex-direction: row; + overflow: hidden; +` + +const ContentArea = styled.div` + flex: 1; + display: flex; + flex-direction: column; + overflow: hidden; +` + +export default CherryAgentPage diff --git a/src/renderer/src/pages/command-poc/components/PocCommandInput.tsx b/src/renderer/src/pages/cherry-agent/components/PocCommandInput.tsx similarity index 94% rename from src/renderer/src/pages/command-poc/components/PocCommandInput.tsx rename to src/renderer/src/pages/cherry-agent/components/PocCommandInput.tsx index e38c0bce9..d60d9f6a9 100644 --- a/src/renderer/src/pages/command-poc/components/PocCommandInput.tsx +++ b/src/renderer/src/pages/cherry-agent/components/PocCommandInput.tsx @@ -1,8 +1,7 @@ +import { useCommandHistory } from '@renderer/hooks/useCommandHistory' import React, { KeyboardEvent, useCallback, useState } from 'react' import styled from 'styled-components' -import { useCommandHistory } from '@renderer/hooks/useCommandHistory' - const InputContainer = styled.div` display: flex; padding: 16px; @@ -74,15 +73,11 @@ interface PocCommandInputProps { commandHistory?: ReturnType } -const PocCommandInput: React.FC = ({ - onSendCommand = () => {}, - disabled = false, - commandHistory -}) => { +const PocCommandInput: React.FC = ({ onSendCommand = () => {}, disabled = false }) => { const [input, setInput] = useState('') - + // Use the provided command history or create a default one - const history = commandHistory || useCommandHistory() + const history = useCommandHistory() const handleSend = useCallback(() => { const trimmedInput = input.trim() @@ -115,7 +110,7 @@ const PocCommandInput: React.FC = ({ (e: React.ChangeEvent) => { const newValue = e.target.value setInput(newValue) - + // Reset navigation if user starts typing and is not navigating if (!history.isNavigating) { history.resetNavigation() diff --git a/src/renderer/src/pages/command-poc/components/PocHeader.tsx b/src/renderer/src/pages/cherry-agent/components/PocHeader.tsx similarity index 100% rename from src/renderer/src/pages/command-poc/components/PocHeader.tsx rename to src/renderer/src/pages/cherry-agent/components/PocHeader.tsx diff --git a/src/renderer/src/pages/command-poc/components/PocMessageBubble.tsx b/src/renderer/src/pages/cherry-agent/components/PocMessageBubble.tsx similarity index 98% rename from src/renderer/src/pages/command-poc/components/PocMessageBubble.tsx rename to src/renderer/src/pages/cherry-agent/components/PocMessageBubble.tsx index 699fd0ec1..c19fec485 100644 --- a/src/renderer/src/pages/command-poc/components/PocMessageBubble.tsx +++ b/src/renderer/src/pages/cherry-agent/components/PocMessageBubble.tsx @@ -1,8 +1,7 @@ +import { PocMessage } from '@types' import React from 'react' import styled from 'styled-components' -import { PocMessage } from '../types' - const MessageContainer = styled.div<{ $isUser: boolean }>` display: flex; justify-content: ${(props) => (props.$isUser ? 'flex-end' : 'flex-start')}; diff --git a/src/renderer/src/pages/command-poc/components/PocMessageList.tsx b/src/renderer/src/pages/cherry-agent/components/PocMessageList.tsx similarity index 98% rename from src/renderer/src/pages/command-poc/components/PocMessageList.tsx rename to src/renderer/src/pages/cherry-agent/components/PocMessageList.tsx index ee1c6fa4d..85b9dae2a 100644 --- a/src/renderer/src/pages/command-poc/components/PocMessageList.tsx +++ b/src/renderer/src/pages/cherry-agent/components/PocMessageList.tsx @@ -1,7 +1,7 @@ +import { PocMessage } from '@types' import React, { useEffect, useRef } from 'react' import styled from 'styled-components' -import { PocMessage } from '../types' import PocMessageBubble from './PocMessageBubble' const MessageContainer = styled.div` diff --git a/src/renderer/src/pages/command-poc/components/PocStatusBar.tsx b/src/renderer/src/pages/cherry-agent/components/PocStatusBar.tsx similarity index 100% rename from src/renderer/src/pages/command-poc/components/PocStatusBar.tsx rename to src/renderer/src/pages/cherry-agent/components/PocStatusBar.tsx diff --git a/src/renderer/src/pages/settings/DisplaySettings/SidebarIconsManager.tsx b/src/renderer/src/pages/settings/DisplaySettings/SidebarIconsManager.tsx index c19fabc70..b6af67527 100644 --- a/src/renderer/src/pages/settings/DisplaySettings/SidebarIconsManager.tsx +++ b/src/renderer/src/pages/settings/DisplaySettings/SidebarIconsManager.tsx @@ -116,7 +116,8 @@ const SidebarIconsManager: FC = ({ translate: , minapp: , knowledge: , - files: + files: , + cherryAgent: }), [] ) @@ -214,7 +215,7 @@ const IconList = styled.div` border: 1px solid var(--color-border); display: flex; flex-direction: column; - overflow-y: hidden; + overflow-y: auto; ` const IconItem = styled.div` diff --git a/src/renderer/src/services/AgentCommandService.ts b/src/renderer/src/services/AgentCommandService.ts index c10491b78..5d50fc05d 100644 --- a/src/renderer/src/services/AgentCommandService.ts +++ b/src/renderer/src/services/AgentCommandService.ts @@ -1,9 +1,8 @@ import { loggerService } from '@logger' import { IpcChannel } from '@shared/IpcChannel' +import { PocCommandExecution, PocCommandOutput, PocExecuteCommandRequest } from '@types' import Emittery from 'emittery' -import { PocCommandExecution, PocCommandOutput, PocExecuteCommandRequest } from '../pages/command-poc/types' - const logger = loggerService.withContext('AgentCommandService') /** @@ -53,6 +52,12 @@ export class AgentCommandService { return } + // Check if we're running in Electron context + if (!window.electron?.ipcRenderer) { + logger.warn('Not running in Electron context, skipping IPC listener setup') + return + } + // Listen for command output from main process this.outputListenerRemover = window.electron.ipcRenderer.on( IpcChannel.Poc_CommandOutput, @@ -104,6 +109,13 @@ export class AgentCommandService { * @returns Promise that resolves when command starts execution */ public async executeCommand(command: string, workingDirectory: string = process.cwd()): Promise { + // Check if we're running in Electron context + if (!window.api?.poc?.executeCommand) { + const errorMessage = 'Not running in Electron context - command execution unavailable' + logger.warn(errorMessage) + throw new Error(errorMessage) + } + const commandId = `cmd_${Date.now()}_${Math.random().toString(36).substr(2, 9)}` logger.info('Executing command', { @@ -154,6 +166,12 @@ export class AgentCommandService { * @returns Promise that resolves to true if interrupted successfully */ public async interruptCommand(commandId: string): Promise { + // Check if we're running in Electron context + if (!window.api?.poc?.interruptCommand) { + logger.warn('Not running in Electron context - command interruption unavailable') + return false + } + logger.info('Interrupting command', { commandId }) try { @@ -272,6 +290,12 @@ export class AgentCommandService { * @returns Promise that resolves to array of active processes */ public async getActiveProcesses(): Promise { + // Check if we're running in Electron context + if (!window.api?.poc?.getActiveProcesses) { + logger.warn('Not running in Electron context - cannot get active processes') + return [] + } + try { return await window.api.poc.getActiveProcesses() } catch (error) { diff --git a/src/renderer/src/store/settings.ts b/src/renderer/src/store/settings.ts index 62437cbbc..fbb709cd0 100644 --- a/src/renderer/src/store/settings.ts +++ b/src/renderer/src/store/settings.ts @@ -20,7 +20,15 @@ import { RemoteSyncState } from './backup' export type SendMessageShortcut = 'Enter' | 'Shift+Enter' | 'Ctrl+Enter' | 'Command+Enter' | 'Alt+Enter' -export type SidebarIcon = 'assistants' | 'agents' | 'paintings' | 'translate' | 'minapp' | 'knowledge' | 'files' +export type SidebarIcon = + | 'assistants' + | 'agents' + | 'paintings' + | 'translate' + | 'minapp' + | 'knowledge' + | 'files' + | 'cherryAgent' export const DEFAULT_SIDEBAR_ICONS: SidebarIcon[] = [ 'assistants', @@ -29,7 +37,8 @@ export const DEFAULT_SIDEBAR_ICONS: SidebarIcon[] = [ 'translate', 'minapp', 'knowledge', - 'files' + 'files', + 'cherryAgent' ] export interface NutstoreSyncRuntime extends RemoteSyncState {} diff --git a/src/renderer/src/pages/command-poc/types.ts b/src/renderer/src/types/cherryAgent.ts similarity index 100% rename from src/renderer/src/pages/command-poc/types.ts rename to src/renderer/src/types/cherryAgent.ts diff --git a/src/renderer/src/types/index.ts b/src/renderer/src/types/index.ts index d2ee286be..f8f7992cc 100644 --- a/src/renderer/src/types/index.ts +++ b/src/renderer/src/types/index.ts @@ -7,6 +7,7 @@ import * as z from 'zod/v4' export * from './file' import type { FileMetadata } from './file' import type { Message } from './newMessage' +export * from './cherryAgent' export type Assistant = { id: string