apteva 0.4.16 → 0.4.17

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/dist/index.html CHANGED
@@ -11,6 +11,6 @@
11
11
  </head>
12
12
  <body>
13
13
  <div id="root"></div>
14
- <script type="module" src="/App.2194efgj.js"></script>
14
+ <script type="module" src="/App.fq4xbpcz.js"></script>
15
15
  </body>
16
16
  </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apteva",
3
- "version": "0.4.16",
3
+ "version": "0.4.17",
4
4
  "description": "Run AI agents locally. Multi-provider support for Claude, GPT, Gemini, Llama, and more.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/src/server.ts CHANGED
@@ -158,8 +158,8 @@ async function cleanupOrphanedProcesses(): Promise<void> {
158
158
  }
159
159
  }
160
160
 
161
- // Run cleanup (don't block startup)
162
- cleanupOrphanedProcesses().catch(() => {});
161
+ // Run cleanup (must complete before auto-restart to avoid killing freshly started agents)
162
+ await cleanupOrphanedProcesses().catch(() => {});
163
163
 
164
164
  // In-memory store for running agent processes (agent_id -> { process, port })
165
165
  export const agentProcesses: Map<string, { proc: Subprocess; port: number }> = new Map();
package/src/web/App.tsx CHANGED
@@ -7,7 +7,7 @@ import type { Agent, Provider, Route, NewAgentForm } from "./types";
7
7
  import { DEFAULT_FEATURES } from "./types";
8
8
 
9
9
  // Context
10
- import { TelemetryProvider, AuthProvider, ProjectProvider, useAuth, useProjects, useAgentStatusChange } from "./context";
10
+ import { TelemetryProvider, AuthProvider, ProjectProvider, useAuth, useProjects, useAgentStatusChange, useTaskChange } from "./context";
11
11
 
12
12
  // Hooks
13
13
  import { useAgents, useProviders, useOnboarding } from "./hooks";
@@ -39,6 +39,7 @@ function AppContent() {
39
39
  const { isAuthenticated, isLoading: authLoading, hasUsers, accessToken, checkAuth } = useAuth();
40
40
  const { currentProjectId, refreshProjects } = useProjects();
41
41
  const statusChangeCounter = useAgentStatusChange();
42
+ const taskChangeCounter = useTaskChange();
42
43
 
43
44
  // Onboarding state
44
45
  const { isComplete: onboardingComplete, setIsComplete: setOnboardingComplete } = useOnboarding();
@@ -107,7 +108,7 @@ function AppContent() {
107
108
  };
108
109
 
109
110
  fetchTaskCount();
110
- }, [shouldFetchData, accessToken, currentProjectId, agents, statusChangeCounter]);
111
+ }, [shouldFetchData, accessToken, currentProjectId, agents, statusChangeCounter, taskChangeCounter]);
111
112
 
112
113
  // Form state
