stagent 0.1.9 → 0.1.10
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 +129 -47
- package/package.json +1 -1
- package/public/readme/cost-usage-list.png +0 -0
- package/public/readme/dashboard-bulk-select.png +0 -0
- package/public/readme/dashboard-card-edit.png +0 -0
- package/public/readme/dashboard-create-form-ai-applied.png +0 -0
- package/public/readme/dashboard-create-form-ai-assist.png +0 -0
- package/public/readme/dashboard-create-form-empty.png +0 -0
- package/public/readme/dashboard-create-form-filled.png +0 -0
- package/public/readme/dashboard-filtered.png +0 -0
- package/public/readme/dashboard-list.png +0 -0
- package/public/readme/dashboard-sorted.png +0 -0
- package/public/readme/dashboard-workflow-confirm.png +0 -0
- package/public/readme/documents-grid.png +0 -0
- package/public/readme/documents-list.png +0 -0
- package/public/readme/home-below-fold.png +0 -0
- package/public/readme/home-list.png +0 -0
- package/public/readme/inbox-list.png +0 -0
- package/public/readme/monitor-list.png +0 -0
- package/public/readme/profiles-list.png +0 -0
- package/public/readme/projects-detail.png +0 -0
- package/public/readme/projects-list.png +0 -0
- package/public/readme/schedules-list.png +0 -0
- package/public/readme/settings-list.png +0 -0
- package/public/readme/workflows-list.png +0 -0
- package/src/app/api/workflows/from-assist/route.ts +143 -0
- package/src/app/dashboard/page.tsx +24 -2
- package/src/app/workflows/from-assist/page.tsx +35 -0
- package/src/components/projects/project-card.tsx +47 -35
- package/src/components/tasks/ai-assist-panel.tsx +31 -10
- package/src/components/tasks/task-card.tsx +16 -1
- package/src/components/tasks/task-create-panel.tsx +39 -0
- package/src/components/workflows/workflow-confirmation-view.tsx +447 -0
- package/src/lib/agents/profiles/__tests__/suggest.test.ts +67 -0
- package/src/lib/agents/profiles/suggest.ts +36 -0
- package/src/lib/agents/runtime/claude.ts +36 -6
- package/src/lib/agents/runtime/task-assist-types.ts +12 -2
- package/src/lib/data/__tests__/clear.test.ts +42 -0
- package/src/lib/data/clear.ts +3 -0
- package/src/lib/notifications/permissions.ts +6 -2
- package/src/lib/workflows/__tests__/assist-builder.test.ts +255 -0
- package/src/lib/workflows/assist-builder.ts +248 -0
- package/src/lib/workflows/assist-session.ts +78 -0
- package/src/lib/workflows/engine.ts +46 -1
|
@@ -2,6 +2,7 @@ import { db } from "@/lib/db";
|
|
|
2
2
|
import { workflows, tasks, agentLogs, notifications } from "@/lib/db/schema";
|
|
3
3
|
import { eq } from "drizzle-orm";
|
|
4
4
|
import { executeTaskWithRuntime } from "@/lib/agents/runtime";
|
|
5
|
+
import { classifyTaskProfile } from "@/lib/agents/router";
|
|
5
6
|
import type { WorkflowDefinition, WorkflowState, StepState, LoopState } from "./types";
|
|
6
7
|
import { createInitialState } from "./types";
|
|
7
8
|
import { executeLoop } from "./loop-executor";
|
|
@@ -47,6 +48,8 @@ export async function executeWorkflow(workflowId: string): Promise<void> {
|
|
|
47
48
|
try {
|
|
48
49
|
await executeLoop(workflowId, definition);
|
|
49
50
|
|
|
51
|
+
await syncSourceTaskStatus(workflowId, "completed");
|
|
52
|
+
|
|
50
53
|
await db.insert(agentLogs).values({
|
|
51
54
|
id: crypto.randomUUID(),
|
|
52
55
|
taskId: null,
|
|
@@ -56,6 +59,8 @@ export async function executeWorkflow(workflowId: string): Promise<void> {
|
|
|
56
59
|
timestamp: new Date(),
|
|
57
60
|
});
|
|
58
61
|
} catch (error) {
|
|
62
|
+
await syncSourceTaskStatus(workflowId, "failed");
|
|
63
|
+
|
|
59
64
|
await db.insert(agentLogs).values({
|
|
60
65
|
id: crypto.randomUUID(),
|
|
61
66
|
taskId: null,
|
|
@@ -94,6 +99,9 @@ export async function executeWorkflow(workflowId: string): Promise<void> {
|
|
|
94
99
|
state.completedAt = new Date().toISOString();
|
|
95
100
|
await updateWorkflowState(workflowId, state, "completed");
|
|
96
101
|
|
|
102
|
+
// Sync parent task status
|
|
103
|
+
await syncSourceTaskStatus(workflowId, "completed");
|
|
104
|
+
|
|
97
105
|
await db.insert(agentLogs).values({
|
|
98
106
|
id: crypto.randomUUID(),
|
|
99
107
|
taskId: null,
|
|
@@ -106,6 +114,9 @@ export async function executeWorkflow(workflowId: string): Promise<void> {
|
|
|
106
114
|
state.status = "failed";
|
|
107
115
|
await updateWorkflowState(workflowId, state, "failed");
|
|
108
116
|
|
|
117
|
+
// Sync parent task status
|
|
118
|
+
await syncSourceTaskStatus(workflowId, "failed");
|
|
119
|
+
|
|
109
120
|
await db.insert(agentLogs).values({
|
|
110
121
|
id: crypto.randomUUID(),
|
|
111
122
|
taskId: null,
|
|
@@ -682,6 +693,12 @@ export async function executeChildTask(
|
|
|
682
693
|
.from(workflows)
|
|
683
694
|
.where(eq(workflows.id, workflowId));
|
|
684
695
|
|
|
696
|
+
// Resolve "auto" profile via multi-agent router
|
|
697
|
+
const resolvedProfile =
|
|
698
|
+
!agentProfile || agentProfile === "auto"
|
|
699
|
+
? classifyTaskProfile(name, prompt, assignedAgent)
|
|
700
|
+
: agentProfile;
|
|
701
|
+
|
|
685
702
|
const taskId = crypto.randomUUID();
|
|
686
703
|
await db.insert(tasks).values({
|
|
687
704
|
id: taskId,
|
|
@@ -693,7 +710,7 @@ export async function executeChildTask(
|
|
|
693
710
|
status: "queued",
|
|
694
711
|
priority: 1,
|
|
695
712
|
assignedAgent: assignedAgent ?? null,
|
|
696
|
-
agentProfile:
|
|
713
|
+
agentProfile: resolvedProfile ?? null,
|
|
697
714
|
createdAt: new Date(),
|
|
698
715
|
updatedAt: new Date(),
|
|
699
716
|
});
|
|
@@ -811,6 +828,34 @@ async function waitForApproval(
|
|
|
811
828
|
return false; // Timeout — treat as denied
|
|
812
829
|
}
|
|
813
830
|
|
|
831
|
+
/**
|
|
832
|
+
* Sync the parent (source) task's status with the workflow's final status.
|
|
833
|
+
* The parent task is linked via `sourceTaskId` in the workflow's definition JSON.
|
|
834
|
+
*/
|
|
835
|
+
async function syncSourceTaskStatus(
|
|
836
|
+
workflowId: string,
|
|
837
|
+
status: "completed" | "failed"
|
|
838
|
+
): Promise<void> {
|
|
839
|
+
try {
|
|
840
|
+
const [workflow] = await db
|
|
841
|
+
.select()
|
|
842
|
+
.from(workflows)
|
|
843
|
+
.where(eq(workflows.id, workflowId));
|
|
844
|
+
|
|
845
|
+
if (!workflow) return;
|
|
846
|
+
|
|
847
|
+
const def = JSON.parse(workflow.definition);
|
|
848
|
+
if (!def.sourceTaskId) return;
|
|
849
|
+
|
|
850
|
+
await db
|
|
851
|
+
.update(tasks)
|
|
852
|
+
.set({ status, updatedAt: new Date() })
|
|
853
|
+
.where(eq(tasks.id, def.sourceTaskId));
|
|
854
|
+
} catch (error) {
|
|
855
|
+
console.error(`[workflow-engine] Failed to sync source task status for workflow ${workflowId}:`, error);
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
|
|
814
859
|
/**
|
|
815
860
|
* Update workflow state in the database.
|
|
816
861
|
*/
|