@builderos/create-agent-os 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -0
- package/bin/cli.js +133 -0
- package/package.json +40 -0
- package/src/template/App.tsx +68 -0
- package/src/template/agent-os/commands/create-tasks/1-get-spec-requirements.md +19 -0
- package/src/template/agent-os/commands/create-tasks/2-create-tasks-list.md +234 -0
- package/src/template/agent-os/commands/create-tasks/create-tasks.md +254 -0
- package/src/template/agent-os/commands/design-screen/design-screen.md +32 -0
- package/src/template/agent-os/commands/design-shell/design-shell.md +34 -0
- package/src/template/agent-os/commands/design-tokens/design-tokens.md +36 -0
- package/src/template/agent-os/commands/export-product/export-product.md +44 -0
- package/src/template/agent-os/commands/implement-tasks/1-determine-tasks.md +13 -0
- package/src/template/agent-os/commands/implement-tasks/2-implement-tasks.md +63 -0
- package/src/template/agent-os/commands/implement-tasks/3-verify-implementation.md +113 -0
- package/src/template/agent-os/commands/implement-tasks/implement-tasks.md +207 -0
- package/src/template/agent-os/commands/initialize-design/initialize-design.md +54 -0
- package/src/template/agent-os/commands/orchestrate-tasks/orchestrate-tasks.md +180 -0
- package/src/template/agent-os/commands/plan-product/1-product-concept.md +53 -0
- package/src/template/agent-os/commands/plan-product/2-create-mission.md +78 -0
- package/src/template/agent-os/commands/plan-product/3-create-roadmap.md +73 -0
- package/src/template/agent-os/commands/plan-product/4-create-tech-stack.md +46 -0
- package/src/template/agent-os/commands/plan-product/plan-product.md +241 -0
- package/src/template/agent-os/commands/sample-data/sample-data.md +51 -0
- package/src/template/agent-os/commands/scaffold-implementation/scaffold-implementation.md +36 -0
- package/src/template/agent-os/commands/screenshot-design/screenshot-design.md +21 -0
- package/src/template/agent-os/commands/shape-spec/1-initialize-spec.md +95 -0
- package/src/template/agent-os/commands/shape-spec/2-shape-spec.md +300 -0
- package/src/template/agent-os/commands/shape-spec/shape-spec.md +40 -0
- package/src/template/agent-os/commands/write-spec/write-spec.md +134 -0
- package/src/template/agent-os/config.yml +13 -0
- package/src/template/agent-os/product/mission.md +29 -0
- package/src/template/agent-os/product/roadmap.md +9 -0
- package/src/template/agent-os/product/tech-stack.md +14 -0
- package/src/template/agent-os/specs/README.md +1 -0
- package/src/template/agent-os/standards/backend/api.md +10 -0
- package/src/template/agent-os/standards/backend/migrations.md +9 -0
- package/src/template/agent-os/standards/backend/models.md +10 -0
- package/src/template/agent-os/standards/backend/queries.md +9 -0
- package/src/template/agent-os/standards/frontend/accessibility.md +10 -0
- package/src/template/agent-os/standards/frontend/components.md +11 -0
- package/src/template/agent-os/standards/frontend/css.md +7 -0
- package/src/template/agent-os/standards/frontend/responsive.md +11 -0
- package/src/template/agent-os/standards/global/coding-style.md +10 -0
- package/src/template/agent-os/standards/global/commenting.md +5 -0
- package/src/template/agent-os/standards/global/conventions.md +11 -0
- package/src/template/agent-os/standards/global/error-handling.md +9 -0
- package/src/template/agent-os/standards/global/tech-stack.md +31 -0
- package/src/template/agent-os/standards/global/validation.md +11 -0
- package/src/template/agent-os/standards/testing/test-writing.md +9 -0
- package/src/template/agent-os-ui/README.md +73 -0
- package/src/template/agent-os-ui/package-lock.json +5028 -0
- package/src/template/agent-os-ui/package.json +52 -0
- package/src/template/agent-os-ui/postcss.config.js +6 -0
- package/src/template/agent-os-ui/src/components/AgentShell.tsx +31 -0
- package/src/template/agent-os-ui/src/components/AgentSidebar.tsx +65 -0
- package/src/template/agent-os-ui/src/components/GuidanceCard.tsx +75 -0
- package/src/template/agent-os-ui/src/components/MarkdownViewer.tsx +25 -0
- package/src/template/agent-os-ui/src/components/PromptButton.tsx +28 -0
- package/src/template/agent-os-ui/src/components/StatusItem.tsx +45 -0
- package/src/template/agent-os-ui/src/components/ThemeToggle.tsx +72 -0
- package/src/template/agent-os-ui/src/index.ts +11 -0
- package/src/template/agent-os-ui/src/style.css +3 -0
- package/src/template/agent-os-ui/tailwind.config.js +50 -0
- package/src/template/agent-os-ui/tsconfig.json +33 -0
- package/src/template/agent-os-ui/vite.config.ts +32 -0
- package/src/template/control-center/backend/backend.log +2 -0
- package/src/template/control-center/backend/index.js +228 -0
- package/src/template/control-center/backend/package-lock.json +951 -0
- package/src/template/control-center/backend/package.json +19 -0
- package/src/template/control-center/frontend/README.md +73 -0
- package/src/template/control-center/frontend/eslint.config.js +23 -0
- package/src/template/control-center/frontend/index.html +21 -0
- package/src/template/control-center/frontend/package-lock.json +5752 -0
- package/src/template/control-center/frontend/package.json +42 -0
- package/src/template/control-center/frontend/public/runtime-config.json +11 -0
- package/src/template/control-center/frontend/public/vite.svg +1 -0
- package/src/template/control-center/frontend/src/App.css +42 -0
- package/src/template/control-center/frontend/src/App.tsx +738 -0
- package/src/template/control-center/frontend/src/assets/react.svg +1 -0
- package/src/template/control-center/frontend/src/components/ThemeToggle.tsx +64 -0
- package/src/template/control-center/frontend/src/components/ui/ToastContext.tsx +81 -0
- package/src/template/control-center/frontend/src/index.css +194 -0
- package/src/template/control-center/frontend/src/main.tsx +14 -0
- package/src/template/control-center/frontend/src/vite-env.d.ts +1 -0
- package/src/template/control-center/frontend/tsconfig.app.json +28 -0
- package/src/template/control-center/frontend/tsconfig.json +7 -0
- package/src/template/control-center/frontend/tsconfig.node.json +26 -0
- package/src/template/control-center/frontend/vite.config.ts +22 -0
- package/src/template/design/.claude/commands/design-os/data-model.md +122 -0
- package/src/template/design/.claude/commands/design-os/design-screen.md +309 -0
- package/src/template/design/.claude/commands/design-os/design-shell.md +238 -0
- package/src/template/design/.claude/commands/design-os/design-tokens.md +166 -0
- package/src/template/design/.claude/commands/design-os/export-product.md +1105 -0
- package/src/template/design/.claude/commands/design-os/product-roadmap.md +121 -0
- package/src/template/design/.claude/commands/design-os/product-vision.md +99 -0
- package/src/template/design/.claude/commands/design-os/sample-data.md +263 -0
- package/src/template/design/.claude/commands/design-os/screenshot-design.md +112 -0
- package/src/template/design/.claude/commands/design-os/shape-section.md +138 -0
- package/src/template/design/.claude/skills/frontend-design/SKILL.md +42 -0
- package/src/template/design/.github/CODE_OF_CONDUCT.md +5 -0
- package/src/template/design/.github/CONTRIBUTING.md +51 -0
- package/src/template/design/.github/ISSUE_TEMPLATE/config.yml +22 -0
- package/src/template/design/.github/PULL_REQUEST_TEMPLATE.md +20 -0
- package/src/template/design/.github/SECURITY.yml +5 -0
- package/src/template/design/.github/SUPPORT.md +19 -0
- package/src/template/design/.github/workflows/pr-decline.yml +135 -0
- package/src/template/design/.github/workflows/stale.yml +25 -0
- package/src/template/design/CHANGELOG.md +13 -0
- package/src/template/design/LICENSE +21 -0
- package/src/template/design/README.md +54 -0
- package/src/template/design/agents.md +218 -0
- package/src/template/design/claude.md +1 -0
- package/src/template/design/components.json +22 -0
- package/src/template/design/docs/codebase-implementation.md +153 -0
- package/src/template/design/docs/design-section.md +135 -0
- package/src/template/design/docs/export.md +149 -0
- package/src/template/design/docs/getting-started.md +59 -0
- package/src/template/design/docs/index.md +56 -0
- package/src/template/design/docs/product-planning.md +113 -0
- package/src/template/design/docs/requirements.md +22 -0
- package/src/template/design/docs/usage.md +62 -0
- package/src/template/design/eslint.config.js +23 -0
- package/src/template/design/index.html +21 -0
- package/src/template/design/package-lock.json +5473 -0
- package/src/template/design/package.json +47 -0
- package/src/template/design/product-plan.zip +0 -0
- package/src/template/design/public/vite.svg +1 -0
- package/src/template/design/src/assets/react.svg +1 -0
- package/src/template/design/src/components/AppLayout.tsx +95 -0
- package/src/template/design/src/components/DataCard.tsx +139 -0
- package/src/template/design/src/components/DataModelPage.tsx +120 -0
- package/src/template/design/src/components/DesignPage.tsx +284 -0
- package/src/template/design/src/components/EmptyState.tsx +155 -0
- package/src/template/design/src/components/ExportPage.tsx +344 -0
- package/src/template/design/src/components/NextPhaseButton.tsx +33 -0
- package/src/template/design/src/components/PhaseNav.tsx +152 -0
- package/src/template/design/src/components/PhaseWarningBanner.tsx +81 -0
- package/src/template/design/src/components/ProductOverviewCard.tsx +102 -0
- package/src/template/design/src/components/ProductPage.tsx +97 -0
- package/src/template/design/src/components/ScreenDesignPage.tsx +370 -0
- package/src/template/design/src/components/ScreenDesignsCard.tsx +49 -0
- package/src/template/design/src/components/SectionPage.tsx +256 -0
- package/src/template/design/src/components/SectionsCard.tsx +47 -0
- package/src/template/design/src/components/SectionsPage.tsx +181 -0
- package/src/template/design/src/components/ShellCard.tsx +85 -0
- package/src/template/design/src/components/ShellDesignPage.tsx +242 -0
- package/src/template/design/src/components/SpecCard.tsx +121 -0
- package/src/template/design/src/components/StepIndicator.tsx +75 -0
- package/src/template/design/src/components/ThemeToggle.tsx +86 -0
- package/src/template/design/src/components/ui/ToastContext.tsx +81 -0
- package/src/template/design/src/components/ui/avatar.tsx +53 -0
- package/src/template/design/src/components/ui/badge.tsx +46 -0
- package/src/template/design/src/components/ui/button.tsx +60 -0
- package/src/template/design/src/components/ui/card.tsx +92 -0
- package/src/template/design/src/components/ui/collapsible.tsx +48 -0
- package/src/template/design/src/components/ui/dialog.tsx +143 -0
- package/src/template/design/src/components/ui/dropdown-menu.tsx +255 -0
- package/src/template/design/src/components/ui/input.tsx +21 -0
- package/src/template/design/src/components/ui/label.tsx +22 -0
- package/src/template/design/src/components/ui/progress.tsx +24 -0
- package/src/template/design/src/components/ui/scroll-area.tsx +18 -0
- package/src/template/design/src/components/ui/select.tsx +67 -0
- package/src/template/design/src/components/ui/separator.tsx +28 -0
- package/src/template/design/src/components/ui/sheet.tsx +137 -0
- package/src/template/design/src/components/ui/skeleton.tsx +13 -0
- package/src/template/design/src/components/ui/switch.tsx +46 -0
- package/src/template/design/src/components/ui/table.tsx +116 -0
- package/src/template/design/src/components/ui/tabs.tsx +64 -0
- package/src/template/design/src/index.css +284 -0
- package/src/template/design/src/lib/data-model-loader.ts +91 -0
- package/src/template/design/src/lib/design-system-loader.ts +101 -0
- package/src/template/design/src/lib/product-loader.ts +221 -0
- package/src/template/design/src/lib/router.tsx +52 -0
- package/src/template/design/src/lib/section-loader.ts +272 -0
- package/src/template/design/src/lib/shell-loader.ts +175 -0
- package/src/template/design/src/lib/utils.ts +6 -0
- package/src/template/design/src/main.tsx +15 -0
- package/src/template/design/src/sections/.gitkeep +0 -0
- package/src/template/design/src/sections/ai-orchestration-engine-oai/OrchestrationEngine.tsx +348 -0
- package/src/template/design/src/sections/core-platform-shell/AppShell.tsx +403 -0
- package/src/template/design/src/sections/gemini-live-integration/GeminiIntegration.tsx +332 -0
- package/src/template/design/src/sections/interactive-2d-canvas/WhiteboardCanvas.tsx +334 -0
- package/src/template/design/src/sections/participation-equity-tracker/EquityTracker.tsx +383 -0
- package/src/template/design/src/sections/persistent-memory-system/PersistentMemory.tsx +308 -0
- package/src/template/design/src/sections/real-time-communication-layer/VideoSession.tsx +342 -0
- package/src/template/design/src/sections/visual-intelligence-agents/VisualAgents.tsx +311 -0
- package/src/template/design/src/types/product.ts +97 -0
- package/src/template/design/src/types/section.ts +33 -0
- package/src/template/design/tsconfig.app.json +34 -0
- package/src/template/design/tsconfig.json +13 -0
- package/src/template/design/tsconfig.node.json +26 -0
- package/src/template/design/vite.config.ts +18 -0
- package/src/template/package.json +27 -0
- package/src/template/vite.config.ts +16 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
const express = require('express');
|
|
2
|
+
const cors = require('cors');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { glob } = require('glob');
|
|
6
|
+
|
|
7
|
+
const app = express();
|
|
8
|
+
const PORT = process.env.PORT || 3001;
|
|
9
|
+
const DESIGN_PORT = process.env.DESIGN_PORT || 3000;
|
|
10
|
+
const APP_PORT = process.env.APP_PORT || 3002;
|
|
11
|
+
|
|
12
|
+
// Configuration
|
|
13
|
+
const PROJECT_ROOT = path.resolve(__dirname, '../..'); // learning-agent-os root
|
|
14
|
+
const APP_DIR = path.join(PROJECT_ROOT, 'app');
|
|
15
|
+
const AGENT_OS_DIR = path.join(PROJECT_ROOT, 'agent-os');
|
|
16
|
+
|
|
17
|
+
app.use(cors());
|
|
18
|
+
app.use(express.json());
|
|
19
|
+
|
|
20
|
+
// Helper to check file existence
|
|
21
|
+
const checkFile = (filePath) => {
|
|
22
|
+
return fs.existsSync(path.join(AGENT_OS_DIR, filePath));
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// Helper to parse markdown checkboxes
|
|
26
|
+
const parseStatus = (relativePath) => {
|
|
27
|
+
const fullPath = path.join(AGENT_OS_DIR, relativePath);
|
|
28
|
+
console.log(`Reading path: ${fullPath}`);
|
|
29
|
+
if (!fs.existsSync(fullPath)) {
|
|
30
|
+
console.log(`File not found: ${fullPath}`);
|
|
31
|
+
return { exists: false, completed: 0, total: 0, nextItem: null, items: [] };
|
|
32
|
+
}
|
|
33
|
+
const content = fs.readFileSync(fullPath, 'utf-8');
|
|
34
|
+
const total = (content.match(/- \[ \]/g) || []).length + (content.match(/- \[x\]/g) || []).length;
|
|
35
|
+
const completed = (content.match(/- \[x\]/g) || []).length;
|
|
36
|
+
|
|
37
|
+
// Find next incomplete item and all items
|
|
38
|
+
let nextItem = null;
|
|
39
|
+
const items = [];
|
|
40
|
+
const lines = content.split('\n');
|
|
41
|
+
|
|
42
|
+
for (const line of lines) {
|
|
43
|
+
const match = line.match(/^\s*-\s*\[([ x])\]\s*(.+)$/);
|
|
44
|
+
if (match) {
|
|
45
|
+
const isCompleted = match[1] === 'x';
|
|
46
|
+
const text = match[2].trim();
|
|
47
|
+
// Clean up text (remove bolding, etc)
|
|
48
|
+
const cleanText = text.replace(/\*\*/g, '').replace(/^\d+\.\s*/, '');
|
|
49
|
+
|
|
50
|
+
items.push({ name: cleanText, completed: isCompleted });
|
|
51
|
+
|
|
52
|
+
if (!nextItem && !isCompleted) {
|
|
53
|
+
nextItem = cleanText;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Check for boilerplate indicators
|
|
59
|
+
const boilerplateMarkers = [
|
|
60
|
+
'[Your Product Name]',
|
|
61
|
+
'[Database choice]',
|
|
62
|
+
'[Role]',
|
|
63
|
+
'[Feature 1]',
|
|
64
|
+
'[Target Audience]',
|
|
65
|
+
'[Unique Value Proposition',
|
|
66
|
+
'MVP Launch',
|
|
67
|
+
'First User',
|
|
68
|
+
'Feature A'
|
|
69
|
+
];
|
|
70
|
+
const isBoilerplate = boilerplateMarkers.some(marker => content.includes(marker));
|
|
71
|
+
|
|
72
|
+
return { exists: true, isBoilerplate, completed, total, nextItem, items };
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// Helper to check service health
|
|
76
|
+
const checkService = (port) => {
|
|
77
|
+
return new Promise((resolve) => {
|
|
78
|
+
const http = require('http');
|
|
79
|
+
const req = http.get(`http://localhost:${port}/`, { timeout: 2000 }, (res) => {
|
|
80
|
+
// If we get any response, the port is active and serving HTTP
|
|
81
|
+
resolve(true);
|
|
82
|
+
// conn.destroy(); // Not needed if we just consume/ignore.
|
|
83
|
+
// Actually, we should consume resume to avoid hanging?
|
|
84
|
+
// Or just destroy.
|
|
85
|
+
res.resume();
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
req.on('error', (e) => {
|
|
89
|
+
resolve(false);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
req.on('timeout', () => {
|
|
93
|
+
req.destroy();
|
|
94
|
+
resolve(false);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// API: Get Project Status
|
|
100
|
+
app.get('/api/status', async (req, res) => {
|
|
101
|
+
try {
|
|
102
|
+
const productFiles = {
|
|
103
|
+
mission: parseStatus('product/mission.md'),
|
|
104
|
+
roadmap: parseStatus('product/roadmap.md'),
|
|
105
|
+
techStack: parseStatus('product/tech-stack.md'),
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
// Get Specs
|
|
109
|
+
const specDirs = glob.sync('specs/*/', { cwd: AGENT_OS_DIR });
|
|
110
|
+
const specs = specDirs.map(dir => {
|
|
111
|
+
const name = path.basename(dir);
|
|
112
|
+
return {
|
|
113
|
+
name,
|
|
114
|
+
spec: parseStatus(`specs/${name}/spec.md`),
|
|
115
|
+
tasks: parseStatus(`specs/${name}/tasks.md`),
|
|
116
|
+
};
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// Check Services
|
|
120
|
+
const services = {
|
|
121
|
+
api: true, // We are responding, so we are alive
|
|
122
|
+
design: await checkService(DESIGN_PORT),
|
|
123
|
+
app: await checkService(APP_PORT)
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
// Check for Design OS export and steps
|
|
127
|
+
const designDir = path.join(PROJECT_ROOT, 'design-system');
|
|
128
|
+
// Note: In dev, these files are in design/public/product. In prod, injected elsewhere.
|
|
129
|
+
// But for this local dev setup, we check where the initialize-design command puts them?
|
|
130
|
+
// Actually, initialize-design puts them in `design/public/product`.
|
|
131
|
+
|
|
132
|
+
const hasDesignExport = fs.existsSync(path.join(PROJECT_ROOT, 'product-plan'));
|
|
133
|
+
const hasDesignInit = fs.existsSync(path.join(designDir, 'product/product-overview.md'));
|
|
134
|
+
const hasTokens = fs.existsSync(path.join(designDir, 'product/design-system/colors.json'));
|
|
135
|
+
const hasShell = fs.existsSync(path.join(designDir, 'product/shell/spec.md'));
|
|
136
|
+
|
|
137
|
+
res.json({
|
|
138
|
+
product: productFiles,
|
|
139
|
+
services,
|
|
140
|
+
design: {
|
|
141
|
+
exists: hasTokens,
|
|
142
|
+
initialized: hasDesignInit,
|
|
143
|
+
tokens: hasTokens,
|
|
144
|
+
shell: hasShell,
|
|
145
|
+
exported: hasDesignExport
|
|
146
|
+
},
|
|
147
|
+
implementation: {
|
|
148
|
+
scaffolded: fs.existsSync(path.join(APP_DIR, 'src/lib/utils.ts'))
|
|
149
|
+
},
|
|
150
|
+
specs,
|
|
151
|
+
projectRoot: PROJECT_ROOT
|
|
152
|
+
});
|
|
153
|
+
} catch (error) {
|
|
154
|
+
console.error(error);
|
|
155
|
+
res.status(500).json({ error: error.message });
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// API: Scaffold New Spec
|
|
160
|
+
app.post('/api/scaffold/spec', (req, res) => {
|
|
161
|
+
const { name } = req.body;
|
|
162
|
+
if (!name) return res.status(400).json({ error: 'Spec name required' });
|
|
163
|
+
|
|
164
|
+
const specDir = path.join(AGENT_OS_DIR, 'specs', name);
|
|
165
|
+
if (fs.existsSync(specDir)) return res.status(400).json({ error: 'Spec already exists' });
|
|
166
|
+
|
|
167
|
+
fs.mkdirSync(specDir, { recursive: true });
|
|
168
|
+
// Create empty placeholders
|
|
169
|
+
fs.writeFileSync(path.join(specDir, 'spec.md'), '# Spec: ' + name);
|
|
170
|
+
fs.writeFileSync(path.join(specDir, 'tasks.md'), '# Tasks\n\n- [ ] Initial task');
|
|
171
|
+
|
|
172
|
+
res.json({ success: true, path: specDir });
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
// API: Delete Spec
|
|
176
|
+
app.delete('/api/scaffold/spec/:name', (req, res) => {
|
|
177
|
+
const { name } = req.params;
|
|
178
|
+
if (!name) return res.status(400).json({ error: 'Spec name required' });
|
|
179
|
+
|
|
180
|
+
// Validate name to prevent directory traversal or deleting non-spec files
|
|
181
|
+
// Allow alphanumeric, hyphens, underscores
|
|
182
|
+
if (!/^[a-zA-Z0-9-_]+$/.test(name)) {
|
|
183
|
+
return res.status(400).json({ error: 'Invalid spec name' });
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const specDir = path.join(AGENT_OS_DIR, 'specs', name);
|
|
187
|
+
if (!fs.existsSync(specDir)) {
|
|
188
|
+
return res.status(404).json({ error: 'Spec not found' });
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
try {
|
|
192
|
+
fs.rmSync(specDir, { recursive: true, force: true });
|
|
193
|
+
res.json({ success: true });
|
|
194
|
+
} catch (error) {
|
|
195
|
+
console.error('Delete error:', error);
|
|
196
|
+
res.status(500).json({ error: 'Failed to delete spec' });
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
// API: Get File Content
|
|
201
|
+
app.get('/api/files', (req, res) => {
|
|
202
|
+
const { path: filePath } = req.query;
|
|
203
|
+
if (!filePath) return res.status(400).json({ error: 'File path required' });
|
|
204
|
+
|
|
205
|
+
// Prevent directory traversal
|
|
206
|
+
const safePath = path.normalize(filePath).replace(/^(\.\.(\/|\\|$))+/, '');
|
|
207
|
+
const absolutePath = path.join(AGENT_OS_DIR, safePath);
|
|
208
|
+
|
|
209
|
+
if (!absolutePath.startsWith(AGENT_OS_DIR)) {
|
|
210
|
+
return res.status(403).json({ error: 'Access denied' });
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (!fs.existsSync(absolutePath)) {
|
|
214
|
+
return res.status(404).json({ error: 'File not found' });
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
try {
|
|
218
|
+
const content = fs.readFileSync(absolutePath, 'utf-8');
|
|
219
|
+
res.json({ content });
|
|
220
|
+
} catch (error) {
|
|
221
|
+
res.status(500).json({ error: error.message });
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
app.listen(PORT, () => {
|
|
226
|
+
console.log(`Control Center Backend running on http://localhost:${PORT}`);
|
|
227
|
+
console.log(`Monitoring Agent OS at: ${AGENT_OS_DIR}`);
|
|
228
|
+
});
|