Skip to content

Commit 8f7051d

Browse files
committed
chore: merge main into release for new releases
2 parents bc1d607 + a0dec65 commit 8f7051d

File tree

56 files changed

+2640
-1167
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+2640
-1167
lines changed

apps/api/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ COPY package.json ./
1313
# Note: workspace:* dependencies will be skipped and copied manually below
1414
RUN curl -fsSL https://bun.sh/install | bash \
1515
&& export PATH="/root/.bun/bin:$PATH" \
16-
&& bun install --production --ignore-scripts || true
16+
&& bun install --production --ignore-scripts
1717

1818
COPY node_modules/@trycompai ./node_modules/@trycompai
1919
COPY node_modules/@prisma ./node_modules/@prisma

apps/api/buildspec.yml

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,6 @@ phases:
3232
- echo "Installing API dependencies only..."
3333
- bun install --filter=@comp/api --frozen-lockfile || bun install --filter=@comp/api --ignore-scripts || bun install --ignore-scripts
3434

35-
- echo "Building @trycompai/email package..."
36-
- cd packages/email
37-
- bun run build
38-
- cd ../..
39-
4035
- echo "Building NestJS application..."
4136
- echo "APP_NAME is set to $APP_NAME"
4237
- echo "Current directory $(pwd)"
@@ -60,13 +55,14 @@ phases:
6055
- '[ -f "../docker-build/src/main.js" ] || { echo "❌ main.js not found in docker-build/src"; exit 1; }'
6156

6257
- mkdir -p ../docker-build/node_modules/@trycompai
63-
- mkdir -p ../docker-build/node_modules/@trycompai/email
64-
- cp -r ../../packages/email/dist ../docker-build/node_modules/@trycompai/email/
65-
- cp ../../packages/email/package.json ../docker-build/node_modules/@trycompai/email/
6658
- mkdir -p ../docker-build/node_modules/@trycompai/utils
59+
- mkdir -p ../docker-build/node_modules/@trycompai/db
6760
- cp -r ../../packages/utils/src ../docker-build/node_modules/@trycompai/utils/
6861
- cp ../../packages/utils/package.json ../docker-build/node_modules/@trycompai/utils/
6962

63+
- cp -r ../../packages/db/dist ../docker-build/node_modules/@trycompai/db/
64+
- cp ../../packages/db/package.json ../docker-build/node_modules/@trycompai/db/
65+
7066
- cp -r ../../node_modules/@prisma ../docker-build/node_modules/@prisma
7167
- cp -r ../../node_modules/.prisma ../docker-build/node_modules/.prisma
7268

apps/api/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
"@nestjs/platform-express": "^11.1.5",
1313
"@nestjs/swagger": "^11.2.0",
1414
"@prisma/client": "^6.13.0",
15+
"@react-email/components": "^0.0.41",
1516
"@trycompai/db": "^1.3.17",
16-
"@trycompai/email": "workspace:*",
1717
"archiver": "^7.0.1",
1818
"axios": "^1.12.2",
1919
"better-auth": "^1.3.27",
@@ -25,6 +25,8 @@
2525
"nanoid": "^5.1.6",
2626
"pdf-lib": "^1.17.1",
2727
"prisma": "^6.13.0",
28+
"react": "^19.1.1",
29+
"react-dom": "^19.1.0",
2830
"reflect-metadata": "^0.2.2",
2931
"resend": "^6.4.2",
3032
"rxjs": "^7.8.1",

