System / Project Objective:
Browse filesYou are an autonomous developer assistant. Build a fully-functional developer product: "AgentIDE" β a VSCode-like environment (web and optional desktop via Electron) with a built-in AI agent that helps with code, file editing, running, debugging, and project management. Deliver a runnable repo, documentation, and demo. Follow the specifications and acceptance tests below.
High-level requirements:
1. UI:
- Project explorer (tree) with create/rename/delete files & folders.
- Monaco (or CodeMirror) editor with syntax highlighting, multi-language support, tabs, and file tabs.
- Integrated terminal (websocket to backend).
- Side panels: File explorer, Git/status, Extensions, AI Chat (agent), Settings.
- Top toolbar: Run, Debug, New File, Open Folder, Save, Undo/Redo.
- Drag-and-drop file upload, file preview (images, markdown, JSON).
- Responsive layout for desktop & tablet; optional Electron packaging for desktop.
2. Backend:
- Node.js + Express (or Fastify) server with WebSocket support (socket.io or ws) for real-time collaboration & terminal streams.
- File I/O API with strict sandboxing: each project runs inside a sandboxed workspace directory.
- Optional containerized runner (Docker) or use a lightweight in-process sandbox for running user code safely.
- Language Server Protocol (LSP) support integration for code intelligence (start with JS/TS, Python).
3. AI Agent:
- Chat panel that can:
* Read project files (up to limits), summarize the repo structure.
* Open specific files on request, suggest edits, refactors, and generate tests.
* Create/modify files when asked; produce diffs and preview changes before applying.
* Run tests/commands by invoking backend endpoints and show results.
- Agent must respect a safe execution policy: ask for explicit confirmation before running destructive operations (delete files, run privileged commands).
- Provide code actions: explain bugs, propose fixes, create unit tests, create README, generate commit messages.
4. Git integration:
- Basic commit, branch, diff, and push/pull (use simple local git or isomorphic-git). Provide UI for staging files and committing.
5. Security & Privacy:
- All code execution occurs in a sandbox. Warn user about remote AI models sending code externally.
- Authentication optional: provide a simple local auth flow (username/password) for demo mode.
6. Extensibility:
- Plugin/extension API skeleton so later we can add language support or formatters.
Deliverables:
1. Full source repo with clear README and setup scripts (`npm install`, `npm run dev`, `npm run build`).
2. Demo data / example project.
3. Design notes: key components, folder structure, decision rationale.
4. Automated tests: basic unit tests and end-to-end smoke test ensuring editor loads, files can be created/saved, agent can read a file, and run a sample command.
Technical choices (recommended but allow alternatives):
- Frontend: React + Vite (or Next.js) + Monaco Editor.
- State: Zustand or Redux.
- Styling: TailwindCSS.
- Backend: Node.js + Express + socket.io.
- LSP: vscode-languageclient or start with language servers via `vscode-ws-jsonrpc`.
- Sandbox for execution: Docker containers per-run OR use `node:vm2` for JS and Docker for other languages.
- Storage: local filesystem for demo; option to add cloud later.
- AI integration: use an LLM API (configurable) β but implement an adapter/abstraction so the project works with OpenAI, Anthropic, or local LLMs.
Acceptance criteria / tests:
- The app opens a project, shows files in explorer, opens files in Monaco tabs, edits and saves to disk.
- The AI Chat can be given the instruction: "Summarize this repo" and return a structured summary within 30 seconds.
- The AI Chat can suggest a code change, show a diff, and after confirmation apply it to the workspace.
- Running `npm run test` in example project through the integrated terminal returns expected output.
- Git: user can stage a changed file, create a commit with message generated by the AI agent.
UX & Prompts for the AI Agent (how agent should behave):
- System prompt for agent:
"You are AgentIDE: a development assistant. You have read-only access to the repo files unless the user permits edits. When asked to make changes: (1) propose a short summary of changes, (2) show a unified diff, (3) ask for confirmation, (4) apply the changes upon confirmation. Always prioritize safe operations. When running code, clearly display the command and ask for permission before executing."
- Example user queries to implement:
* "Explain the project's structure and main entry points."
* "Create unit tests for file X using Jest."
* "Find a bug in file Y and propose a fix."
* "Refactor function Z to be asynchronous and add error handling."
Dev tasks (milestones):
1. MVP frontend: Monaco editor, explorer, open/save files.
2. Backend file APIs + terminal websocket.
3. AI Chat read-only: summarize files and propose edits (no apply).
4. AI apply-edits workflow (show diff -> confirm -> apply).
5. Git basics.
6. Packaging + docs + tests.
Constraints:
- Keep architecture modular.
- Make AI calls via an adapter so keys/configs are not hard-coded.
- Implement user confirmation for any write or run actions.
Output format for the developer:
- Provide a Git repo skeleton with `packages/` and `apps/` if monorepo, or a simple single-repo layout.
- Include `README.md`, `CONTRIBUTING.md`, and a simple `LICENSE`.
End of prompt.
- README.md +8 -5
- components/footer.js +165 -0
- components/hero.js +132 -0
- components/navbar.js +171 -0
- index.html +121 -18
- package.json +32 -0
- script.js +77 -0
- server.js +283 -0
- style.css +35 -18
- tests/smoke-test.js +46 -0
|
@@ -1,10 +1,13 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
sdk: static
|
| 7 |
pinned: false
|
|
|
|
|
|
|
| 8 |
---
|
| 9 |
|
| 10 |
-
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: AgentIDE π
|
| 3 |
+
colorFrom: blue
|
| 4 |
+
colorTo: purple
|
| 5 |
+
emoji: π³
|
| 6 |
sdk: static
|
| 7 |
pinned: false
|
| 8 |
+
tags:
|
| 9 |
+
- deepsite-v3
|
| 10 |
---
|
| 11 |
|
| 12 |
+
# Welcome to your new DeepSite project!
|
| 13 |
+
This project was created with [DeepSite](https://huggingface.co/deepsite).
|
|
@@ -0,0 +1,165 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
class Footer extends HTMLElement {
|
| 2 |
+
connectedCallback() {
|
| 3 |
+
this.attachShadow({ mode: 'open' });
|
| 4 |
+
|
| 5 |
+
const styles = `
|
| 6 |
+
<style>
|
| 7 |
+
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap');
|
| 8 |
+
|
| 9 |
+
:host {
|
| 10 |
+
display: block;
|
| 11 |
+
background-color: #0f172a;
|
| 12 |
+
color: #94a3b8;
|
| 13 |
+
padding: 4rem 1.5rem 2rem 1.5rem;
|
| 14 |
+
margin-top: 4rem;
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
.container {
|
| 18 |
+
max-width: 1280px;
|
| 19 |
+
margin: 0 auto;
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
.grid {
|
| 23 |
+
display: grid;
|
| 24 |
+
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
| 25 |
+
gap: 3rem;
|
| 26 |
+
margin-bottom: 3rem;
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
.brand h3 {
|
| 30 |
+
color: white;
|
| 31 |
+
font-family: 'Inter', sans-serif;
|
| 32 |
+
font-size: 1.5rem;
|
| 33 |
+
font-weight: 800;
|
| 34 |
+
margin: 0 0 1rem 0;
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
.brand span {
|
| 38 |
+
color: #4f46e5;
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
.brand p {
|
| 42 |
+
line-height: 1.6;
|
| 43 |
+
font-size: 0.95rem;
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
.col h4 {
|
| 47 |
+
color: white;
|
| 48 |
+
font-family: 'Inter', sans-serif;
|
| 49 |
+
font-size: 1rem;
|
| 50 |
+
font-weight: 600;
|
| 51 |
+
margin: 0 0 1.25rem 0;
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
.col ul {
|
| 55 |
+
list-style: none;
|
| 56 |
+
padding: 0;
|
| 57 |
+
margin: 0;
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
.col li {
|
| 61 |
+
margin-bottom: 0.75rem;
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
.col a {
|
| 65 |
+
color: #94a3b8;
|
| 66 |
+
text-decoration: none;
|
| 67 |
+
font-size: 0.9rem;
|
| 68 |
+
transition: color 0.2s;
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
.col a:hover {
|
| 72 |
+
color: #4f46e5;
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
.bottom {
|
| 76 |
+
border-top: 1px solid #1e293b;
|
| 77 |
+
padding-top: 2rem;
|
| 78 |
+
display: flex;
|
| 79 |
+
flex-direction: column;
|
| 80 |
+
align-items: center;
|
| 81 |
+
gap: 1rem;
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
@media (min-width: 768px) {
|
| 85 |
+
.bottom {
|
| 86 |
+
flex-direction: row;
|
| 87 |
+
justify-content: space-between;
|
| 88 |
+
}
|
| 89 |
+
}
|
| 90 |
+
|
| 91 |
+
.socials {
|
| 92 |
+
display: flex;
|
| 93 |
+
gap: 1rem;
|
| 94 |
+
}
|
| 95 |
+
|
| 96 |
+
.socials a {
|
| 97 |
+
color: #94a3b8;
|
| 98 |
+
transition: color 0.2s;
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
.socials a:hover {
|
| 102 |
+
color: white;
|
| 103 |
+
}
|
| 104 |
+
</style>
|
| 105 |
+
`;
|
| 106 |
+
|
| 107 |
+
this.shadowRoot.innerHTML = `
|
| 108 |
+
${styles}
|
| 109 |
+
<div class="container">
|
| 110 |
+
<div class="grid">
|
| 111 |
+
<div class="brand">
|
| 112 |
+
<h3>Nebula<span>Nexus</span></h3>
|
| 113 |
+
<p>Making the web a better place, one pixel at a time. Join us in the journey to digital perfection.</p>
|
| 114 |
+
</div>
|
| 115 |
+
|
| 116 |
+
<div class="col">
|
| 117 |
+
<h4>Product</h4>
|
| 118 |
+
<ul>
|
| 119 |
+
<li><a href="#">Features</a></li>
|
| 120 |
+
<li><a href="#">Integrations</a></li>
|
| 121 |
+
<li><a href="#">Pricing</a></li>
|
| 122 |
+
<li><a href="#">Changelog</a></li>
|
| 123 |
+
</ul>
|
| 124 |
+
</div>
|
| 125 |
+
|
| 126 |
+
<div class="col">
|
| 127 |
+
<h4>Company</h4>
|
| 128 |
+
<ul>
|
| 129 |
+
<li><a href="#">About Us</a></li>
|
| 130 |
+
<li><a href="#">Careers</a></li>
|
| 131 |
+
<li><a href="#">Blog</a></li>
|
| 132 |
+
<li><a href="#">Contact</a></li>
|
| 133 |
+
</ul>
|
| 134 |
+
</div>
|
| 135 |
+
|
| 136 |
+
<div class="col">
|
| 137 |
+
<h4>Legal</h4>
|
| 138 |
+
<ul>
|
| 139 |
+
<li><a href="#">Privacy Policy</a></li>
|
| 140 |
+
<li><a href="#">Terms of Service</a></li>
|
| 141 |
+
<li><a href="#">Cookie Policy</a></li>
|
| 142 |
+
</ul>
|
| 143 |
+
</div>
|
| 144 |
+
</div>
|
| 145 |
+
|
| 146 |
+
<div class="bottom">
|
| 147 |
+
<p>© 2023 Nebula Nexus Inc. All rights reserved.</p>
|
| 148 |
+
<div class="socials">
|
| 149 |
+
<a href="#">
|
| 150 |
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M23 3a10.9 10.9 0 0 1-3.14 1.53 4.48 4.48 0 0 0-7.86 3v1A10.66 10.66 0 0 1 3 4s-4 9 5 13a11.64 11.64 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0-.08-.83A7.72 7.72 0 0 0 23 3z"></path></svg>
|
| 151 |
+
</a>
|
| 152 |
+
<a href="#">
|
| 153 |
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"></path><rect x="2" y="9" width="4" height="12"></rect><circle cx="4" cy="4" r="2"></circle></svg>
|
| 154 |
+
</a>
|
| 155 |
+
<a href="#">
|
| 156 |
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path></svg>
|
| 157 |
+
</a>
|
| 158 |
+
</div>
|
| 159 |
+
</div>
|
| 160 |
+
</div>
|
| 161 |
+
`;
|
| 162 |
+
}
|
| 163 |
+
}
|
| 164 |
+
|
| 165 |
+
customElements.define('app-footer', Footer);
|
|
@@ -0,0 +1,132 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
class Hero extends HTMLElement {
|
| 2 |
+
connectedCallback() {
|
| 3 |
+
this.attachShadow({ mode: 'open' });
|
| 4 |
+
|
| 5 |
+
const styles = `
|
| 6 |
+
<style>
|
| 7 |
+
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;800;900&display=swap');
|
| 8 |
+
|
| 9 |
+
:host {
|
| 10 |
+
display: block;
|
| 11 |
+
padding: 5rem 1.5rem;
|
| 12 |
+
max-width: 1280px;
|
| 13 |
+
margin: 0 auto;
|
| 14 |
+
text-align: center;
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
.badge {
|
| 18 |
+
display: inline-flex;
|
| 19 |
+
align-items: center;
|
| 20 |
+
gap: 0.5rem;
|
| 21 |
+
background-color: #e0e7ff;
|
| 22 |
+
color: #4338ca;
|
| 23 |
+
padding: 0.5rem 1rem;
|
| 24 |
+
border-radius: 9999px;
|
| 25 |
+
font-size: 0.875rem;
|
| 26 |
+
font-weight: 600;
|
| 27 |
+
margin-bottom: 1.5rem;
|
| 28 |
+
}
|
| 29 |
+
|
| 30 |
+
h1 {
|
| 31 |
+
font-family: 'Inter', sans-serif;
|
| 32 |
+
font-size: 3.5rem;
|
| 33 |
+
font-weight: 900;
|
| 34 |
+
line-height: 1.1;
|
| 35 |
+
color: #0f172a;
|
| 36 |
+
margin: 0 0 1.5rem 0;
|
| 37 |
+
letter-spacing: -0.025em;
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
h1 span {
|
| 41 |
+
background: linear-gradient(135deg, #4f46e5 0%, #14b8a6 100%);
|
| 42 |
+
-webkit-background-clip: text;
|
| 43 |
+
-webkit-text-fill-color: transparent;
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
p {
|
| 47 |
+
font-family: 'Inter', sans-serif;
|
| 48 |
+
font-size: 1.25rem;
|
| 49 |
+
color: #64748b;
|
| 50 |
+
max-width: 700px;
|
| 51 |
+
margin: 0 auto 2.5rem auto;
|
| 52 |
+
line-height: 1.6;
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
.actions {
|
| 56 |
+
display: flex;
|
| 57 |
+
justify-content: center;
|
| 58 |
+
gap: 1rem;
|
| 59 |
+
flex-wrap: wrap;
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
.btn {
|
| 63 |
+
padding: 1rem 2rem;
|
| 64 |
+
border-radius: 0.75rem;
|
| 65 |
+
font-family: 'Inter', sans-serif;
|
| 66 |
+
font-weight: 600;
|
| 67 |
+
font-size: 1rem;
|
| 68 |
+
text-decoration: none;
|
| 69 |
+
transition: all 0.2s;
|
| 70 |
+
display: inline-flex;
|
| 71 |
+
align-items: center;
|
| 72 |
+
gap: 0.5rem;
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
.btn-primary {
|
| 76 |
+
background-color: #4f46e5;
|
| 77 |
+
color: white;
|
| 78 |
+
box-shadow: 0 4px 6px -1px rgba(79, 70, 229, 0.2);
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
.btn-primary:hover {
|
| 82 |
+
background-color: #4338ca;
|
| 83 |
+
transform: translateY(-2px);
|
| 84 |
+
box-shadow: 0 10px 15px -3px rgba(79, 70, 229, 0.3);
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
.btn-secondary {
|
| 88 |
+
background-color: white;
|
| 89 |
+
color: #0f172a;
|
| 90 |
+
border: 1px solid #e2e8f0;
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
.btn-secondary:hover {
|
| 94 |
+
background-color: #f8fafc;
|
| 95 |
+
border-color: #cbd5e1;
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
@media (max-width: 768px) {
|
| 99 |
+
h1 {
|
| 100 |
+
font-size: 2.5rem;
|
| 101 |
+
}
|
| 102 |
+
p {
|
| 103 |
+
font-size: 1.1rem;
|
| 104 |
+
}
|
| 105 |
+
}
|
| 106 |
+
</style>
|
| 107 |
+
`;
|
| 108 |
+
|
| 109 |
+
this.shadowRoot.innerHTML = `
|
| 110 |
+
${styles}
|
| 111 |
+
<div class="badge">
|
| 112 |
+
<span style="width: 8px; height: 8px; background: #14b8a6; border-radius: 50%;"></span>
|
| 113 |
+
v2.0 is now live
|
| 114 |
+
</div>
|
| 115 |
+
<h1>Crafting Digital <br><span>Excellence</span> for Everyone</h1>
|
| 116 |
+
<p>Build stunning websites and applications with our next-generation platform. Fast, secure, and infinitely scalable for your ambitions.</p>
|
| 117 |
+
|
| 118 |
+
<div class="actions">
|
| 119 |
+
<a href="#" class="btn btn-primary">
|
| 120 |
+
Start Building Free
|
| 121 |
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg>
|
| 122 |
+
</a>
|
| 123 |
+
<a href="#" class="btn btn-secondary">
|
| 124 |
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="5 3 19 12 5 21 5 3"></polygon></svg>
|
| 125 |
+
Watch Demo
|
| 126 |
+
</a>
|
| 127 |
+
</div>
|
| 128 |
+
`;
|
| 129 |
+
}
|
| 130 |
+
}
|
| 131 |
+
|
| 132 |
+
customElements.define('app-hero', Hero);
|
|
@@ -0,0 +1,171 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
class Navbar extends HTMLElement {
|
| 2 |
+
constructor() {
|
| 3 |
+
super();
|
| 4 |
+
}
|
| 5 |
+
|
| 6 |
+
connectedCallback() {
|
| 7 |
+
this.attachShadow({ mode: 'open' });
|
| 8 |
+
|
| 9 |
+
// Styles are internal to Shadow DOM for encapsulation.
|
| 10 |
+
// We mimic Tailwind's utility classes with standard CSS.
|
| 11 |
+
const styles = `
|
| 12 |
+
<style>
|
| 13 |
+
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap');
|
| 14 |
+
|
| 15 |
+
:host {
|
| 16 |
+
display: block;
|
| 17 |
+
position: fixed;
|
| 18 |
+
top: 0;
|
| 19 |
+
left: 0;
|
| 20 |
+
right: 0;
|
| 21 |
+
z-index: 50;
|
| 22 |
+
background: rgba(255, 255, 255, 0.85);
|
| 23 |
+
backdrop-filter: blur(12px);
|
| 24 |
+
-webkit-backdrop-filter: blur(12px);
|
| 25 |
+
border-bottom: 1px solid rgba(0,0,0,0.05);
|
| 26 |
+
height: 70px;
|
| 27 |
+
display: flex;
|
| 28 |
+
align-items: center;
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
.container {
|
| 32 |
+
max-width: 1280px;
|
| 33 |
+
width: 100%;
|
| 34 |
+
margin: 0 auto;
|
| 35 |
+
padding: 0 1.5rem;
|
| 36 |
+
display: flex;
|
| 37 |
+
justify-content: space-between;
|
| 38 |
+
align-items: center;
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
.logo {
|
| 42 |
+
font-family: 'Inter', sans-serif;
|
| 43 |
+
font-weight: 800;
|
| 44 |
+
font-size: 1.5rem;
|
| 45 |
+
color: #0f172a;
|
| 46 |
+
text-decoration: none;
|
| 47 |
+
display: flex;
|
| 48 |
+
align-items: center;
|
| 49 |
+
gap: 0.5rem;
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
.logo span {
|
| 53 |
+
color: #4f46e5; /* Primary Color */
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
.nav-links {
|
| 57 |
+
display: flex;
|
| 58 |
+
gap: 2rem;
|
| 59 |
+
list-style: none;
|
| 60 |
+
margin: 0;
|
| 61 |
+
padding: 0;
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
.nav-links a {
|
| 65 |
+
text-decoration: none;
|
| 66 |
+
color: #475569;
|
| 67 |
+
font-family: 'Inter', sans-serif;
|
| 68 |
+
font-weight: 500;
|
| 69 |
+
font-size: 0.95rem;
|
| 70 |
+
transition: color 0.2s;
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
.nav-links a:hover {
|
| 74 |
+
color: #4f46e5;
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
.btn-primary {
|
| 78 |
+
background-color: #4f46e5;
|
| 79 |
+
color: white;
|
| 80 |
+
padding: 0.6rem 1.25rem;
|
| 81 |
+
border-radius: 0.5rem;
|
| 82 |
+
text-decoration: none;
|
| 83 |
+
font-family: 'Inter', sans-serif;
|
| 84 |
+
font-weight: 600;
|
| 85 |
+
font-size: 0.9rem;
|
| 86 |
+
transition: background-color 0.2s;
|
| 87 |
+
display: inline-flex;
|
| 88 |
+
align-items: center;
|
| 89 |
+
gap: 0.5rem;
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
.btn-primary:hover {
|
| 93 |
+
background-color: #4338ca;
|
| 94 |
+
}
|
| 95 |
+
|
| 96 |
+
.menu-toggle {
|
| 97 |
+
display: none;
|
| 98 |
+
background: none;
|
| 99 |
+
border: none;
|
| 100 |
+
cursor: pointer;
|
| 101 |
+
color: #334155;
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
@media (max-width: 768px) {
|
| 105 |
+
.nav-links {
|
| 106 |
+
display: none;
|
| 107 |
+
position: absolute;
|
| 108 |
+
top: 70px;
|
| 109 |
+
left: 0;
|
| 110 |
+
right: 0;
|
| 111 |
+
background: white;
|
| 112 |
+
flex-direction: column;
|
| 113 |
+
padding: 2rem;
|
| 114 |
+
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
|
| 115 |
+
text-align: center;
|
| 116 |
+
}
|
| 117 |
+
|
| 118 |
+
.nav-links.active {
|
| 119 |
+
display: flex;
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
.menu-toggle {
|
| 123 |
+
display: block;
|
| 124 |
+
}
|
| 125 |
+
|
| 126 |
+
.desktop-cta {
|
| 127 |
+
display: none;
|
| 128 |
+
}
|
| 129 |
+
}
|
| 130 |
+
</style>
|
| 131 |
+
`;
|
| 132 |
+
|
| 133 |
+
this.shadowRoot.innerHTML = `
|
| 134 |
+
${styles}
|
| 135 |
+
<nav class="container">
|
| 136 |
+
<a href="#" class="logo">
|
| 137 |
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#4f46e5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><polygon points="16.24 7.76 14.12 14.12 7.76 16.24 9.88 9.88 16.24 7.76"></polygon></svg>
|
| 138 |
+
Nebula<span>Nexus</span>
|
| 139 |
+
</a>
|
| 140 |
+
|
| 141 |
+
<button class="menu-toggle">
|
| 142 |
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line></svg>
|
| 143 |
+
</button>
|
| 144 |
+
|
| 145 |
+
<ul class="nav-links">
|
| 146 |
+
<li><a href="#">Features</a></li>
|
| 147 |
+
<li><a href="#">Solutions</a></li>
|
| 148 |
+
<li><a href="#">Resources</a></li>
|
| 149 |
+
<li><a href="#">Pricing</a></li>
|
| 150 |
+
</ul>
|
| 151 |
+
|
| 152 |
+
<div class="desktop-cta">
|
| 153 |
+
<a href="#" class="btn-primary">
|
| 154 |
+
Get Started
|
| 155 |
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg>
|
| 156 |
+
</a>
|
| 157 |
+
</div>
|
| 158 |
+
</nav>
|
| 159 |
+
`;
|
| 160 |
+
|
| 161 |
+
// Mobile Menu Logic
|
| 162 |
+
const toggleBtn = this.shadowRoot.querySelector('.menu-toggle');
|
| 163 |
+
const navLinks = this.shadowRoot.querySelector('.nav-links');
|
| 164 |
+
|
| 165 |
+
toggleBtn.addEventListener('click', () => {
|
| 166 |
+
navLinks.classList.toggle('active');
|
| 167 |
+
});
|
| 168 |
+
}
|
| 169 |
+
}
|
| 170 |
+
|
| 171 |
+
customElements.define('app-navbar', Navbar);
|
|
@@ -1,19 +1,122 @@
|
|
| 1 |
-
|
| 2 |
-
<html>
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
</html>
|
|
|
|
| 1 |
+
|
| 2 |
+
<!DOCTYPE html>
|
| 3 |
+
<html lang="en">
|
| 4 |
+
<head>
|
| 5 |
+
<meta charset="UTF-8">
|
| 6 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 7 |
+
<title>AgentIDE - AI-Powered Development Environment</title>
|
| 8 |
+
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>π</text></svg>">
|
| 9 |
+
|
| 10 |
+
<!-- Monaco Editor -->
|
| 11 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.44.0/min/vs/loader.min.js"></script>
|
| 12 |
+
|
| 13 |
+
<!-- XTerm.js for Terminal -->
|
| 14 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/xterm/5.3.0/xterm.min.css">
|
| 15 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/xterm/5.3.0/xterm.min.js"></script>
|
| 16 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/xterm/5.3.0/xterm-addon-fit.min.js"></script>
|
| 17 |
+
|
| 18 |
+
<!-- Socket.IO -->
|
| 19 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.7.2/socket.io.min.js"></script>
|
| 20 |
+
|
| 21 |
+
<!-- Feather Icons -->
|
| 22 |
+
<script src="https://unpkg.com/feather-icons"></script>
|
| 23 |
+
|
| 24 |
+
<!-- Custom Styles -->
|
| 25 |
+
<link rel="stylesheet" href="style.css">
|
| 26 |
+
|
| 27 |
+
<!-- Web Components -->
|
| 28 |
+
<script src="components/activity-bar.js"></script>
|
| 29 |
+
<script src="components/sidebar.js"></script>
|
| 30 |
+
<script src="components/editor-container.js"></script>
|
| 31 |
+
<script src="components/terminal.js"></script>
|
| 32 |
+
<script src="components/ai-chat.js"></script>
|
| 33 |
+
<script src="components/status-bar.js"></script>
|
| 34 |
+
<script src="components/toolbar.js"></script>
|
| 35 |
+
</head>
|
| 36 |
+
<body class="ide-body">
|
| 37 |
+
<!-- IDE Layout -->
|
| 38 |
+
<div id="ide-container" class="ide-container">
|
| 39 |
+
<!-- Top Toolbar -->
|
| 40 |
+
<ide-toolbar></ide-toolbar>
|
| 41 |
+
|
| 42 |
+
<!-- Main IDE Area -->
|
| 43 |
+
<div class="ide-main">
|
| 44 |
+
<!-- Activity Bar (Left icons) -->
|
| 45 |
+
<ide-activity-bar></ide-activity-bar>
|
| 46 |
+
|
| 47 |
+
<!-- Sidebar (Explorer, Search, etc.) -->
|
| 48 |
+
<ide-sidebar id="sidebar" active-panel="explorer"></ide-sidebar>
|
| 49 |
+
|
| 50 |
+
<!-- Editor Area -->
|
| 51 |
+
<div class="editor-area">
|
| 52 |
+
<!-- Tabs Container -->
|
| 53 |
+
<div id="editor-tabs" class="editor-tabs">
|
| 54 |
+
<!-- Tabs will be dynamically added -->
|
| 55 |
+
</div>
|
| 56 |
+
|
| 57 |
+
<!-- Monaco Editor Container -->
|
| 58 |
+
<div id="monaco-container" class="monaco-container"></div>
|
| 59 |
+
|
| 60 |
+
<!-- Terminal Panel -->
|
| 61 |
+
<div id="terminal-panel" class="terminal-panel hidden">
|
| 62 |
+
<ide-terminal></ide-terminal>
|
| 63 |
+
</div>
|
| 64 |
+
|
| 65 |
+
<!-- Welcome Tab (shown when no files open) -->
|
| 66 |
+
<div id="welcome-tab" class="welcome-tab">
|
| 67 |
+
<div class="welcome-content">
|
| 68 |
+
<h1>π AgentIDE</h1>
|
| 69 |
+
<p>AI-Powered Development Environment</p>
|
| 70 |
+
|
| 71 |
+
<div class="welcome-actions">
|
| 72 |
+
<button class="welcome-btn" onclick="app.createNewFile()">
|
| 73 |
+
<i data-feather="file-plus"></i>
|
| 74 |
+
New File
|
| 75 |
+
</button>
|
| 76 |
+
<button class="welcome-btn" onclick="app.openFolder()">
|
| 77 |
+
<i data-feather="folder"></i>
|
| 78 |
+
Open Folder
|
| 79 |
+
</button>
|
| 80 |
+
<button class="welcome-btn" onclick="app.toggleTerminal()">
|
| 81 |
+
<i data-feather="terminal"></i>
|
| 82 |
+
Open Terminal
|
| 83 |
+
</button>
|
| 84 |
+
<button class="welcome-btn primary" onclick="app.openAIChat()">
|
| 85 |
+
<i data-feather="message-square"></i>
|
| 86 |
+
Ask AI Agent
|
| 87 |
+
</button>
|
| 88 |
+
</div>
|
| 89 |
+
|
| 90 |
+
<div class="recent-files">
|
| 91 |
+
<h3>Recent Files</h3>
|
| 92 |
+
<div id="recent-files-list"></div>
|
| 93 |
+
</div>
|
| 94 |
+
|
| 95 |
+
<div class="quick-start">
|
| 96 |
+
<h3>Quick Start</h3>
|
| 97 |
+
<ul>
|
| 98 |
+
<li><a href="#" onclick="app.openFile('index.html')">Open index.html</a></li>
|
| 99 |
+
<li><a href="#" onclick="app.openFile('app.js')">Open app.js</a></li>
|
| 100 |
+
<li><a href="#" onclick="app.openFile('styles.css')">Open styles.css</a></li>
|
| 101 |
+
</ul>
|
| 102 |
+
</div>
|
| 103 |
+
</div>
|
| 104 |
+
</div>
|
| 105 |
+
</div>
|
| 106 |
+
|
| 107 |
+
<!-- AI Chat Panel (Right side) -->
|
| 108 |
+
<ide-chat-panel id="ai-chat-panel" class="hidden"></ide-chat-panel>
|
| 109 |
+
</div>
|
| 110 |
+
|
| 111 |
+
<!-- Status Bar -->
|
| 112 |
+
<ide-status-bar></ide-status-bar>
|
| 113 |
+
</div>
|
| 114 |
+
|
| 115 |
+
<!-- Main Application Script -->
|
| 116 |
+
<script src="script.js"></script>
|
| 117 |
+
<script>
|
| 118 |
+
feather.replace();
|
| 119 |
+
</script>
|
| 120 |
+
<script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
|
| 121 |
+
</body>
|
| 122 |
</html>
|
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
```json
|
| 2 |
+
{
|
| 3 |
+
"name": "agentide",
|
| 4 |
+
"version": "1.0.0",
|
| 5 |
+
"description": "VSCode-like IDE with built-in AI Agent",
|
| 6 |
+
"main": "server.js",
|
| 7 |
+
"scripts": {
|
| 8 |
+
"start": "node server.js",
|
| 9 |
+
"dev": "node server.js",
|
| 10 |
+
"test": "echo \"Running tests...\" && node tests/smoke-test.js"
|
| 11 |
+
},
|
| 12 |
+
"keywords": [
|
| 13 |
+
"ide",
|
| 14 |
+
"editor",
|
| 15 |
+
"ai",
|
| 16 |
+
"monaco",
|
| 17 |
+
"vscode"
|
| 18 |
+
],
|
| 19 |
+
"author": "AgentIDE Team",
|
| 20 |
+
"license": "MIT",
|
| 21 |
+
"dependencies": {
|
| 22 |
+
"express": "^4.18.2",
|
| 23 |
+
"socket.io": "^4.7.2",
|
| 24 |
+
"cors": "^2.8.5",
|
| 25 |
+
"chokidar": "^3.5.3",
|
| 26 |
+
"node-pty": "^1.0.0"
|
| 27 |
+
},
|
| 28 |
+
"devDependencies": {
|
| 29 |
+
"nodemon": "^3.0.1"
|
| 30 |
+
}
|
| 31 |
+
}
|
| 32 |
+
```
|
|
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
document.addEventListener('DOMContentLoaded', () => {
|
| 2 |
+
fetchTeamData();
|
| 3 |
+
setupEventListeners();
|
| 4 |
+
feather.replace();
|
| 5 |
+
});
|
| 6 |
+
|
| 7 |
+
// Fetch Data from Public API (RandomUser.me)
|
| 8 |
+
async function fetchTeamData() {
|
| 9 |
+
const grid = document.getElementById('team-grid');
|
| 10 |
+
const btn = document.getElementById('refresh-team');
|
| 11 |
+
|
| 12 |
+
// Add loading state visual
|
| 13 |
+
if(btn) {
|
| 14 |
+
const icon = btn.querySelector('[data-feather]');
|
| 15 |
+
if(icon) icon.classList.add('animate-spin');
|
| 16 |
+
btn.disabled = true;
|
| 17 |
+
btn.innerHTML = 'Loading...';
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
try {
|
| 21 |
+
const response = await fetch('https://randomuser.me/api/?results=4&nat=us,gb,ca,au,de');
|
| 22 |
+
const data = await response.json();
|
| 23 |
+
renderTeam(data.results);
|
| 24 |
+
} catch (error) {
|
| 25 |
+
console.error('Error fetching team:', error);
|
| 26 |
+
grid.innerHTML = `
|
| 27 |
+
<div class="col-span-full text-center text-red-500 p-8 bg-red-50 rounded-xl border border-red-100">
|
| 28 |
+
<i data-feather="alert-circle" class="inline-block mb-2"></i>
|
| 29 |
+
<p>Failed to load team data. Please try again.</p>
|
| 30 |
+
</div>
|
| 31 |
+
`;
|
| 32 |
+
feather.replace();
|
| 33 |
+
} finally {
|
| 34 |
+
// Reset button state
|
| 35 |
+
if(btn) {
|
| 36 |
+
btn.disabled = false;
|
| 37 |
+
btn.innerHTML = `<i data-feather="refresh-cw" class="w-4 h-4"></i> Refresh Team`;
|
| 38 |
+
feather.replace();
|
| 39 |
+
}
|
| 40 |
+
}
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
// Render Team Cards
|
| 44 |
+
function renderTeam(users) {
|
| 45 |
+
const grid = document.getElementById('team-grid');
|
| 46 |
+
grid.innerHTML = '';
|
| 47 |
+
|
| 48 |
+
users.forEach((user, index) => {
|
| 49 |
+
const card = document.createElement('div');
|
| 50 |
+
card.className = 'bg-white rounded-2xl p-6 shadow-sm border border-slate-100 text-center hover:shadow-md transition-all duration-300 group animate-fade-in';
|
| 51 |
+
card.style.animationDelay = `${index * 100}ms`;
|
| 52 |
+
|
| 53 |
+
card.innerHTML = `
|
| 54 |
+
<div class="relative w-24 h-24 mx-auto mb-4">
|
| 55 |
+
<img src="${user.picture.large}" alt="${user.name.first}" class="w-full h-full rounded-full object-cover ring-4 ring-indigo-50 group-hover:ring-primary transition-all">
|
| 56 |
+
<div class="absolute bottom-0 right-0 w-6 h-6 bg-green-500 border-2 border-white rounded-full"></div>
|
| 57 |
+
</div>
|
| 58 |
+
<h3 class="font-bold text-lg text-slate-800 capitalize">${user.name.first} ${user.name.last}</h3>
|
| 59 |
+
<p class="text-primary text-sm font-medium mb-3">Product Designer</p>
|
| 60 |
+
<p class="text-slate-500 text-xs mb-4">${user.location.city}, ${user.location.country}</p>
|
| 61 |
+
<div class="flex justify-center gap-3">
|
| 62 |
+
<a href="#" class="text-slate-400 hover:text-blue-500 transition-colors"><i data-feather="linkedin" class="w-4 h-4"></i></a>
|
| 63 |
+
<a href="#" class="text-slate-400 hover:text-gray-800 transition-colors"><i data-feather="github" class="w-4 h-4"></i></a>
|
| 64 |
+
<a href="#" class="text-slate-400 hover:text-blue-400 transition-colors"><i data-feather="twitter" class="w-4 h-4"></i></a>
|
| 65 |
+
</div>
|
| 66 |
+
`;
|
| 67 |
+
grid.appendChild(card);
|
| 68 |
+
});
|
| 69 |
+
feather.replace();
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
function setupEventListeners() {
|
| 73 |
+
const refreshBtn = document.getElementById('refresh-team');
|
| 74 |
+
if (refreshBtn) {
|
| 75 |
+
refreshBtn.addEventListener('click', fetchTeamData);
|
| 76 |
+
}
|
| 77 |
+
}
|
|
@@ -0,0 +1,283 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const express = require('express');
|
| 2 |
+
const http = require('http');
|
| 3 |
+
const { Server } = require('socket.io');
|
| 4 |
+
const cors = require('cors');
|
| 5 |
+
const fs = require('fs').promises;
|
| 6 |
+
const path = require('path');
|
| 7 |
+
const { exec } = require('child_process');
|
| 8 |
+
|
| 9 |
+
const app = express();
|
| 10 |
+
app.use(cors());
|
| 11 |
+
app.use(express.json());
|
| 12 |
+
|
| 13 |
+
// Create a workspace directory
|
| 14 |
+
const WORKSPACE_DIR = path.join(__dirname, 'workspace');
|
| 15 |
+
async function ensureWorkspace() {
|
| 16 |
+
try {
|
| 17 |
+
await fs.access(WORKSPACE_DIR);
|
| 18 |
+
} catch {
|
| 19 |
+
await fs.mkdir(WORKSPACE_DIR, { recursive: true });
|
| 20 |
+
// Create demo files
|
| 21 |
+
await fs.writeFile(
|
| 22 |
+
path.join(WORKSPACE_DIR, 'index.html'),
|
| 23 |
+
`<!DOCTYPE html>
|
| 24 |
+
<html lang="en">
|
| 25 |
+
<head>
|
| 26 |
+
<meta charset="UTF-8">
|
| 27 |
+
<title>Demo App</title>
|
| 28 |
+
</head>
|
| 29 |
+
<body>
|
| 30 |
+
<h1>Hello AgentIDE!</h1>
|
| 31 |
+
<p>This is a sample project.</p>
|
| 32 |
+
</body>
|
| 33 |
+
</html>`
|
| 34 |
+
);
|
| 35 |
+
await fs.writeFile(
|
| 36 |
+
path.join(WORKSPACE_DIR, 'app.js'),
|
| 37 |
+
`// Main application file
|
| 38 |
+
console.log('AgentIDE demo app starting...');
|
| 39 |
+
|
| 40 |
+
function greet(name) {
|
| 41 |
+
return \`Hello, \${name}!\`;
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
const result = greet('World');
|
| 45 |
+
console.log(result);`
|
| 46 |
+
);
|
| 47 |
+
await fs.writeFile(
|
| 48 |
+
path.join(WORKSPACE_DIR, 'styles.css'),
|
| 49 |
+
`/* Demo styles */
|
| 50 |
+
body {
|
| 51 |
+
font-family: Arial, sans-serif;
|
| 52 |
+
margin: 0;
|
| 53 |
+
padding: 20px;
|
| 54 |
+
background: #1e1e1e;
|
| 55 |
+
color: #d4d4d4;
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
h1 {
|
| 59 |
+
color: #4fc1ff;
|
| 60 |
+
}`
|
| 61 |
+
);
|
| 62 |
+
await fs.writeFile(
|
| 63 |
+
path.join(WORKSPACE_DIR, 'package.json'),
|
| 64 |
+
JSON.stringify({
|
| 65 |
+
name: 'demo-project',
|
| 66 |
+
version: '1.0.0',
|
| 67 |
+
scripts: {
|
| 68 |
+
test: 'echo "Tests passed!" && exit 0'
|
| 69 |
+
}
|
| 70 |
+
}, null, 2)
|
| 71 |
+
);
|
| 72 |
+
await fs.mkdir(path.join(WORKSPACE_DIR, 'src'), { recursive: true });
|
| 73 |
+
await fs.writeFile(
|
| 74 |
+
path.join(WORKSPACE_DIR, 'src', 'utils.js'),
|
| 75 |
+
`// Utility functions
|
| 76 |
+
export function add(a, b) {
|
| 77 |
+
return a + b;
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
export function multiply(a, b) {
|
| 81 |
+
return a * b;
|
| 82 |
+
}`
|
| 83 |
+
);
|
| 84 |
+
}
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
// File System API
|
| 88 |
+
app.get('/api/files', async (req, res) => {
|
| 89 |
+
try {
|
| 90 |
+
const files = await readDirectory(WORKSPACE_DIR);
|
| 91 |
+
res.json(files);
|
| 92 |
+
} catch (error) {
|
| 93 |
+
res.status(500).json({ error: error.message });
|
| 94 |
+
}
|
| 95 |
+
});
|
| 96 |
+
|
| 97 |
+
app.get('/api/files/*', async (req, res) => {
|
| 98 |
+
try {
|
| 99 |
+
const filePath = path.join(WORKSPACE_DIR, req.params[0]);
|
| 100 |
+
const content = await fs.readFile(filePath, 'utf-8');
|
| 101 |
+
res.json({ content });
|
| 102 |
+
} catch (error) {
|
| 103 |
+
res.status(500).json({ error: error.message });
|
| 104 |
+
}
|
| 105 |
+
});
|
| 106 |
+
|
| 107 |
+
app.post('/api/files/*', async (req, res) => {
|
| 108 |
+
try {
|
| 109 |
+
const filePath = path.join(WORKSPACE_DIR, req.params[0]);
|
| 110 |
+
const dir = path.dirname(filePath);
|
| 111 |
+
await fs.mkdir(dir, { recursive: true });
|
| 112 |
+
await fs.writeFile(filePath, req.body.content, 'utf-8');
|
| 113 |
+
res.json({ success: true });
|
| 114 |
+
} catch (error) {
|
| 115 |
+
res.status(500).json({ error: error.message });
|
| 116 |
+
}
|
| 117 |
+
});
|
| 118 |
+
|
| 119 |
+
app.delete('/api/files/*', async (req, res) => {
|
| 120 |
+
try {
|
| 121 |
+
const filePath = path.join(WORKSPACE_DIR, req.params[0]);
|
| 122 |
+
await fs.unlink(filePath);
|
| 123 |
+
res.json({ success: true });
|
| 124 |
+
} catch (error) {
|
| 125 |
+
res.status(500).json({ error: error.message });
|
| 126 |
+
}
|
| 127 |
+
});
|
| 128 |
+
|
| 129 |
+
app.post('/api/files/create-folder/*', async (req, res) => {
|
| 130 |
+
try {
|
| 131 |
+
const folderPath = path.join(WORKSPACE_DIR, req.params[0]);
|
| 132 |
+
await fs.mkdir(folderPath, { recursive: true });
|
| 133 |
+
res.json({ success: true });
|
| 134 |
+
} catch (error) {
|
| 135 |
+
res.status(500).json({ error: error.message });
|
| 136 |
+
}
|
| 137 |
+
});
|
| 138 |
+
|
| 139 |
+
app.post('/api/files/rename', async (req, res) => {
|
| 140 |
+
try {
|
| 141 |
+
const { oldPath, newPath } = req.body;
|
| 142 |
+
const fullOldPath = path.join(WORKSPACE_DIR, oldPath);
|
| 143 |
+
const fullNewPath = path.join(WORKSPACE_DIR, newPath);
|
| 144 |
+
await fs.rename(fullOldPath, fullNewPath);
|
| 145 |
+
res.json({ success: true });
|
| 146 |
+
} catch (error) {
|
| 147 |
+
res.status(500).json({ error: error.message });
|
| 148 |
+
}
|
| 149 |
+
});
|
| 150 |
+
|
| 151 |
+
// AI API
|
| 152 |
+
app.post('/api/ai/chat', async (req, res) => {
|
| 153 |
+
const { message, context } = req.body;
|
| 154 |
+
|
| 155 |
+
// Simulated AI responses (in production, integrate with OpenAI/Anthropic)
|
| 156 |
+
const responses = {
|
| 157 |
+
'summarize': {
|
| 158 |
+
type: 'summary',
|
| 159 |
+
content: `# Project Summary
|
| 160 |
+
|
| 161 |
+
This is a demo project with the following structure:
|
| 162 |
+
- **index.html**: Main HTML entry point
|
| 163 |
+
- **app.js**: JavaScript application logic
|
| 164 |
+
- **styles.css**: Styling definitions
|
| 165 |
+
- **package.json**: Project configuration
|
| 166 |
+
- **src/utils.js**: Utility functions
|
| 167 |
+
|
| 168 |
+
The project appears to be a simple web application demonstrating basic functionality.`
|
| 169 |
+
},
|
| 170 |
+
'explain': {
|
| 171 |
+
type: 'explanation',
|
| 172 |
+
content: `The code you've selected is a simple greeting function that takes a name parameter and returns a formatted string. It uses template literals for string interpolation.`
|
| 173 |
+
},
|
| 174 |
+
'default': {
|
| 175 |
+
type: 'response',
|
| 176 |
+
content: `I've analyzed your request. Based on the project structure, I can help you with:
|
| 177 |
+
|
| 178 |
+
1. Creating new files and folders
|
| 179 |
+
2. Refactoring existing code
|
| 180 |
+
3. Generating unit tests
|
| 181 |
+
4. Explaining code snippets
|
| 182 |
+
5. Running commands and tests
|
| 183 |
+
|
| 184 |
+
What would you like me to do?`
|
| 185 |
+
}
|
| 186 |
+
};
|
| 187 |
+
|
| 188 |
+
// Simple keyword matching for demo
|
| 189 |
+
let response = responses.default;
|
| 190 |
+
if (message.toLowerCase().includes('summarize') || message.toLowerCase().includes('structure')) {
|
| 191 |
+
response = responses.summarize;
|
| 192 |
+
} else if (message.toLowerCase().includes('explain')) {
|
| 193 |
+
response = responses.explain;
|
| 194 |
+
}
|
| 195 |
+
|
| 196 |
+
res.json(response);
|
| 197 |
+
});
|
| 198 |
+
|
| 199 |
+
// Execute command
|
| 200 |
+
app.post('/api/execute', (req, res) => {
|
| 201 |
+
const { command } = req.body;
|
| 202 |
+
|
| 203 |
+
exec(command, { cwd: WORKSPACE_DIR }, (error, stdout, stderr) => {
|
| 204 |
+
res.json({
|
| 205 |
+
success: !error,
|
| 206 |
+
output: stdout || stderr,
|
| 207 |
+
error: error ? error.message : null
|
| 208 |
+
});
|
| 209 |
+
});
|
| 210 |
+
});
|
| 211 |
+
|
| 212 |
+
// Helper function to read directory recursively
|
| 213 |
+
async function readDirectory(dir, basePath = '') {
|
| 214 |
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
| 215 |
+
const result = [];
|
| 216 |
+
|
| 217 |
+
for (const entry of entries) {
|
| 218 |
+
const fullPath = path.join(dir, entry.name);
|
| 219 |
+
const relativePath = path.join(basePath, entry.name);
|
| 220 |
+
|
| 221 |
+
if (entry.isDirectory()) {
|
| 222 |
+
result.push({
|
| 223 |
+
name: entry.name,
|
| 224 |
+
path: relativePath,
|
| 225 |
+
type: 'folder',
|
| 226 |
+
children: await readDirectory(fullPath, relativePath)
|
| 227 |
+
});
|
| 228 |
+
} else {
|
| 229 |
+
const stats = await fs.stat(fullPath);
|
| 230 |
+
result.push({
|
| 231 |
+
name: entry.name,
|
| 232 |
+
path: relativePath,
|
| 233 |
+
type: 'file',
|
| 234 |
+
size: stats.size,
|
| 235 |
+
extension: path.extname(entry.name).slice(1)
|
| 236 |
+
});
|
| 237 |
+
}
|
| 238 |
+
}
|
| 239 |
+
|
| 240 |
+
return result;
|
| 241 |
+
}
|
| 242 |
+
|
| 243 |
+
// WebSocket Server for terminal and real-time updates
|
| 244 |
+
const server = http.createServer(app);
|
| 245 |
+
const io = new Server(server, {
|
| 246 |
+
cors: {
|
| 247 |
+
origin: '*',
|
| 248 |
+
methods: ['GET', 'POST']
|
| 249 |
+
}
|
| 250 |
+
});
|
| 251 |
+
|
| 252 |
+
io.on('connection', (socket) => {
|
| 253 |
+
console.log('Client connected');
|
| 254 |
+
|
| 255 |
+
socket.on('terminal-input', (data) => {
|
| 256 |
+
// Simulate terminal output
|
| 257 |
+
exec(data.command, { cwd: WORKSPACE_DIR }, (error, stdout, stderr) => {
|
| 258 |
+
socket.emit('terminal-output', {
|
| 259 |
+
output: stdout || stderr || `Command: ${data.command}`,
|
| 260 |
+
error: !!error
|
| 261 |
+
});
|
| 262 |
+
});
|
| 263 |
+
});
|
| 264 |
+
|
| 265 |
+
socket.on('file-change', (data) => {
|
| 266 |
+
socket.broadcast.emit('file-updated', data);
|
| 267 |
+
});
|
| 268 |
+
|
| 269 |
+
socket.on('disconnect', () => {
|
| 270 |
+
console.log('Client disconnected');
|
| 271 |
+
});
|
| 272 |
+
});
|
| 273 |
+
|
| 274 |
+
// Start server
|
| 275 |
+
ensureWorkspace().then(() => {
|
| 276 |
+
const PORT = process.env.PORT || 3001;
|
| 277 |
+
server.listen(PORT, () => {
|
| 278 |
+
console.log(`AgentIDE server running on http://localhost:${PORT}`);
|
| 279 |
+
console.log(`Workspace: ${WORKSPACE_DIR}`);
|
| 280 |
+
});
|
| 281 |
+
});
|
| 282 |
+
|
| 283 |
+
module.exports = app;
|
|
@@ -1,28 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
| 1 |
body {
|
| 2 |
-
|
| 3 |
-
font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
|
| 4 |
}
|
| 5 |
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
|
|
|
| 9 |
}
|
| 10 |
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
font-size: 15px;
|
| 14 |
-
margin-bottom: 10px;
|
| 15 |
-
margin-top: 5px;
|
| 16 |
}
|
| 17 |
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
}
|
| 25 |
|
| 26 |
-
|
| 27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* Custom Utilities */
|
| 2 |
+
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap');
|
| 3 |
+
|
| 4 |
body {
|
| 5 |
+
font-family: 'Inter', sans-serif;
|
|
|
|
| 6 |
}
|
| 7 |
|
| 8 |
+
/* Smooth fade in animation */
|
| 9 |
+
@keyframes fadeIn {
|
| 10 |
+
from { opacity: 0; transform: translateY(20px); }
|
| 11 |
+
to { opacity: 1; transform: translateY(0); }
|
| 12 |
}
|
| 13 |
|
| 14 |
+
.animate-fade-in {
|
| 15 |
+
animation: fadeIn 0.6s ease-out forwards;
|
|
|
|
|
|
|
|
|
|
| 16 |
}
|
| 17 |
|
| 18 |
+
/* Glassmorphism utility class for non-component elements */
|
| 19 |
+
.glass {
|
| 20 |
+
background: rgba(255, 255, 255, 0.7);
|
| 21 |
+
backdrop-filter: blur(10px);
|
| 22 |
+
-webkit-backdrop-filter: blur(10px);
|
| 23 |
+
border-bottom: 1px solid rgba(255, 255, 255, 0.3);
|
| 24 |
}
|
| 25 |
|
| 26 |
+
/* Custom Scrollbar */
|
| 27 |
+
::-webkit-scrollbar {
|
| 28 |
+
width: 10px;
|
| 29 |
+
}
|
| 30 |
+
::-webkit-scrollbar-track {
|
| 31 |
+
background: #f1f5f9;
|
| 32 |
+
}
|
| 33 |
+
::-webkit-scrollbar-thumb {
|
| 34 |
+
background: #cbd5e1;
|
| 35 |
+
border-radius: 5px;
|
| 36 |
}
|
| 37 |
+
::-webkit-scrollbar-thumb:hover {
|
| 38 |
+
background: #94a3b8;
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
/* Text Selection */
|
| 42 |
+
::selection {
|
| 43 |
+
background: #4f46e5;
|
| 44 |
+
color: #ffffff;
|
| 45 |
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Smoke test for AgentIDE
|
| 2 |
+
const assert = require('assert');
|
| 3 |
+
|
| 4 |
+
console.log('π§ͺ Running AgentIDE Smoke Tests...\n');
|
| 5 |
+
|
| 6 |
+
// Test 1: Server should start
|
| 7 |
+
console.log('β Test 1: Server initialization');
|
| 8 |
+
|
| 9 |
+
// Test 2: Workspace should exist
|
| 10 |
+
const fs = require('fs');
|
| 11 |
+
const path = require('path');
|
| 12 |
+
const workspaceDir = path.join(__dirname, '../workspace');
|
| 13 |
+
|
| 14 |
+
try {
|
| 15 |
+
assert(fs.existsSync(workspaceDir), 'Workspace directory should exist');
|
| 16 |
+
console.log('β Test 2: Workspace directory exists');
|
| 17 |
+
} catch (e) {
|
| 18 |
+
console.log('β Test 2: Workspace directory missing');
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
// Test 3: Demo files should exist
|
| 22 |
+
const demoFiles = ['index.html', 'app.js', 'styles.css', 'package.json'];
|
| 23 |
+
let filesExist = true;
|
| 24 |
+
demoFiles.forEach(file => {
|
| 25 |
+
if (!fs.existsSync(path.join(workspaceDir, file))) {
|
| 26 |
+
filesExist = false;
|
| 27 |
+
}
|
| 28 |
+
});
|
| 29 |
+
if (filesExist) {
|
| 30 |
+
console.log('β Test 3: Demo files present');
|
| 31 |
+
} else {
|
| 32 |
+
console.log('β Test 3: Demo files missing');
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
// Test 4: Package.json should have correct structure
|
| 36 |
+
try {
|
| 37 |
+
const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, '../package.json'), 'utf8'));
|
| 38 |
+
assert(pkg.name === 'agentide', 'Package name should be agentide');
|
| 39 |
+
assert(pkg.dependencies !== undefined, 'Dependencies should exist');
|
| 40 |
+
console.log('β Test 4: Package.json structure valid');
|
| 41 |
+
} catch (e) {
|
| 42 |
+
console.log('β Test 4: Package.json invalid');
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
console.log('\nπ All basic tests passed!');
|
| 46 |
+
console.log('Run "npm start" to launch the IDE server.');
|