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.
Files changed (44) hide show
  1. package/README.md +129 -47
  2. package/package.json +1 -1
  3. package/public/readme/cost-usage-list.png +0 -0
  4. package/public/readme/dashboard-bulk-select.png +0 -0
  5. package/public/readme/dashboard-card-edit.png +0 -0
  6. package/public/readme/dashboard-create-form-ai-applied.png +0 -0
  7. package/public/readme/dashboard-create-form-ai-assist.png +0 -0
  8. package/public/readme/dashboard-create-form-empty.png +0 -0
  9. package/public/readme/dashboard-create-form-filled.png +0 -0
  10. package/public/readme/dashboard-filtered.png +0 -0
  11. package/public/readme/dashboard-list.png +0 -0
  12. package/public/readme/dashboard-sorted.png +0 -0
  13. package/public/readme/dashboard-workflow-confirm.png +0 -0
  14. package/public/readme/documents-grid.png +0 -0
  15. package/public/readme/documents-list.png +0 -0
  16. package/public/readme/home-below-fold.png +0 -0
  17. package/public/readme/home-list.png +0 -0
  18. package/public/readme/inbox-list.png +0 -0
  19. package/public/readme/monitor-list.png +0 -0
  20. package/public/readme/profiles-list.png +0 -0
  21. package/public/readme/projects-detail.png +0 -0
  22. package/public/readme/projects-list.png +0 -0
  23. package/public/readme/schedules-list.png +0 -0
  24. package/public/readme/settings-list.png +0 -0
  25. package/public/readme/workflows-list.png +0 -0
  26. package/src/app/api/workflows/from-assist/route.ts +143 -0
  27. package/src/app/dashboard/page.tsx +24 -2
  28. package/src/app/workflows/from-assist/page.tsx +35 -0
  29. package/src/components/projects/project-card.tsx +47 -35
  30. package/src/components/tasks/ai-assist-panel.tsx +31 -10
  31. package/src/components/tasks/task-card.tsx +16 -1
  32. package/src/components/tasks/task-create-panel.tsx +39 -0
  33. package/src/components/workflows/workflow-confirmation-view.tsx +447 -0
  34. package/src/lib/agents/profiles/__tests__/suggest.test.ts +67 -0
  35. package/src/lib/agents/profiles/suggest.ts +36 -0
  36. package/src/lib/agents/runtime/claude.ts +36 -6
  37. package/src/lib/agents/runtime/task-assist-types.ts +12 -2
  38. package/src/lib/data/__tests__/clear.test.ts +42 -0
  39. package/src/lib/data/clear.ts +3 -0
  40. package/src/lib/notifications/permissions.ts +6 -2
  41. package/src/lib/workflows/__tests__/assist-builder.test.ts +255 -0
  42. package/src/lib/workflows/assist-builder.ts +248 -0
  43. package/src/lib/workflows/assist-session.ts +78 -0
  44. 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: agentProfile ?? null,
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
  */