axios+telemetry cleanup
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import axios from 'axios'
|
||||
import { nativeRequest } from '../utils/http.js'
|
||||
|
||||
import { debugBody, extractErrorDetail } from './debugUtils.js'
|
||||
import {
|
||||
@@ -148,38 +148,26 @@ export function createBridgeApiClient(deps: BridgeApiDeps): BridgeApiClient {
|
||||
|
||||
const response = await withOAuthRetry(
|
||||
(token: string) =>
|
||||
axios.post<{
|
||||
nativeRequest<{
|
||||
environment_id: string
|
||||
environment_secret: string
|
||||
}>(
|
||||
`${deps.baseUrl}/v1/environments/bridge`,
|
||||
{
|
||||
machine_name: config.machineName,
|
||||
directory: config.dir,
|
||||
branch: config.branch,
|
||||
git_repo_url: config.gitRepoUrl,
|
||||
// Advertise session capacity so claude.ai/code can show
|
||||
// "2/4 sessions" badges and only block the picker when
|
||||
// actually at capacity. Backends that don't yet accept
|
||||
// this field will silently ignore it.
|
||||
max_sessions: config.maxSessions,
|
||||
// worker_type lets claude.ai filter environments by origin
|
||||
// (e.g. assistant picker only shows assistant-mode workers).
|
||||
// Desktop cowork app sends "cowork"; we send a distinct value.
|
||||
metadata: { worker_type: config.workerType },
|
||||
// Idempotent re-registration: if we have a backend-issued
|
||||
// environment_id from a prior session (--session-id resume),
|
||||
// send it back so the backend reattaches instead of creating
|
||||
// a new env. The backend may still hand back a fresh ID if
|
||||
// the old one expired — callers must compare the response.
|
||||
...(config.reuseEnvironmentId && {
|
||||
environment_id: config.reuseEnvironmentId,
|
||||
}),
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
body: {
|
||||
machine_name: config.machineName,
|
||||
directory: config.dir,
|
||||
branch: config.branch,
|
||||
git_repo_url: config.gitRepoUrl,
|
||||
max_sessions: config.maxSessions,
|
||||
metadata: { worker_type: config.workerType },
|
||||
...(config.reuseEnvironmentId && {
|
||||
environment_id: config.reuseEnvironmentId,
|
||||
}),
|
||||
},
|
||||
headers: getHeaders(token),
|
||||
timeout: 15_000,
|
||||
validateStatus: status => status < 500,
|
||||
},
|
||||
),
|
||||
'Registration',
|
||||
@@ -209,17 +197,16 @@ export function createBridgeApiClient(deps: BridgeApiDeps): BridgeApiClient {
|
||||
const prevEmptyPolls = consecutiveEmptyPolls
|
||||
consecutiveEmptyPolls = 0
|
||||
|
||||
const response = await axios.get<WorkResponse | null>(
|
||||
`${deps.baseUrl}/v1/environments/${environmentId}/work/poll`,
|
||||
const pollUrl = reclaimOlderThanMs !== undefined
|
||||
? `${deps.baseUrl}/v1/environments/${environmentId}/work/poll?reclaim_older_than_ms=${reclaimOlderThanMs}`
|
||||
: `${deps.baseUrl}/v1/environments/${environmentId}/work/poll`
|
||||
const response = await nativeRequest<WorkResponse | null>(
|
||||
pollUrl,
|
||||
{
|
||||
method: 'GET',
|
||||
headers: getHeaders(environmentSecret),
|
||||
params:
|
||||
reclaimOlderThanMs !== undefined
|
||||
? { reclaim_older_than_ms: reclaimOlderThanMs }
|
||||
: undefined,
|
||||
timeout: 10_000,
|
||||
signal,
|
||||
validateStatus: status => status < 500,
|
||||
timeout: 10_000,
|
||||
},
|
||||
)
|
||||
|
||||
@@ -256,13 +243,13 @@ export function createBridgeApiClient(deps: BridgeApiDeps): BridgeApiClient {
|
||||
|
||||
debug(`[bridge:api] POST .../work/${workId}/ack`)
|
||||
|
||||
const response = await axios.post(
|
||||
const response = await nativeRequest(
|
||||
`${deps.baseUrl}/v1/environments/${environmentId}/work/${workId}/ack`,
|
||||
{},
|
||||
{
|
||||
method: 'POST',
|
||||
body: {},
|
||||
headers: getHeaders(sessionToken),
|
||||
timeout: 10_000,
|
||||
validateStatus: s => s < 500,
|
||||
},
|
||||
)
|
||||
|
||||
@@ -282,13 +269,13 @@ export function createBridgeApiClient(deps: BridgeApiDeps): BridgeApiClient {
|
||||
|
||||
const response = await withOAuthRetry(
|
||||
(token: string) =>
|
||||
axios.post(
|
||||
nativeRequest(
|
||||
`${deps.baseUrl}/v1/environments/${environmentId}/work/${workId}/stop`,
|
||||
{ force },
|
||||
{
|
||||
method: 'POST',
|
||||
body: { force },
|
||||
headers: getHeaders(token),
|
||||
timeout: 10_000,
|
||||
validateStatus: s => s < 500,
|
||||
},
|
||||
),
|
||||
'StopWork',
|
||||
@@ -305,12 +292,12 @@ export function createBridgeApiClient(deps: BridgeApiDeps): BridgeApiClient {
|
||||
|
||||
const response = await withOAuthRetry(
|
||||
(token: string) =>
|
||||
axios.delete(
|
||||
nativeRequest(
|
||||
`${deps.baseUrl}/v1/environments/bridge/${environmentId}`,
|
||||
{
|
||||
method: 'DELETE',
|
||||
headers: getHeaders(token),
|
||||
timeout: 10_000,
|
||||
validateStatus: s => s < 500,
|
||||
},
|
||||
),
|
||||
'Deregister',
|
||||
@@ -329,13 +316,13 @@ export function createBridgeApiClient(deps: BridgeApiDeps): BridgeApiClient {
|
||||
|
||||
const response = await withOAuthRetry(
|
||||
(token: string) =>
|
||||
axios.post(
|
||||
nativeRequest(
|
||||
`${deps.baseUrl}/v1/sessions/${sessionId}/archive`,
|
||||
{},
|
||||
{
|
||||
method: 'POST',
|
||||
body: {},
|
||||
headers: getHeaders(token),
|
||||
timeout: 10_000,
|
||||
validateStatus: s => s < 500,
|
||||
},
|
||||
),
|
||||
'ArchiveSession',
|
||||
@@ -368,13 +355,13 @@ export function createBridgeApiClient(deps: BridgeApiDeps): BridgeApiClient {
|
||||
|
||||
const response = await withOAuthRetry(
|
||||
(token: string) =>
|
||||
axios.post(
|
||||
nativeRequest(
|
||||
`${deps.baseUrl}/v1/environments/${environmentId}/bridge/reconnect`,
|
||||
{ session_id: sessionId },
|
||||
{
|
||||
method: 'POST',
|
||||
body: { session_id: sessionId },
|
||||
headers: getHeaders(token),
|
||||
timeout: 10_000,
|
||||
validateStatus: s => s < 500,
|
||||
},
|
||||
),
|
||||
'ReconnectSession',
|
||||
@@ -394,18 +381,18 @@ export function createBridgeApiClient(deps: BridgeApiDeps): BridgeApiClient {
|
||||
|
||||
debug(`[bridge:api] POST .../work/${workId}/heartbeat`)
|
||||
|
||||
const response = await axios.post<{
|
||||
const response = await nativeRequest<{
|
||||
lease_extended: boolean
|
||||
state: string
|
||||
last_heartbeat: string
|
||||
ttl_seconds: number
|
||||
}>(
|
||||
`${deps.baseUrl}/v1/environments/${environmentId}/work/${workId}/heartbeat`,
|
||||
{},
|
||||
{
|
||||
method: 'POST',
|
||||
body: {},
|
||||
headers: getHeaders(sessionToken),
|
||||
timeout: 10_000,
|
||||
validateStatus: s => s < 500,
|
||||
},
|
||||
)
|
||||
|
||||
@@ -427,13 +414,13 @@ export function createBridgeApiClient(deps: BridgeApiDeps): BridgeApiClient {
|
||||
`[bridge:api] POST /v1/sessions/${sessionId}/events type=${event.type}`,
|
||||
)
|
||||
|
||||
const response = await axios.post(
|
||||
const response = await nativeRequest(
|
||||
`${deps.baseUrl}/v1/sessions/${sessionId}/events`,
|
||||
{ events: [event] },
|
||||
{
|
||||
method: 'POST',
|
||||
body: { events: [event] },
|
||||
headers: getHeaders(sessionToken),
|
||||
timeout: 10_000,
|
||||
validateStatus: s => s < 500,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* accessToken + baseUrl — no implicit auth or config reads.
|
||||
*/
|
||||
|
||||
import axios from 'axios'
|
||||
import { isHttpError, nativeRequest } from '../utils/http.js'
|
||||
import { logForDebugging } from '../utils/debug.js'
|
||||
import { errorMessage } from '../utils/errors.js'
|
||||
import { jsonStringify } from '../utils/slowOperations.js'
|
||||
@@ -33,16 +33,13 @@ export async function createCodeSession(
|
||||
const url = `${baseUrl}/v1/code/sessions`
|
||||
let response
|
||||
try {
|
||||
response = await axios.post(
|
||||
response = await nativeRequest(
|
||||
url,
|
||||
// bridge: {} is the positive signal for the oneof runner — omitting it
|
||||
// (or sending environment_id: "") now 400s. BridgeRunner is an empty
|
||||
// message today; it's a placeholder for future bridge-specific options.
|
||||
{ title, bridge: {}, ...(tags?.length ? { tags } : {}) },
|
||||
{
|
||||
method: 'POST',
|
||||
body: { title, bridge: {}, ...(tags?.length ? { tags } : {}) },
|
||||
headers: oauthHeaders(accessToken),
|
||||
timeout: timeoutMs,
|
||||
validateStatus: s => s < 500,
|
||||
},
|
||||
)
|
||||
} catch (err: unknown) {
|
||||
@@ -104,13 +101,13 @@ export async function fetchRemoteCredentials(
|
||||
}
|
||||
let response
|
||||
try {
|
||||
response = await axios.post(
|
||||
response = await nativeRequest(
|
||||
url,
|
||||
{},
|
||||
{
|
||||
method: 'POST',
|
||||
body: {},
|
||||
headers,
|
||||
timeout: timeoutMs,
|
||||
validateStatus: s => s < 500,
|
||||
},
|
||||
)
|
||||
} catch (err: unknown) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { SDKMessage } from '../entrypoints/agentSdkTypes.js'
|
||||
import { nativeRequest } from '../utils/http.js'
|
||||
import { logForDebugging } from '../utils/debug.js'
|
||||
import { errorMessage } from '../utils/errors.js'
|
||||
import { extractErrorDetail } from './debugUtils.js'
|
||||
@@ -59,7 +60,6 @@ export async function createBridgeSession({
|
||||
const { parseGitHubRepository } = await import('../utils/detectRepository.js')
|
||||
const { getDefaultBranch } = await import('../utils/git.js')
|
||||
const { getMainLoopModel } = await import('../utils/model/model.js')
|
||||
const { default: axios } = await import('axios')
|
||||
|
||||
const accessToken =
|
||||
getAccessToken?.() ?? getClaudeAIOAuthTokens()?.accessToken
|
||||
@@ -144,10 +144,11 @@ export async function createBridgeSession({
|
||||
const url = `${baseUrlOverride ?? getOauthConfig().BASE_API_URL}/v1/sessions`
|
||||
let response
|
||||
try {
|
||||
response = await axios.post(url, requestBody, {
|
||||
response = await nativeRequest(url, {
|
||||
method: 'POST',
|
||||
body: requestBody,
|
||||
headers,
|
||||
signal,
|
||||
validateStatus: s => s < 500,
|
||||
})
|
||||
} catch (err: unknown) {
|
||||
logForDebugging(
|
||||
@@ -195,7 +196,6 @@ export async function getBridgeSession(
|
||||
const { getOrganizationUUID } = await import('../services/oauth/client.js')
|
||||
const { getOauthConfig } = await import('../constants/oauth.js')
|
||||
const { getOAuthHeaders } = await import('../utils/teleport/api.js')
|
||||
const { default: axios } = await import('axios')
|
||||
|
||||
const accessToken =
|
||||
opts?.getAccessToken?.() ?? getClaudeAIOAuthTokens()?.accessToken
|
||||
@@ -221,9 +221,9 @@ export async function getBridgeSession(
|
||||
|
||||
let response
|
||||
try {
|
||||
response = await axios.get<{ environment_id?: string; title?: string }>(
|
||||
response = await nativeRequest<{ environment_id?: string; title?: string }>(
|
||||
url,
|
||||
{ headers, timeout: 10_000, validateStatus: s => s < 500 },
|
||||
{ headers, timeout: 10_000 },
|
||||
)
|
||||
} catch (err: unknown) {
|
||||
logForDebugging(
|
||||
@@ -272,7 +272,6 @@ export async function archiveBridgeSession(
|
||||
const { getOrganizationUUID } = await import('../services/oauth/client.js')
|
||||
const { getOauthConfig } = await import('../constants/oauth.js')
|
||||
const { getOAuthHeaders } = await import('../utils/teleport/api.js')
|
||||
const { default: axios } = await import('axios')
|
||||
|
||||
const accessToken =
|
||||
opts?.getAccessToken?.() ?? getClaudeAIOAuthTokens()?.accessToken
|
||||
@@ -296,13 +295,13 @@ export async function archiveBridgeSession(
|
||||
const url = `${opts?.baseUrl ?? getOauthConfig().BASE_API_URL}/v1/sessions/${sessionId}/archive`
|
||||
logForDebugging(`[bridge] Archiving session ${sessionId}`)
|
||||
|
||||
const response = await axios.post(
|
||||
const response = await nativeRequest(
|
||||
url,
|
||||
{},
|
||||
{
|
||||
method: 'POST',
|
||||
body: {},
|
||||
headers,
|
||||
timeout: opts?.timeoutMs ?? 10_000,
|
||||
validateStatus: s => s < 500,
|
||||
},
|
||||
)
|
||||
|
||||
@@ -333,7 +332,6 @@ export async function updateBridgeSessionTitle(
|
||||
const { getOrganizationUUID } = await import('../services/oauth/client.js')
|
||||
const { getOauthConfig } = await import('../constants/oauth.js')
|
||||
const { getOAuthHeaders } = await import('../utils/teleport/api.js')
|
||||
const { default: axios } = await import('axios')
|
||||
|
||||
const accessToken =
|
||||
opts?.getAccessToken?.() ?? getClaudeAIOAuthTokens()?.accessToken
|
||||
@@ -362,10 +360,14 @@ export async function updateBridgeSessionTitle(
|
||||
logForDebugging(`[bridge] Updating session title: ${compatId} → ${title}`)
|
||||
|
||||
try {
|
||||
const response = await axios.patch(
|
||||
const response = await nativeRequest(
|
||||
url,
|
||||
{ title },
|
||||
{ headers, timeout: 10_000, validateStatus: s => s < 500 },
|
||||
{
|
||||
method: 'PATCH',
|
||||
body: { title },
|
||||
headers,
|
||||
timeout: 10_000,
|
||||
},
|
||||
)
|
||||
|
||||
if (response.status === 200) {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
import type { ContentBlockParam } from '@anthropic-ai/sdk/resources/messages.mjs'
|
||||
import axios from 'axios'
|
||||
import { isHttpError, nativeRequest } from '../utils/http.js'
|
||||
import { randomUUID } from 'crypto'
|
||||
import { mkdir, writeFile } from 'fs/promises'
|
||||
import { basename, join } from 'path'
|
||||
@@ -79,11 +79,10 @@ async function resolveOne(att: InboundAttachment): Promise<string | undefined> {
|
||||
// FedStart URL degrades to "no @path" instead of crashing print.ts's
|
||||
// reader loop (which has no catch around the await).
|
||||
const url = `${getBridgeBaseUrl()}/api/oauth/files/${encodeURIComponent(att.file_uuid)}/content`
|
||||
const response = await axios.get(url, {
|
||||
const response = await nativeRequest<ArrayBuffer>(url, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
responseType: 'arraybuffer',
|
||||
timeout: DOWNLOAD_TIMEOUT_MS,
|
||||
validateStatus: () => true,
|
||||
})
|
||||
if (response.status !== 200) {
|
||||
debug(`fetch ${att.file_uuid} failed: status=${response.status}`)
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
*/
|
||||
|
||||
import { feature } from 'bun:bundle'
|
||||
import axios from 'axios'
|
||||
import { isHttpError, nativeRequest } from '../utils/http.js'
|
||||
import {
|
||||
createV2ReplTransport,
|
||||
type ReplBridgeTransport,
|
||||
@@ -981,17 +981,17 @@ async function archiveSession(
|
||||
// cse_* and we correctly send it.
|
||||
const compatId = toCompatSessionId(sessionId)
|
||||
try {
|
||||
const response = await axios.post(
|
||||
const response = await nativeRequest(
|
||||
`${baseUrl}/v1/sessions/${compatId}/archive`,
|
||||
{},
|
||||
{
|
||||
method: 'POST',
|
||||
body: {},
|
||||
headers: {
|
||||
...oauthHeaders(accessToken),
|
||||
'anthropic-beta': 'ccr-byoc-2025-07-29',
|
||||
'x-organization-uuid': orgUUID,
|
||||
},
|
||||
timeout: timeoutMs,
|
||||
validateStatus: () => true,
|
||||
},
|
||||
)
|
||||
logForDebugging(
|
||||
@@ -1001,7 +1001,7 @@ async function archiveSession(
|
||||
} catch (err) {
|
||||
const msg = errorMessage(err)
|
||||
logForDebugging(`[remote-bridge] Archive failed: ${msg}`)
|
||||
return axios.isAxiosError(err) && err.code === 'ECONNABORTED'
|
||||
return isHttpError(err) && err.code === 'ECONNABORTED'
|
||||
? 'timeout'
|
||||
: 'error'
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import axios from 'axios'
|
||||
import { nativeRequest } from '../utils/http.js'
|
||||
import memoize from 'lodash-es/memoize.js'
|
||||
import { hostname } from 'os'
|
||||
import { getOauthConfig } from '../constants/oauth.js'
|
||||
@@ -142,19 +142,19 @@ export async function enrollTrustedDevice(): Promise<void> {
|
||||
const baseUrl = getOauthConfig().BASE_API_URL
|
||||
let response
|
||||
try {
|
||||
response = await axios.post<{
|
||||
response = await nativeRequest<{
|
||||
device_token?: string
|
||||
device_id?: string
|
||||
}>(
|
||||
`${baseUrl}/api/auth/trusted_devices`,
|
||||
{ display_name: `Claude Code on ${hostname()} · ${process.platform}` },
|
||||
{
|
||||
method: 'POST',
|
||||
body: { display_name: `Claude Code on ${hostname()} · ${process.platform}` },
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
timeout: 10_000,
|
||||
validateStatus: s => s < 500,
|
||||
},
|
||||
)
|
||||
} catch (err: unknown) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import axios from 'axios'
|
||||
import { nativeRequest } from '../utils/http.js'
|
||||
import { jsonParse, jsonStringify } from '../utils/slowOperations.js'
|
||||
import type { WorkSecret } from './types.js'
|
||||
|
||||
@@ -98,10 +98,11 @@ export async function registerWorker(
|
||||
sessionUrl: string,
|
||||
accessToken: string,
|
||||
): Promise<number> {
|
||||
const response = await axios.post(
|
||||
const response = await nativeRequest(
|
||||
`${sessionUrl}/worker/register`,
|
||||
{},
|
||||
{
|
||||
method: 'POST',
|
||||
body: {},
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
'Content-Type': 'application/json',
|
||||
|
||||
Reference in New Issue
Block a user