Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/trigger-tasks-deploy-main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ jobs:
VERCEL_ACCESS_TOKEN: ${{ secrets.VERCEL_ACCESS_TOKEN }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
VERCEL_TEAM_ID: ${{ secrets.VERCEL_TEAM_ID }}
run: bunx trigger.dev@4.0.0 deploy --env staging --log-level debug
run: bunx trigger.dev@4.0.6 deploy --env staging --log-level debug
2 changes: 1 addition & 1 deletion .github/workflows/trigger-tasks-deploy-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,4 @@ jobs:
VERCEL_ACCESS_TOKEN: ${{ secrets.VERCEL_ACCESS_TOKEN }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
VERCEL_TEAM_ID: ${{ secrets.VERCEL_TEAM_ID }}
run: bunx trigger.dev@4.0.0 deploy
run: bunx trigger.dev@4.0.6 deploy
11 changes: 5 additions & 6 deletions apps/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@
"@tiptap/extension-table-cell": "^3.4.4",
"@tiptap/extension-table-header": "^3.4.4",
"@tiptap/extension-table-row": "^3.4.4",
"@trigger.dev/react-hooks": "4.0.0",
"@trigger.dev/sdk": "4.0.0",
"@trigger.dev/react-hooks": "4.0.6",
"@trigger.dev/sdk": "4.0.6",
"@trycompai/db": "^1.3.7",
"@trycompai/email": "workspace:*",
"@types/canvas-confetti": "^1.9.0",
Expand Down Expand Up @@ -117,7 +117,7 @@
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.3.0",
"@trigger.dev/build": "4.0.0",
"@trigger.dev/build": "4.0.6",
"@types/d3": "^7.4.3",
"@types/jspdf": "^2.0.0",
"@types/node": "^24.0.3",
Expand Down Expand Up @@ -156,8 +156,8 @@
"db:generate": "bun run db:getschema && prisma generate",
"db:getschema": "node ../../packages/db/scripts/combine-schemas.js && cp ../../packages/db/dist/schema.prisma prisma/schema.prisma",
"db:migrate": "cd ../../packages/db && bunx prisma migrate dev && cd ../../apps/app",
"deploy:trigger-prod": "npx trigger.dev@4.0.0 deploy",
"dev": "bun i && bunx concurrently --kill-others --names \"next,trigger\" --prefix-colors \"yellow,blue\" \"next dev --turbo -p 3000\" \"bun run trigger:dev\"",
"deploy:trigger-prod": "npx trigger.dev@4.0.6 deploy",
"dev": "bun i && bunx concurrently --kill-others --names \"next,trigger\" --prefix-colors \"yellow,blue\" \"next dev --turbo -p 3000\" \"bunx trigger.dev@4.0.6 dev\"",
"lint": "next lint && prettier --check .",
"prebuild": "bun run db:generate",
"start": "next start",
Expand All @@ -173,7 +173,6 @@
"test:e2e:ui": "playwright test --ui",
"test:ui": "vitest --ui",
"test:watch": "vitest --watch",
"trigger:dev": "npx trigger.dev@4.0.0 dev",
"typecheck": "tsc --noEmit"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ export async function executeAutomationScript(data: {
orgId: string;
taskId: string;
automationId: string;
version?: number; // Optional: test specific version
}) {
try {
const result = await callEnterpriseApi('/api/tasks-automations/trigger/execute', {
Expand Down Expand Up @@ -361,6 +362,12 @@ export async function publishAutomation(
},
});

// Enable automation if not already enabled
await db.evidenceAutomation.update({
where: { id: automationId },
data: { isEnabled: true },
});

return {
success: true,
version,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ import {
import { Label } from '@comp/ui/label';
import { Textarea } from '@comp/ui/textarea';
import { Loader2 } from 'lucide-react';
import { useParams } from 'next/navigation';
import { useParams, useRouter } from 'next/navigation';
import { useState } from 'react';
import { toast } from 'sonner';
import { publishAutomation } from '../actions/task-automation-actions';
import { executeAutomationScript, publishAutomation } from '../actions/task-automation-actions';
import { useAutomationVersions } from '../hooks/use-automation-versions';
import { useSharedChatContext } from '../lib/chat-context';

Expand All @@ -25,6 +25,7 @@ interface PublishDialogProps {
}

export function PublishDialog({ open, onOpenChange }: PublishDialogProps) {
const router = useRouter();
const { orgId, taskId } = useParams<{
orgId: string;
taskId: string;
Expand All @@ -33,8 +34,20 @@ export function PublishDialog({ open, onOpenChange }: PublishDialogProps) {
const { automationIdRef } = useSharedChatContext();
const [changelog, setChangelog] = useState('');
const [isPublishing, setIsPublishing] = useState(false);
const [showPostPublishOptions, setShowPostPublishOptions] = useState(false);
const [publishedVersion, setPublishedVersion] = useState<number | null>(null);
const { mutate } = useAutomationVersions();

const handleDialogChange = (newOpen: boolean) => {
onOpenChange(newOpen);
// Reset state when dialog closes
if (!newOpen) {
setChangelog('');
setShowPostPublishOptions(false);
setPublishedVersion(null);
}
};

const handlePublish = async () => {
setIsPublishing(true);

Expand All @@ -50,51 +63,105 @@ export function PublishDialog({ open, onOpenChange }: PublishDialogProps) {
throw new Error(result.error || 'Failed to publish');
}

toast.success(`Version ${result.version?.version} published successfully!`);
setChangelog('');
onOpenChange(false);
const versionNumber = result.version?.version;
toast.success(`Version ${versionNumber} published successfully!`);
setPublishedVersion(versionNumber || null);

// Refresh versions list
await mutate();

// Trigger a test run with the new version
if (versionNumber) {
const runResult = await executeAutomationScript({
orgId,
taskId,
automationId: automationIdRef.current,
version: versionNumber,
});

if (runResult.success) {
toast.success('Running automation with published version');
} else {
toast.error(runResult.error || 'Failed to start automation run');
}
}

// Show post-publish options instead of closing
setShowPostPublishOptions(true);
} catch (error) {
toast.error(error instanceof Error ? error.message : 'Failed to publish automation');
} finally {
setIsPublishing(false);
}
};

const handleGoToOverview = () => {
handleDialogChange(false);
router.push(`/${orgId}/tasks/${taskId}/automations/${automationIdRef.current}/overview`);
};

const handleStayHere = () => {
handleDialogChange(false);
};

return (
<Dialog open={open} onOpenChange={onOpenChange}>
<Dialog open={open} onOpenChange={handleDialogChange}>
<DialogContent>
<DialogHeader>
<DialogTitle>Publish Automation</DialogTitle>
<DialogDescription>
Create a new version of this automation. The current draft will remain editable.
</DialogDescription>
</DialogHeader>

<div className="space-y-4 py-4">
<div className="space-y-2">
<Label htmlFor="changelog">Changelog (optional)</Label>
<Textarea
id="changelog"
placeholder="Describe what changed in this version..."
value={changelog}
onChange={(e) => setChangelog(e.target.value)}
rows={4}
/>
</div>
</div>

<DialogFooter>
<Button variant="outline" onClick={() => onOpenChange(false)} disabled={isPublishing}>
Cancel
</Button>
<Button onClick={handlePublish} disabled={isPublishing}>
{isPublishing && <Loader2 className="h-4 w-4 mr-2 animate-spin" />}
{isPublishing ? 'Publishing...' : 'Publish'}
</Button>
</DialogFooter>
{!showPostPublishOptions ? (
<>
<DialogHeader>
<DialogTitle>Publish Automation</DialogTitle>
<DialogDescription>
Create a new version of this automation. The current draft will remain editable.
</DialogDescription>
</DialogHeader>

<div className="space-y-4 py-4">
<div className="space-y-2">
<Label htmlFor="changelog">Changelog (optional)</Label>
<Textarea
id="changelog"
placeholder="Describe what changed in this version..."
value={changelog}
onChange={(e) => setChangelog(e.target.value)}
rows={4}
/>
</div>
</div>

<DialogFooter>
<Button
variant="outline"
onClick={() => handleDialogChange(false)}
disabled={isPublishing}
>
Cancel
</Button>
<Button onClick={handlePublish} disabled={isPublishing}>
{isPublishing && <Loader2 className="h-4 w-4 mr-2 animate-spin" />}
{isPublishing ? 'Publishing...' : 'Publish'}
</Button>
</DialogFooter>
</>
) : (
<>
<DialogHeader>
<DialogTitle>Automation Published!</DialogTitle>
<DialogDescription>
Version {publishedVersion} has been published and is now running. Where would you like to go?
</DialogDescription>
</DialogHeader>

<DialogFooter className="flex-col sm:flex-row gap-2">
<Button variant="outline" onClick={handleStayHere} className="w-full sm:w-auto">
Stay Here
</Button>
<Button onClick={handleGoToOverview} className="w-full sm:w-auto">
Go to Overview
</Button>
</DialogFooter>
</>
)}
</DialogContent>
</Dialog>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
'use client';

import { CheckCircle2, FileText, Loader2, XCircle } from 'lucide-react';
import { useEffect, useState } from 'react';

interface FileWritingActivityProps {
input: any;
state: 'input-streaming' | 'input-available' | 'output-available' | 'output-error';
output?: any;
isAnimating: boolean;
}

export function FileWritingActivity({
input,
state,
output,
isAnimating,
}: FileWritingActivityProps) {
const isComplete = state === 'output-available';
const isError = state === 'output-error';
const isLoading = state === 'input-streaming' || state === 'input-available';
const [startTime] = useState(() => Date.now());
const [duration, setDuration] = useState<number | null>(null);
const [isExpanded, setIsExpanded] = useState(false);

// Track actual timing
useEffect(() => {
if ((isComplete || isError) && duration === null) {
const elapsed = Math.round((Date.now() - startTime) / 1000);
setDuration(elapsed);
}
}, [isComplete, isError, startTime, duration]);

const getIcon = () => {
if (isError) return <XCircle className="h-4 w-4 text-muted-foreground" />;
if (isComplete) return <CheckCircle2 className="h-4 w-4 text-muted-foreground" />;
if (isLoading) return <Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />;
return <FileText className="h-4 w-4 text-muted-foreground" />;
};

const getTitle = () => {
if (isError) {
return duration ? `Failed to save after ${duration}s` : 'Failed to save automation';
}

if (isComplete && duration !== null) {
return `Saved in ${duration}s`;
}
return 'Creating automation...';
};

const getResultSummary = () => {
// Only show summary when complete and available
if (!isComplete || !output?.summary) return null;

return (
<div className="mt-2">
<p className="text-xs text-muted-foreground">{output.summary}</p>
</div>
);
};

return (
<div className="py-0.5">
<button
type="button"
className="flex items-center gap-2 text-xs text-muted-foreground hover:text-foreground transition-colors"
onClick={() => setIsExpanded(!isExpanded)}
>
<div className="w-1 h-1 rounded-full bg-muted-foreground/40" />
<span>{getTitle()}</span>
</button>
{isExpanded && (isComplete || isError) && output?.summary && (
<div className="mt-1 ml-3 text-xs text-muted-foreground/80 leading-relaxed">
{output.summary}
</div>
)}
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { memo } from 'react';
import { DataPart } from '../../../lib/types/data-parts';
import { Metadata } from '../../../lib/types/metadata';
import { TaskAutomationToolSet } from '../../../tools/task-automation-tools';
import { FileWritingActivity } from './file-writing-activity';
import { PromptInfo } from './prompt-info';
import { PromptSecret } from './prompt-secret';
import { Reasoning } from './reasoning';
Expand Down Expand Up @@ -62,6 +63,15 @@ export const MessagePart = memo(function MessagePart({
isAnimating={partIndex === 0}
/>
);
} else if (part.type === 'tool-storeToS3') {
return (
<FileWritingActivity
input={part.input}
state={part.state}
output={part.output}
isAnimating={partIndex === 0}
/>
);
}
return null;
});
Loading
Loading