diff --git a/apps/agent-worker/src/runtime/docker.ts b/apps/agent-worker/src/runtime/docker.ts index 7421d40..a4b3d75 100644 --- a/apps/agent-worker/src/runtime/docker.ts +++ b/apps/agent-worker/src/runtime/docker.ts @@ -244,7 +244,9 @@ export const inspectUserBoxStatus = async ( const running = runningField === 'true'; return { running, + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- empty field means "no image" image: imageField || null, + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- empty field means "not started" startedAt: running ? startedAtField || null : null, memoryLimitBytes: Number(memoryField) || null, }; diff --git a/apps/agent-worker/src/terminal-token.ts b/apps/agent-worker/src/terminal-token.ts index 90ae713..2fe8cfd 100644 --- a/apps/agent-worker/src/terminal-token.ts +++ b/apps/agent-worker/src/terminal-token.ts @@ -37,7 +37,8 @@ export const parseBoxTokenUsername = (token: string): string | null => { const parts = token.split('.'); if (parts.length !== 4 || parts[1] !== 'box') return null; const username = parts[2]; - return username ? username : null; + if (!username) return null; + return username; }; // User-scoped variant authorizing a terminal connection to a user's box. diff --git a/apps/agent-worker/src/worker.ts b/apps/agent-worker/src/worker.ts index 6953619..279e4cc 100644 --- a/apps/agent-worker/src/worker.ts +++ b/apps/agent-worker/src/worker.ts @@ -293,7 +293,7 @@ const createInteractionRequest = async (args: { ...args, }); -const patchInteractionRequest = async (args: { +const _patchInteractionRequest = async (args: { interactionId: Id<'agentInteractionRequests'>; status: 'pending' | 'answered' | 'approved' | 'rejected' | 'expired'; response?: string; @@ -1179,6 +1179,7 @@ export const replyToInteraction = async ( externalRequestId: string; response: string; }, + // eslint-disable-next-line @typescript-eslint/require-await -- keep async so callers receive a rejected promise ) => { // Every runtime now runs its CLI non-interactively inside the box, so no // runtime emits an interaction request that expects a reply. diff --git a/apps/agent-worker/tests/unit/agent-runtime.test.ts b/apps/agent-worker/tests/unit/agent-runtime.test.ts index af5b972..c37238f 100644 --- a/apps/agent-worker/tests/unit/agent-runtime.test.ts +++ b/apps/agent-worker/tests/unit/agent-runtime.test.ts @@ -9,9 +9,9 @@ describe('agent runtime registry', () => { test('registerAdapter/getAdapter resolves a registered runtime', () => { const fake: AgentRuntime = { name: 'codex', - prepareAuth: async () => {}, - runTurn: async () => ({}), - abort: async () => {}, + prepareAuth: () => Promise.resolve(), + runTurn: () => Promise.resolve({}), + abort: () => Promise.resolve(), }; registerAdapter('codex', () => fake); expect(getAdapter('codex').name).toBe('codex'); diff --git a/apps/next/src/app/(app)/spoons/[spoonId]/agent/[jobId]/page.tsx b/apps/next/src/app/(app)/spoons/[spoonId]/agent/[jobId]/page.tsx index 29aaef5..f37e085 100644 --- a/apps/next/src/app/(app)/spoons/[spoonId]/agent/[jobId]/page.tsx +++ b/apps/next/src/app/(app)/spoons/[spoonId]/agent/[jobId]/page.tsx @@ -1,6 +1,5 @@ 'use client'; -import type { FunctionReturnType } from 'convex/server'; import { useEffect } from 'react'; import Link from 'next/link'; import { useParams, useRouter } from 'next/navigation'; @@ -16,10 +15,7 @@ const AgentWorkspacePage = () => { const router = useRouter(); const params = useParams<{ spoonId: string; jobId: string }>(); const jobId = params.jobId as Id<'agentJobs'>; - const job = useQuery(api.agentJobs.get, { jobId }) as - | FunctionReturnType - | null - | undefined; + const job = useQuery(api.agentJobs.get, { jobId }); useEffect(() => { if (job?.threadId) router.replace(`/threads/${job.threadId}`); diff --git a/apps/next/src/app/(app)/threads/[threadId]/page.tsx b/apps/next/src/app/(app)/threads/[threadId]/page.tsx index b265e0a..fecd061 100644 --- a/apps/next/src/app/(app)/threads/[threadId]/page.tsx +++ b/apps/next/src/app/(app)/threads/[threadId]/page.tsx @@ -1,6 +1,5 @@ 'use client'; -import type { FunctionReturnType } from 'convex/server'; import { useState } from 'react'; import Link from 'next/link'; import { useParams, useRouter } from 'next/navigation'; @@ -34,10 +33,7 @@ const ThreadDetailPage = () => { const router = useRouter(); const params = useParams<{ threadId: string }>(); const threadId = params.threadId as Id<'threads'>; - const details = useQuery(api.threads.get, { threadId }) as - | FunctionReturnType - | null - | undefined; + const details = useQuery(api.threads.get, { threadId }); const createJob = useMutation(api.agentJobs.createForThread); const markResolved = useMutation(api.threads.markResolved); const cancel = useMutation(api.threads.cancel); diff --git a/apps/next/src/app/api/threads/[threadId]/message/route.ts b/apps/next/src/app/api/threads/[threadId]/message/route.ts index d591458..3934585 100644 --- a/apps/next/src/app/api/threads/[threadId]/message/route.ts +++ b/apps/next/src/app/api/threads/[threadId]/message/route.ts @@ -1,4 +1,3 @@ -import type { FunctionReturnType } from 'convex/server'; import { NextResponse } from 'next/server'; import { proxyWorker } from '@/lib/agent-worker-proxy'; import { convexAuthNextjsToken } from '@convex-dev/auth/nextjs/server'; @@ -40,7 +39,7 @@ export const POST = async ( api.threads.get, { threadId }, { token }, - )) as FunctionReturnType | null; + )); if (details === null) { return NextResponse.json({ error: 'Thread not found.' }, { status: 404 }); } diff --git a/apps/next/src/components/agent-workspace/agent-workspace-shell.tsx b/apps/next/src/components/agent-workspace/agent-workspace-shell.tsx index 91e3302..924b31f 100644 --- a/apps/next/src/components/agent-workspace/agent-workspace-shell.tsx +++ b/apps/next/src/components/agent-workspace/agent-workspace-shell.tsx @@ -1,6 +1,5 @@ 'use client'; -import type { FunctionReturnType } from 'convex/server'; import type { CSSProperties, PointerEvent as ReactPointerEvent } from 'react'; import { useCallback, useEffect, useState } from 'react'; import { useMutation, useQuery } from 'convex/react'; @@ -61,10 +60,7 @@ type PendingOverwrite = { }; export const AgentWorkspaceShell = ({ jobId }: { jobId: Id<'agentJobs'> }) => { - const job = useQuery(api.agentJobs.get, { jobId }) as - | FunctionReturnType - | null - | undefined; + const job = useQuery(api.agentJobs.get, { jobId }); const messages = useQuery( api.agentJobs.listMessages, diff --git a/apps/next/tests/component/xterm-session.test.tsx b/apps/next/tests/component/xterm-session.test.tsx index 963e0f7..344d7ca 100644 --- a/apps/next/tests/component/xterm-session.test.tsx +++ b/apps/next/tests/component/xterm-session.test.tsx @@ -13,11 +13,11 @@ const { writeTextSpy, } = vi.hoisted(() => ({ openSpy: vi.fn(), - wsInstances: [] as Array<{ + wsInstances: [] as { url: string; send: ReturnType; close: ReturnType; - }>, + }[], fetchSpy: vi.fn(), fitSpy: vi.fn(), selectionHandlers: [] as (() => void)[], @@ -110,17 +110,23 @@ beforeEach(() => { fetchSpy.mockResolvedValue({ ok: true, status: 200, - json: async () => ({ url: 'ws://x' }), - text: async () => '', + json: () => Promise.resolve({ url: 'ws://x' }), + text: () => Promise.resolve(''), }); vi.stubGlobal('WebSocket', FakeWebSocket); vi.stubGlobal('fetch', fetchSpy); vi.stubGlobal( 'ResizeObserver', class { - observe() {} - disconnect() {} - unobserve() {} + observe() { + /* noop */ + } + disconnect() { + /* noop */ + } + unobserve() { + /* noop */ + } }, ); Object.defineProperty(document, 'fonts', {