Skip to content

Commit 4ad255a

Browse files
committed
chore: cleanup and add automations
1 parent 217eecb commit 4ad255a

File tree

21 files changed

+502
-132
lines changed

21 files changed

+502
-132
lines changed

apps/api/src/tasks/tasks.controller.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,4 +497,66 @@ export class TasksController {
497497
message: 'Attachment deleted successfully',
498498
};
499499
}
500+
501+
// ==================== AUTOMATION RUNS ====================
502+
503+
@Get(':taskId/automation-runs')
504+
@ApiOperation({
505+
summary: 'Get all automation runs for a task',
506+
description: 'Retrieve all evidence automation runs for a specific task',
507+
})
508+
@ApiParam({
509+
name: 'taskId',
510+
description: 'Task ID',
511+
example: 'tsk_abc123def456',
512+
})
513+
@ApiResponse({
514+
status: 200,
515+
description: 'Automation runs retrieved successfully',
516+
content: {
517+
'application/json': {
518+
schema: {
519+
type: 'array',
520+
items: {
521+
type: 'object',
522+
properties: {
523+
id: { type: 'string', example: 'ear_abc123def456' },
524+
status: {
525+
type: 'string',
526+
enum: ['PENDING', 'RUNNING', 'COMPLETED', 'FAILED'],
527+
},
528+
trigger: {
529+
type: 'string',
530+
enum: ['MANUAL', 'SCHEDULED', 'EVENT'],
531+
},
532+
createdAt: { type: 'string', format: 'date-time' },
533+
completedAt: {
534+
type: 'string',
535+
format: 'date-time',
536+
nullable: true,
537+
},
538+
error: { type: 'object', nullable: true },
539+
},
540+
},
541+
},
542+
},
543+
},
544+
})
545+
@ApiResponse({
546+
status: 401,
547+
description: 'Unauthorized',
548+
})
549+
@ApiResponse({
550+
status: 404,
551+
description: 'Task not found',
552+
})
553+
async getTaskAutomationRuns(
554+
@OrganizationId() organizationId: string,
555+
@Param('taskId') taskId: string,
556+
) {
557+
return await this.tasksService.getTaskAutomationRuns(
558+
organizationId,
559+
taskId,
560+
);
561+
}
500562
}

apps/api/src/tasks/tasks.service.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,23 @@ export class TasksService {
8686
throw new BadRequestException('Task not found or access denied');
8787
}
8888
}
89+
90+
/**
91+
* Get all automation runs for a task
92+
*/
93+
async getTaskAutomationRuns(organizationId: string, taskId: string) {
94+
// Verify task access
95+
await this.verifyTaskAccess(organizationId, taskId);
96+
97+
const runs = await db.evidenceAutomationRun.findMany({
98+
where: {
99+
taskId,
100+
},
101+
orderBy: {
102+
createdAt: 'desc',
103+
},
104+
});
105+
106+
return runs;
107+
}
89108
}