apps/api/src/device-agent/device-agent.controller.ts

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,8 @@ export class DeviceAgentController {
7171
@AuthContext() authContext: AuthContextType,
7272
@Response({ passthrough: true }) res: ExpressResponse,
7373
) {
74-
// Use the authenticated user's ID as the employee ID
75-
const employeeId = authContext.userId || 'unknown-user';
76-
7774
const { stream, filename, contentType } =
78-
await this.deviceAgentService.downloadWindowsAgent(
79-
organizationId,
80-
employeeId,
81-
);
75+
await this.deviceAgentService.downloadWindowsAgent();
8276

8377
// Set headers for file download
8478
res.set({

apps/api/src/device-agent/device-agent.service.ts

Lines changed: 18 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,6 @@
11
import { Injectable, NotFoundException, Logger } from '@nestjs/common';
22
import { S3Client, GetObjectCommand } from '@aws-sdk/client-s3';
3-
import { Readable, PassThrough } from 'stream';
4-
import archiver from 'archiver';
5-
import { generateWindowsScript } from './scripts/windows';
6-
import {
7-
getPackageFilename,
8-
getReadmeContent,
9-
getScriptFilename,
10-
} from './scripts/common';
3+
import { Readable } from 'stream';
114

125
@Injectable()
136
export class DeviceAgentService {
@@ -73,56 +66,12 @@ export class DeviceAgentService {
7366
}
7467
}
7568

76-
async downloadWindowsAgent(
77-
organizationId: string,
78-
employeeId: string,
79-
): Promise<{ stream: Readable; filename: string; contentType: string }> {
69+
async downloadWindowsAgent(): Promise<{ stream: Readable; filename: string; contentType: string }> {
8070
try {
81-
this.logger.log(
82-
`Creating Windows agent zip for org ${organizationId}, employee ${employeeId}`,
83-
);
84-
85-
// Hardcoded device marker paths used by the setup scripts
86-
const fleetDevicePathWindows = 'C:\\ProgramData\\CompAI\\Fleet';
87-
88-
// Generate the Windows setup script
89-
const script = generateWindowsScript({
90-
orgId: organizationId,
91-
employeeId: employeeId,
92-
fleetDevicePath: fleetDevicePathWindows,
93-
});
94-
95-
// Create a passthrough stream for the response
96-
const passThrough = new PassThrough();
97-
const archive = archiver('zip', { zlib: { level: 9 } });
98-
99-
// Pipe archive to passthrough
100-
archive.pipe(passThrough);
101-
102-
// Error handling for the archive
103-
archive.on('error', (err) => {
104-
this.logger.error('Archive error:', err);
105-
passThrough.destroy(err);
106-
});
107-
108-
archive.on('warning', (warn) => {
109-
this.logger.warn('Archive warning:', warn);
110-
});
111-
112-
// Add script file
113-
const scriptFilename = getScriptFilename('windows');
114-
archive.append(script, { name: scriptFilename, mode: 0o755 });
115-
116-
// Add README
117-
const readmeContent = getReadmeContent('windows');
118-
archive.append(readmeContent, { name: 'README.txt' });
119-
120-
// Get MSI package from S3 and stream it into the zip
121-
const windowsPackageFilename = 'fleet-osquery.msi';
71+
const windowsPackageFilename = 'Comp AI Agent 1.0.0.exe';
12272
const packageKey = `windows/${windowsPackageFilename}`;
123-
const packageFilename = getPackageFilename('windows');
12473

125-
this.logger.log(`Downloading Windows MSI from S3: ${packageKey}`);
74+
this.logger.log(`Downloading Windows agent from S3: ${packageKey}`);
12675

12776
const getObjectCommand = new GetObjectCommand({
12877
Bucket: this.fleetBucketName,
@@ -131,31 +80,27 @@ export class DeviceAgentService {
13180

13281
const s3Response = await this.s3Client.send(getObjectCommand);
13382

134-
if (s3Response.Body) {
135-
const s3Stream = s3Response.Body as Readable;
136-
s3Stream.on('error', (err) => {
137-
this.logger.error('S3 stream error:', err);
138-
passThrough.destroy(err);
139-
});
140-
archive.append(s3Stream, { name: packageFilename, store: true });
141-
} else {
142-
this.logger.warn(
143-
'Windows MSI file not found in S3, creating zip without MSI',
144-
);
83+
if (!s3Response.Body) {
84+
throw new NotFoundException('Windows agent executable file not found in S3');
14585
}
14686

147-
// Finalize the archive
148-
archive.finalize();
87+
// Use S3 stream directly as Node.js Readable
88+
const s3Stream = s3Response.Body as Readable;
14989

150-
this.logger.log('Successfully created Windows agent zip');
90+
this.logger.log(
91+
`Successfully retrieved Windows agent: ${windowsPackageFilename}`,
92+
);
15193

15294
return {
153-
stream: passThrough,
154-
filename: `compai-device-agent-windows.zip`,
155-
contentType: 'application/zip',
95+
stream: s3Stream,
96+
filename: windowsPackageFilename,
97+
contentType: 'application/octet-stream',
15698
};
15799
} catch (error) {
158-
this.logger.error('Failed to create Windows agent zip:', error);
100+
if (error instanceof NotFoundException) {
101+
throw error;
102+
}
103+
this.logger.error('Failed to download Windows agent from S3:', error);
159104
throw error;
160105
}
161106
}

apps/api/src/device-agent/scripts/common.ts

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,38 +7,3 @@ export function getScriptFilename(os: SupportedOS): string {
77
export function getPackageFilename(os: SupportedOS): string {
88
return os === 'macos' ? 'compai-device-agent.pkg' : 'compai-device-agent.msi';
99
}
10-
11-
export function getReadmeContent(os: SupportedOS): string {
12-
if (os === 'macos') {
13-
return `Installation Instructions for macOS:
14-
15-
1. First, run the setup script by double-clicking "run_me_first.command"
16-
- This will create the necessary organization markers for device management
17-
- You may need to allow the script to run in System Preferences > Security & Privacy
18-
19-
2. Then, install the agent by double-clicking "compai-device-agent.pkg"
20-
- Follow the installation wizard
21-
- You may need to allow the installer in System Preferences > Security & Privacy
22-
23-
3. The agent will start automatically after installation
24-
`;
25-
}
26-
27-
return `Installation Instructions for Windows:
28-
29-
1. First, run the setup script:
30-
- Right-click on "run_me_first.bat" and select "Run as administrator" (required)
31-
- This writes organization markers to the device and registry
32-
- If prompted by SmartScreen, click "More info" -> "Run anyway"
33-
34-
2. Then, install the agent:
35-
- Double-click "compai-device-agent.msi" and follow the wizard
36-
37-
3. Troubleshooting:
38-
- If setup fails, open the log at: %ProgramData%\\CompAI\\Fleet or %Public%\\CompAI\\Fleet -> setup.log
39-
- Ensure your antivirus or endpoint protection allows running local .bat files
40-
- If you cannot run as administrator, ask IT to assist or install both files and registry keys manually
41-
42-
4. After installation, the agent will start automatically.
43-
`;
44-
}

0 commit comments

Comments
 (0)