113
114
  const [newAgent, setNewAgent] = useState<NewAgentForm>({
@@ -948,9 +948,12 @@ function HostedServices({ onServerAdded, projectId }: { onServerAdded?: () => vo
948
948
 
949
949
  const fetchStatus = async () => {
950
950
  try {
951
+ const serversUrl = projectId && projectId !== "unassigned"
952
+ ? `/api/mcp/servers?project=${encodeURIComponent(projectId)}`
953
+ : "/api/mcp/servers";
951
954
  const [providersRes, serversRes] = await Promise.all([
952
955
  authFetch("/api/providers"),
953
- authFetch("/api/mcp/servers"),
956
+ authFetch(serversUrl),
954
957
  ]);
955
958
  const providersData = await providersRes.json();
956
959
  const serversData = await serversRes.json();
@@ -1037,7 +1040,7 @@ function HostedServices({ onServerAdded, projectId }: { onServerAdded?: () => vo
1037
1040
 
1038
1041
  useEffect(() => {
1039
1042
  fetchStatus();
1040
- }, [authFetch]);
1043
+ }, [authFetch, projectId]);
1041
1044
 
1042
1045
  if (loading) {
1043
1046
  return <div className="text-center py-8 text-[#666]">Loading...</div>;
@@ -1360,9 +1363,12 @@ function AgentDojoContent({
1360
1363
  setLoadingConfigs(true);
1361
1364
  try {
1362
1365
  const projectParam = projectId && projectId !== "unassigned" ? `?project_id=${projectId}` : "";
1366
+ const serversUrl = projectId && projectId !== "unassigned"
1367
+ ? `/api/mcp/servers?project=${encodeURIComponent(projectId)}`
1368
+ : "/api/mcp/servers";
1363
1369
  const [configsRes, serversRes] = await Promise.all([
1364
1370
  authFetch(`/api/integrations/agentdojo/configs${projectParam}`),
1365
- authFetch("/api/mcp/servers"),
1371
+ authFetch(serversUrl),
1366
1372
  ]);
1367
1373
  const configsData = await configsRes.json();
1368
1374
  const serversData = await serversRes.json();
@@ -20,6 +20,7 @@ interface TelemetryContextValue {
20
20
  lastActivityByAgent: Record<string, { timestamp: string; category: string; type: string }>;
21
21
  activeAgents: Record<string, { type: string; expiresAt: number }>;
22
22
  statusChangeCounter: number;
23
+ taskChangeCounter: number;
23
24
  clearEvents: () => void;
24
25
  }
25
26
 
@@ -33,6 +34,7 @@ export function TelemetryProvider({ children }: { children: React.ReactNode }) {
33
34
  const [lastActivityByAgent, setLastActivityByAgent] = useState<Record<string, { timestamp: string; category: string; type: string }>>({});
34
35
  const [activeAgents, setActiveAgents] = useState<Record<string, { type: string; expiresAt: number }>>({});
35
36
  const [statusChangeCounter, setStatusChangeCounter] = useState(0);
37
+ const [taskChangeCounter, setTaskChangeCounter] = useState(0);
36
38
  const eventSourceRef = useRef<EventSource | null>(null);
37
39
  const reconnectTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
38
40
 
@@ -117,6 +119,11 @@ export function TelemetryProvider({ children }: { children: React.ReactNode }) {
117
119
  if (data.some((e: TelemetryEvent) => e.category === "system" && (e.type === "agent_started" || e.type === "agent_stopped"))) {
118
120
  setStatusChangeCounter(c => c + 1);
119
121
  }
122
+
123
+ // Detect task change events
124
+ if (data.some((e: TelemetryEvent) => e.category === "TASK" && (e.type === "task_created" || e.type === "task_updated" || e.type === "task_deleted"))) {
125
+ setTaskChangeCounter(c => c + 1);
126
+ }
120
127
  }
121
128
  } catch {
122
129
  // Ignore parse errors (likely keepalive or empty message)
@@ -162,7 +169,7 @@ export function TelemetryProvider({ children }: { children: React.ReactNode }) {
162
169
  }, []);
163
170
 
164
171
  return (
165
- <TelemetryContext.Provider value={{ connected, events, lastActivityByAgent, activeAgents, statusChangeCounter, clearEvents }}>
172
+ <TelemetryContext.Provider value={{ connected, events, lastActivityByAgent, activeAgents, statusChangeCounter, taskChangeCounter, clearEvents }}>
166
173
  {children}
167
174
  </TelemetryContext.Provider>
168
175
  );
@@ -235,3 +242,9 @@ export function useAgentStatusChange(): number {
235
242
  const { statusChangeCounter } = useTelemetryContext();
236
243
  return statusChangeCounter;
237
244
  }
245
+
246
+ // Hook to trigger task count refetch on task mutations
247
+ export function useTaskChange(): number {
248
+ const { taskChangeCounter } = useTelemetryContext();
249
+ return taskChangeCounter;
250
+ }
@@ -1,4 +1,4 @@
1
- export { TelemetryProvider, useTelemetryContext, useTelemetry, useAgentActivity, useAgentStatusChange } from "./TelemetryContext";
1
+ export { TelemetryProvider, useTelemetryContext, useTelemetry, useAgentActivity, useAgentStatusChange, useTaskChange } from "./TelemetryContext";
2
2
  export type { TelemetryEvent } from "./TelemetryContext";
3
3
 
4
4
  export { AuthProvider, useAuth, useAuthHeaders } from "./AuthContext";