(res: http.ServerResponse, urlPath: string)
| 822 | } |
| 823 | |
| 824 | private serveTaskDetail(res: http.ServerResponse, urlPath: string): void { |
| 825 | const taskId = urlPath.replace("/api/task/", ""); |
| 826 | const task = this.store.getTask(taskId); |
| 827 | if (!task) { |
| 828 | res.writeHead(404, { "Content-Type": "application/json" }); |
| 829 | res.end(JSON.stringify({ error: "Task not found" })); |
| 830 | return; |
| 831 | } |
| 832 | |
| 833 | const chunks = this.store.getChunksByTask(taskId); |
| 834 | const chunkItems = chunks.map((c) => { |
| 835 | const text = c.role === "user" ? stripInboundMetadata(c.content) : c.content; |
| 836 | return { id: c.id, role: c.role, content: text, summary: c.summary, createdAt: c.createdAt }; |
| 837 | }); |
| 838 | |
| 839 | const relatedSkills = this.store.getSkillsByTask(taskId); |
| 840 | const skillLinks = relatedSkills.map((rs) => ({ |
| 841 | skillId: rs.skill.id, |
| 842 | skillName: rs.skill.name, |
| 843 | relation: rs.relation, |
| 844 | versionAt: rs.versionAt, |
| 845 | status: rs.skill.status, |
| 846 | qualityScore: rs.skill.qualityScore, |
| 847 | })); |
| 848 | |
| 849 | const db = (this.store as any).db; |
| 850 | const meta = db.prepare("SELECT skill_status, skill_reason FROM tasks WHERE id = ?").get(taskId) as |
| 851 | { skill_status: string | null; skill_reason: string | null } | undefined; |
| 852 | const hubTask = this.getHubTaskForLocal(taskId); |
| 853 | const ts = this.resolveTaskTeamShareForApi(taskId, hubTask); |
| 854 | |
| 855 | this.jsonResponse(res, { |
| 856 | id: task.id, |
| 857 | sessionKey: task.sessionKey, |
| 858 | title: task.title, |
| 859 | summary: task.summary, |
| 860 | status: task.status, |
| 861 | owner: task.owner ?? "agent:main", |
| 862 | startedAt: task.startedAt, |
| 863 | endedAt: task.endedAt, |
| 864 | chunks: chunkItems, |
| 865 | skillStatus: meta?.skill_status ?? null, |
| 866 | skillReason: meta?.skill_reason ?? null, |
| 867 | skillLinks, |
| 868 | sharingVisibility: ts.visibility, |
| 869 | sharingGroupId: ts.groupId, |
| 870 | hubTaskId: ts.hasHubLink, |
| 871 | }); |
| 872 | } |
| 873 | |
| 874 | private serveStats(res: http.ServerResponse, url?: URL): void { |
| 875 | const emptyStats = { |
no test coverage detected