Skip to content

Commit 0399e76

Browse files
authored
feat(cloud): cloud task service & rendering (#932)
1 parent e97cb30 commit 0399e76

File tree

30 files changed

+1756
-59
lines changed

30 files changed

+1756
-59
lines changed

apps/twig/src/api/posthogClient.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ export class PostHogAPIClient {
354354
task_id: taskId,
355355
id: runId,
356356
},
357-
body: updates,
357+
body: updates as Record<string, unknown>,
358358
},
359359
);
360360
return data as unknown as TaskRun;
@@ -383,6 +383,40 @@ export class PostHogAPIClient {
383383
}
384384
}
385385

386+
async getTaskRunSessionLogs(
387+
taskId: string,
388+
runId: string,
389+
options?: { limit?: number; after?: string },
390+
): Promise<StoredLogEntry[]> {
391+
try {
392+
const teamId = await this.getTeamId();
393+
const url = new URL(
394+
`${this.api.baseUrl}/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/session_logs/`,
395+
);
396+
url.searchParams.set("limit", String(options?.limit ?? 5000));
397+
if (options?.after) {
398+
url.searchParams.set("after", options.after);
399+
}
400+
const response = await this.api.fetcher.fetch({
401+
method: "get",
402+
url,
403+
path: `/api/projects/${teamId}/tasks/${taskId}/runs/${runId}/session_logs/`,
404+
});
405+
406+
if (!response.ok) {
407+
log.warn(
408+
`Failed to fetch session logs: ${response.status} ${response.statusText}`,
409+
);
410+
return [];
411+
}
412+
413+
return (await response.json()) as StoredLogEntry[];
414+
} catch (err) {
415+
log.warn("Failed to fetch task run session logs", err);
416+
return [];
417+
}
418+
}
419+
386420
async getTaskLogs(taskId: string): Promise<StoredLogEntry[]> {
387421
try {
388422
const task = (await this.getTask(taskId)) as unknown as Task;

apps/twig/src/main/di/container.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import "reflect-metadata";
22
import { Container } from "inversify";
33
import { AgentService } from "../services/agent/service.js";
44
import { AppLifecycleService } from "../services/app-lifecycle/service.js";
5+
import { CloudTaskService } from "../services/cloud-task/service.js";
56
import { ConnectivityService } from "../services/connectivity/service.js";
67
import { ContextMenuService } from "../services/context-menu/service.js";
78
import { DeepLinkService } from "../services/deep-link/service.js";
@@ -32,6 +33,7 @@ export const container = new Container({
3233

3334
container.bind(MAIN_TOKENS.AgentService).to(AgentService);
3435
container.bind(MAIN_TOKENS.AppLifecycleService).to(AppLifecycleService);
36+
container.bind(MAIN_TOKENS.CloudTaskService).to(CloudTaskService);
3537
container.bind(MAIN_TOKENS.ConnectivityService).to(ConnectivityService);
3638
container.bind(MAIN_TOKENS.ContextMenuService).to(ContextMenuService);
3739
container.bind(MAIN_TOKENS.DeepLinkService).to(DeepLinkService);

apps/twig/src/main/di/tokens.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export const MAIN_TOKENS = Object.freeze({
88
// Services
99
AgentService: Symbol.for("Main.AgentService"),
1010
AppLifecycleService: Symbol.for("Main.AppLifecycleService"),
11+
CloudTaskService: Symbol.for("Main.CloudTaskService"),
1112
ConnectivityService: Symbol.for("Main.ConnectivityService"),
1213
ContextMenuService: Symbol.for("Main.ContextMenuService"),
1314

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { z } from "zod";
2+
import type { CloudTaskUpdatePayload, TaskRun } from "../../../shared/types.js";
3+
4+
export type { CloudTaskUpdatePayload };
5+
6+
// --- Terminal statuses ---
7+
8+
export const TERMINAL_STATUSES = ["completed", "failed", "cancelled"] as const;
9+
10+
// --- Events ---
11+
12+
export const CloudTaskEvent = {
13+
Update: "cloud-task-update",
14+
} as const;
15+
16+
export interface CloudTaskEvents {
17+
[CloudTaskEvent.Update]: CloudTaskUpdatePayload;
18+
}
19+
20+
export type TaskRunStatus = TaskRun["status"];
21+
22+
// --- tRPC Schemas ---
23+
24+
export const watchInput = z.object({
25+
taskId: z.string(),
26+
runId: z.string(),
27+
apiHost: z.string(),
28+
teamId: z.number(),
29+
});
30+
31+
export type WatchInput = z.infer<typeof watchInput>;
32+
33+
export const unwatchInput = z.object({
34+
taskId: z.string(),
35+
runId: z.string(),
36+
});
37+
38+
export const updateTokenInput = z.object({
39+
token: z.string(),
40+
});
41+
42+
export const onUpdateInput = z.object({
43+
taskId: z.string(),
44+
runId: z.string(),
45+
});

0 commit comments

Comments
 (0)