apps/app/next.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ const config: NextConfig = {
3939
process.env.NODE_ENV === 'production' && process.env.STATIC_ASSETS_URL
4040
? `${process.env.STATIC_ASSETS_URL}/app`
4141
: '',
42-
reactStrictMode: true,
42+
reactStrictMode: false,
4343
transpilePackages: ['@trycompai/db', '@prisma/client'],
4444
images: {
4545
remotePatterns: [

apps/app/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"@ai-sdk/groq": "^2.0.0",
77
"@ai-sdk/openai": "^2.0.0",
88
"@ai-sdk/provider": "^2.0.0",
9-
"@ai-sdk/react": "^2.0.0",
9+
"@ai-sdk/react": "^2.0.60",
1010
"@ai-sdk/rsc": "^1.0.0",
1111
"@aws-sdk/client-lambda": "^3.891.0",
1212
"@aws-sdk/client-s3": "^3.859.0",
@@ -59,12 +59,13 @@
5959
"@upstash/ratelimit": "^2.0.5",
6060
"@vercel/sandbox": "^0.0.21",
6161
"@vercel/sdk": "^1.7.1",
62-
"ai": "^5.0.0",
62+
"ai": "^5.0.60",
6363
"axios": "^1.9.0",
6464
"better-auth": "^1.2.8",
6565
"botid": "^1.5.5",
6666
"canvas-confetti": "^1.9.3",
6767
"d3": "^7.9.0",
68+
"date-fns": "^4.1.0",
6869
"dub": "^0.66.1",
6970
"framer-motion": "^12.18.1",
7071
"geist": "^1.3.1",

apps/app/src/app/(app)/[orgId]/tasks/[taskId]/automation/[automationId]/chat.tsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,15 @@ export function Chat({ className, orgId, taskId, taskName, automationId }: Props
131131
{
132132
text: `I've added the secret "${secretName}". You can now use it in the automation script.`,
133133
},
134-
{ body: { modelId: 'openai/gpt-5-mini', reasoningEffort: 'medium', orgId, taskId } },
134+
{
135+
body: {
136+
modelId: 'openai/gpt-5-mini',
137+
reasoningEffort: 'medium',
138+
orgId,
139+
taskId,
140+
automationId,
141+
},
142+
},
135143
);
136144
},
137145
[sendMessage, orgId, taskId],
@@ -149,7 +157,15 @@ export function Chat({ className, orgId, taskId, taskName, automationId }: Props
149157
{
150158
text: `I've provided the following information:\n\n${infoText}\n\nYou can now continue with creating the automation script.`,
151159
},
152-
{ body: { modelId: 'openai/gpt-5-mini', reasoningEffort: 'medium', orgId, taskId } },
160+
{
161+
body: {
162+
modelId: 'openai/gpt-5-mini',
163+
reasoningEffort: 'medium',
164+
orgId,
165+
taskId,
166+
automationId,
167+
},
168+
},
153169
);
154170
},
155171
[sendMessage, orgId, taskId],

apps/app/src/app/(app)/[orgId]/tasks/[taskId]/automation/[automationId]/components/chat/message-part/prompt-info.tsx

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { AlertCircle, CheckCircle2, Info } from 'lucide-react';
2-
import { memo, useEffect, useState } from 'react';
2+
import { memo, useState } from 'react';
33
import { toast } from 'sonner';
44
import { Button } from '../../ui/button';
55
import { Input } from '../../ui/input';
@@ -37,22 +37,18 @@ export const PromptInfo = memo(function PromptInfo({
3737
}
3838
: null;
3939

40-
const [values, setValues] = useState<Record<string, string>>({});
4140
const [isSubmitting, setIsSubmitting] = useState(false);
4241
const [isComplete, setIsComplete] = useState(false);
43-
const [isInitialized, setIsInitialized] = useState(false);
4442

45-
// Initialize values from props only once
46-
useEffect(() => {
47-
if (infoData?.fields && !isInitialized) {
48-
const initial: Record<string, string> = {};
49-
infoData.fields.forEach((field: FieldInfo) => {
50-
initial[field.name] = field.defaultValue || '';
51-
});
52-
setValues(initial);
53-
setIsInitialized(true);
54-
}
55-
}, [infoData, isInitialized]);
43+
// Initialize values from props only once on mount
44+
const [values, setValues] = useState<Record<string, string>>(() => {
45+
if (!infoData?.fields) return {};
46+
const initial: Record<string, string> = {};
47+
infoData.fields.forEach((field: FieldInfo) => {
48+
initial[field.name] = field.defaultValue || '';
49+
});
50+
return initial;
51+
});
5652

5753
const handleSubmit = async () => {
5854
// Validate required fields

apps/app/src/app/(app)/[orgId]/tasks/[taskId]/automation/[automationId]/components/chat/message-part/prompt-secret.tsx

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { AlertCircle, CheckCircle2, Key } from 'lucide-react';
2-
import { memo, useEffect, useState } from 'react';
2+
import { memo, useState } from 'react';
33
import { toast } from 'sonner';
44
import { Button } from '../../ui/button';
55
import { Input } from '../../ui/input';
@@ -33,21 +33,13 @@ export const PromptSecret = memo(function PromptSecret({
3333
}
3434
: null;
3535

36-
// Use the secret name from AI or allow user to set one
37-
const [name, setName] = useState('');
36+
// Use the secret name from AI or allow user to set one - initialize on mount only
37+
const [name, setName] = useState(() => secretData?.secretName || '');
3838
const [value, setValue] = useState('');
39-
const [description, setDescription] = useState('');
39+
const [description, setDescription] = useState(() => secretData?.description || '');
4040
const [isSubmitting, setIsSubmitting] = useState(false);
4141
const [isComplete, setIsComplete] = useState(false);
4242

43-
// Initialize state from props only once
44-
useEffect(() => {
45-
if (secretData && !name && !description) {
46-
setName(secretData.secretName || '');
47-
setDescription(secretData.description || '');
48-
}
49-
}, [secretData, name, description]);
50-
5143
// Use the provided secret name or the user-entered one
5244
const finalSecretName = secretData?.secretName || name;
5345

apps/app/src/app/(app)/[orgId]/tasks/[taskId]/automation/[automationId]/components/workflow/workflow-visualizer-simple.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,15 @@ Please fix the automation script to resolve this error.`;
139139
// Send the error to the chat
140140
sendMessage(
141141
{ text: errorMessage },
142-
{ body: { modelId: 'openai/gpt-5-mini', reasoningEffort: 'medium', orgId, taskId } },
142+
{
143+
body: {
144+
modelId: 'openai/gpt-5-mini',
145+
reasoningEffort: 'medium',
146+
orgId,
147+
taskId,
148+
automationId,
149+
},
150+
},
143151
);
144152

145153
// Close the dialog

apps/app/src/app/(app)/[orgId]/tasks/[taskId]/automation/[automationId]/lib/chat-context.tsx

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import { Chat } from '@ai-sdk/react';
44
import { DataUIPart, DefaultChatTransport } from 'ai';
5-
import { useParams } from 'next/navigation';
65
import { createContext, useContext, useMemo, useRef, type ReactNode } from 'react';
76
import { toast } from 'sonner';
87
import { mutate } from 'swr';
@@ -20,11 +19,6 @@ export function ChatProvider({ children }: { children: ReactNode }) {
2019
const mapDataToState = useTaskAutomationDataMapper();
2120
const mapDataToStateRef = useRef(mapDataToState);
2221
mapDataToStateRef.current = mapDataToState;
23-
const { orgId, taskId, automationId } = useParams<{
24-
orgId: string;
25-
taskId: string;
26-
automationId: string;
27-
}>();
2822

2923
const baseUrl = process.env.NEXT_PUBLIC_ENTERPRISE_API_URL;
3024
const url = `${baseUrl}/api/tasks-automations/chat`;
@@ -34,20 +28,12 @@ export function ChatProvider({ children }: { children: ReactNode }) {
3428
new Chat<ChatUIMessage>({
3529
transport: new DefaultChatTransport({
3630
api: url,
37-
body: {
38-
orgId,
39-
taskId,
40-
automationId,
41-
},
4231
}),
4332
onToolCall: () => mutate(`/api/auth/info`),
4433
onData: (data: DataUIPart<DataPart>) => mapDataToStateRef.current(data),
4534
onError: (error) => {
46-
// Use setTimeout to avoid triggering state updates during render
47-
setTimeout(() => {
48-
toast.error(`Communication error with the AI: ${error.message}`);
49-
console.error('Error sending message:', error);
50-
}, 0);
35+
toast.error(`Communication error with the AI: ${error.message}`);
36+
console.error('Error sending message:', error);
5137
},
5238
}),
5339
[],

apps/app/src/app/(app)/[orgId]/tasks/[taskId]/automation/[automationId]/lib/task-automation-store.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ export const useTaskAutomationStore = create<TaskAutomationStore>()((set) => ({
3131
scriptUrl: undefined,
3232

3333
// Actions
34-
setChatStatus: (status) =>
35-
set((state) => (state.chatStatus === status ? state : { chatStatus: status })),
34+
setChatStatus: (status) => set({ chatStatus: status }),
3635

3736
setScriptGenerated: (generated, path) =>
3837
set({

0 commit comments

Comments
 (0)