Download apps/vis/server/src/routes/tasks.ts from SaylorTwift/kimi-code: direct link, hf CLI and curl.
- Browser
- Download file 3.97 kB
-
https://huggingface.co/SaylorTwift/kimi-code/resolve/main/apps/vis/server/src/routes/tasks.ts
- Command line
-
hf download hf://SaylorTwift/kimi-code/apps/vis/server/src/routes/tasks.ts
-
curl -L -o tasks.ts https://huggingface.co/SaylorTwift/kimi-code/resolve/main/apps/vis/server/src/routes/tasks.ts
3.97 kB
| import { Hono } from 'hono'; | |
| import { KIMI_CODE_HOME } from '../config'; | |
| import type { BackgroundTaskEntry } from '../lib/agent-record-types'; | |
| import { readSessionDetail } from '../lib/session-store'; | |
| import { | |
| isSafeTaskId, | |
| listBackgroundTasks, | |
| readTaskOutput, | |
| taskOutputMetadata, | |
| } from '../lib/task-store'; | |
| /** Default output-log window size: 256 KiB. Large enough to show a whole | |
| * typical log in one fetch, bounded so a multi-MB log pages instead of | |
| * loading wholesale. Overridable via `?limit=`. */ | |
| const DEFAULT_OUTPUT_LIMIT = 256 * 1024; | |
| const MAX_OUTPUT_LIMIT = 4 * 1024 * 1024; | |
| export function tasksRoute(home: string = KIMI_CODE_HOME): Hono { | |
| const r = new Hono(); | |
| // List background tasks (process / agent / question) for a session. Current | |
| // tasks live under each spawning agent's homedir; the main agent also falls | |
| // back to the legacy session-root tasks directory. | |
| r.get('/:id/tasks', async (c) => { | |
| const id = c.req.param('id'); | |
| const detail = await readSessionDetail(home, id); | |
| if (!detail) { | |
| return c.json({ error: 'session not found', code: 'NOT_FOUND' }, 404); | |
| } | |
| const entries: BackgroundTaskEntry[] = []; | |
| for (const agent of detail.agents) { | |
| const fallbackDir = agent.agentId === 'main' ? detail.sessionDir : undefined; | |
| const tasks = await listBackgroundTasks(agent.homedir, fallbackDir); | |
| for (const task of tasks) { | |
| const output = await taskOutputMetadata(agent.homedir, task.taskId, fallbackDir); | |
| entries.push({ | |
| task, | |
| agentId: agent.agentId, | |
| outputSizeBytes: output.size, | |
| outputExists: output.exists, | |
| }); | |
| } | |
| } | |
| // Newest first across all agents. | |
| entries.sort((a, b) => (b.task.startedAt ?? 0) - (a.task.startedAt ?? 0)); | |
| return c.json({ sessionId: id, tasks: entries }); | |
| }); | |
| // Read a byte-window of a single task's output.log. The task may belong to | |
| // any agent, so locate the agent whose tasks/ directory holds it. | |
| r.get('/:id/tasks/:taskId/output', async (c) => { | |
| const id = c.req.param('id'); | |
| const taskId = c.req.param('taskId'); | |
| if (!isSafeTaskId(taskId)) { | |
| return c.json({ error: 'invalid task id', code: 'BAD_REQUEST' }, 400); | |
| } | |
| const offset = parseNonNegativeInt(c.req.query('offset'), 0); | |
| const limit = Math.min( | |
| parseNonNegativeInt(c.req.query('limit'), DEFAULT_OUTPUT_LIMIT), | |
| MAX_OUTPUT_LIMIT, | |
| ); | |
| const detail = await readSessionDetail(home, id); | |
| if (!detail) { | |
| return c.json({ error: 'session not found', code: 'NOT_FOUND' }, 404); | |
| } | |
| // Prefer the agent whose log exists, including an empty log. An explicit | |
| // ?agent= short-circuits the scan. The main agent also reads the legacy | |
| // session-root tasks directory as its fallback. | |
| const hinted = c.req.query('agent'); | |
| const hintedAgent = detail.agents.find((agent) => agent.agentId === hinted); | |
| let owner = hintedAgent ?? detail.agents[0]; | |
| if (hintedAgent === undefined) { | |
| for (const agent of detail.agents) { | |
| const fallbackDir = agent.agentId === 'main' ? detail.sessionDir : undefined; | |
| if ((await taskOutputMetadata(agent.homedir, taskId, fallbackDir)).exists) { | |
| owner = agent; | |
| break; | |
| } | |
| } | |
| } | |
| const dir = owner?.homedir ?? detail.sessionDir; | |
| const fallbackDir = owner?.agentId === 'main' ? detail.sessionDir : undefined; | |
| const window = await readTaskOutput(dir, taskId, offset, limit, fallbackDir); | |
| return c.json({ | |
| sessionId: id, | |
| taskId, | |
| offset: window.offset, | |
| nextOffset: window.nextOffset, | |
| size: window.size, | |
| content: window.content, | |
| eof: window.eof, | |
| }); | |
| }); | |
| return r; | |
| } | |
| function parseNonNegativeInt(raw: string | undefined, fallback: number): number { | |
| if (raw === undefined) return fallback; | |
| const n = Number.parseInt(raw, 10); | |
| return Number.isFinite(n) && n >= 0 ? n : fallback; | |
| } | |