// The agent passes page_context.environment.apiUrl in as an argument, so the // allowlist keeps the user's DATA_TOKEN from being sent to any other host. const APPROVED_API_URL = /^https:\/\/(?:api\.tela\.com|(?:api|tela-api-pr-\d+)\.telastaging\.com)$/ const BULK_TASK_PATHS = ['/task/bulk', '/task/bulk/undo-approval'] const TASK_PATH = /^\/task\/([^/?]+)(?:\/rerun)?$/ export function resolveApiUrl(apiUrl: string | undefined): string { if (!apiUrl || !APPROVED_API_URL.test(apiUrl)) { console.error(`API URL not approved for this agent: ${apiUrl || '(missing)'}. Pass page_context.environment.apiUrl.`) process.exit(1) } return apiUrl } function refuse(message: string): never { console.error(`Refused: ${message}`) process.exit(1) } if (import.meta.main) { const [apiUrl, workstationId, method, path, body] = process.argv.slice(2) if (!workstationId || !method || !path?.startsWith('/') || path.startsWith('//')) { console.error('Usage: bun ./.claude/skills/workstation/tela-api.ts [body]') process.exit(1) } const dataToken = process.env.DATA_TOKEN if (!dataToken) { console.error('DATA_TOKEN is required') process.exit(1) } const baseUrl = resolveApiUrl(apiUrl) const headers = { 'x-data-token': dataToken, 'Content-Type': 'application/json' } // Writes are checked against the open Workstation here, not only in SKILL.md, so a task id // from another Workstation is refused even if the model is told to use it. if (method !== 'GET') { const payload = body ? JSON.parse(body) as unknown : undefined if (path === '/task') { if ([payload].flat().some(item => (item as { promptApplicationId?: string } | undefined)?.promptApplicationId !== workstationId)) refuse('tasks can only be created in the open Workstation') } else { const taskIds = BULK_TASK_PATHS.includes(path) ? payload : [path.match(TASK_PATH)?.[1]] if (!Array.isArray(taskIds) || taskIds.length === 0 || taskIds.some(id => typeof id !== 'string')) refuse(`${method} ${path} is not a Workstation task operation`) for (const taskId of taskIds as string[]) { const res = await fetch(`${baseUrl}/task/${encodeURIComponent(taskId)}`, { headers }) const task = res.ok ? await res.json() as { promptApplicationId?: string | null } : null if (task?.promptApplicationId !== workstationId) refuse(`task ${taskId} is not in the open Workstation, nothing was changed`) } } } const res = await fetch(baseUrl + path, { method, headers, body }) process.stdout.write(`${res.status} ${await res.text()}\n`) }