feat: sweep My Tasks (Recently Assigned) for already-done tasks
This commit is contained in:
@@ -110,6 +110,23 @@ export class AsanaClient {
|
||||
});
|
||||
}
|
||||
|
||||
// Get the authenticated user's GID
|
||||
async getMe(): Promise<{ gid: string; name: string }> {
|
||||
return this.request("/users/me?opt_fields=name");
|
||||
}
|
||||
|
||||
// Get user task list for a workspace
|
||||
async getUserTaskList(userGid: string, workspaceGid: string): Promise<{ gid: string; name: string }> {
|
||||
return this.request(`/users/${userGid}/user_task_list?workspace=${workspaceGid}&opt_fields=name`);
|
||||
}
|
||||
|
||||
// Get tasks from user task list (My Tasks / Recently Assigned)
|
||||
async getUserTasks(userTaskListGid: string): Promise<AsanaTask[]> {
|
||||
return this.request(
|
||||
`/user_task_lists/${userTaskListGid}/tasks?opt_fields=name,notes,completed,assignee.name,tags.name,custom_fields,due_on,created_at,modified_at,memberships.project.name,memberships.section.name`
|
||||
);
|
||||
}
|
||||
|
||||
// Helper: Find section by name
|
||||
async findSection(projectGid: string, sectionName: string): Promise<AsanaSection | null> {
|
||||
const sections = await this.getSections(projectGid);
|
||||
|
||||
@@ -19,6 +19,8 @@ export class TaskLoop {
|
||||
private lock: FileLock;
|
||||
private running = false;
|
||||
private timer: ReturnType<typeof setInterval> | null = null;
|
||||
private userTaskListGid: string | null = null;
|
||||
private workspaceGid: string = "";
|
||||
|
||||
constructor(config: Config) {
|
||||
this.config = config;
|
||||
@@ -75,6 +77,20 @@ export class TaskLoop {
|
||||
this.config.asanaProjectGid = projects[0].gid;
|
||||
logger.info("task-loop", `Auto-selected project: ${projects[0].name} (${projects[0].gid})`);
|
||||
}
|
||||
|
||||
this.workspaceGid = ws.gid;
|
||||
}
|
||||
|
||||
// Cache user task list for "My Tasks" / "Recently Assigned" sweep
|
||||
try {
|
||||
const me = await this.asana.getMe();
|
||||
if (this.workspaceGid) {
|
||||
const utl = await this.asana.getUserTaskList(me.gid, this.workspaceGid);
|
||||
this.userTaskListGid = utl.gid;
|
||||
logger.info("task-loop", `Cached user task list: ${utl.name} (${utl.gid})`);
|
||||
}
|
||||
} catch (error: any) {
|
||||
logger.warn("task-loop", `Could not get user task list: ${error.message}`);
|
||||
}
|
||||
} catch (error: any) {
|
||||
logger.error("task-loop", "Failed to discover Asana project", { error: error.message });
|
||||
@@ -303,6 +319,41 @@ EVIDENCE: one line why`;
|
||||
logger.debug("task-loop", `Sweep: "${task.name}" not yet done`, { evidence: check.evidence });
|
||||
}
|
||||
}
|
||||
|
||||
// Also sweep user's "My Tasks" (Recently Assigned)
|
||||
if (this.userTaskListGid) {
|
||||
try {
|
||||
const myTasks = await this.asana.getUserTasks(this.userTaskListGid);
|
||||
const incompleteMyTasks = myTasks.filter((t) => !t.completed);
|
||||
|
||||
if (incompleteMyTasks.length > 0) {
|
||||
logger.info("task-loop", `Sweeping ${incompleteMyTasks.length} tasks from My Tasks (Recently Assigned)`);
|
||||
|
||||
for (const task of incompleteMyTasks) {
|
||||
// Skip if already checked in project sweep
|
||||
if (seen.has(task.gid)) continue;
|
||||
|
||||
const check = await this.verifyTaskAlreadyDone(task);
|
||||
|
||||
if (check.done) {
|
||||
logger.info("task-loop", `My Tasks sweep: "${task.name}" is already done`, { evidence: check.evidence });
|
||||
|
||||
await this.asana.addComment(
|
||||
task.gid,
|
||||
`✅ Pi Worker sweep: This task is **already completed**.\n\nEvidence:\n${check.evidence}`
|
||||
);
|
||||
|
||||
await this.asana.updateTask(task.gid, { completed: true });
|
||||
logger.info("task-loop", `My Tasks sweep: Marked done: ${task.name}`);
|
||||
} else {
|
||||
logger.debug("task-loop", `My Tasks sweep: "${task.name}" not yet done`);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error: any) {
|
||||
logger.warn("task-loop", `My Tasks sweep error: ${error.message}`);
|
||||
}
|
||||
}
|
||||
} catch (error: any) {
|
||||
logger.error("task-loop", `Sweep error: ${error.message}`);
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
❌ Poll error: Network request for 'getUpdates' failed!
|
||||
|
||||
Reference in New Issue
Block a user