client.ts 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029
  1. import type {
  2. HealthGetOutput,
  3. LocationGetInput,
  4. LocationGetOutput,
  5. AgentsListInput,
  6. AgentsListOutput,
  7. SessionsListInput,
  8. SessionsListOutput,
  9. SessionsCreateInput,
  10. SessionsCreateOutput,
  11. SessionsActiveOutput,
  12. SessionsGetInput,
  13. SessionsGetOutput,
  14. SessionsSwitchAgentInput,
  15. SessionsSwitchAgentOutput,
  16. SessionsSwitchModelInput,
  17. SessionsSwitchModelOutput,
  18. SessionsPromptInput,
  19. SessionsPromptOutput,
  20. SessionsCompactInput,
  21. SessionsCompactOutput,
  22. SessionsWaitInput,
  23. SessionsWaitOutput,
  24. SessionsStageInput,
  25. SessionsStageOutput,
  26. SessionsClearInput,
  27. SessionsClearOutput,
  28. SessionsCommitInput,
  29. SessionsCommitOutput,
  30. SessionsContextInput,
  31. SessionsContextOutput,
  32. SessionsHistoryInput,
  33. SessionsHistoryOutput,
  34. SessionsEventsInput,
  35. SessionsEventsOutput,
  36. SessionsInterruptInput,
  37. SessionsInterruptOutput,
  38. SessionsMessageInput,
  39. SessionsMessageOutput,
  40. MessagesListInput,
  41. MessagesListOutput,
  42. ModelsListInput,
  43. ModelsListOutput,
  44. ProvidersListInput,
  45. ProvidersListOutput,
  46. ProvidersGetInput,
  47. ProvidersGetOutput,
  48. IntegrationsListInput,
  49. IntegrationsListOutput,
  50. IntegrationsGetInput,
  51. IntegrationsGetOutput,
  52. IntegrationsConnectKeyInput,
  53. IntegrationsConnectKeyOutput,
  54. IntegrationsConnectOauthInput,
  55. IntegrationsConnectOauthOutput,
  56. IntegrationsAttemptStatusInput,
  57. IntegrationsAttemptStatusOutput,
  58. IntegrationsAttemptCompleteInput,
  59. IntegrationsAttemptCompleteOutput,
  60. IntegrationsAttemptCancelInput,
  61. IntegrationsAttemptCancelOutput,
  62. CredentialsUpdateInput,
  63. CredentialsUpdateOutput,
  64. CredentialsRemoveInput,
  65. CredentialsRemoveOutput,
  66. PermissionsListRequestsInput,
  67. PermissionsListRequestsOutput,
  68. PermissionsListSavedInput,
  69. PermissionsListSavedOutput,
  70. PermissionsRemoveSavedInput,
  71. PermissionsRemoveSavedOutput,
  72. PermissionsCreateInput,
  73. PermissionsCreateOutput,
  74. PermissionsListInput,
  75. PermissionsListOutput,
  76. PermissionsGetInput,
  77. PermissionsGetOutput,
  78. PermissionsReplyInput,
  79. PermissionsReplyOutput,
  80. FilesListInput,
  81. FilesListOutput,
  82. FilesFindInput,
  83. FilesFindOutput,
  84. CommandsListInput,
  85. CommandsListOutput,
  86. SkillsListInput,
  87. SkillsListOutput,
  88. EventsSubscribeOutput,
  89. PtysListInput,
  90. PtysListOutput,
  91. PtysCreateInput,
  92. PtysCreateOutput,
  93. PtysGetInput,
  94. PtysGetOutput,
  95. PtysUpdateInput,
  96. PtysUpdateOutput,
  97. PtysRemoveInput,
  98. PtysRemoveOutput,
  99. QuestionsListRequestsInput,
  100. QuestionsListRequestsOutput,
  101. QuestionsListInput,
  102. QuestionsListOutput,
  103. QuestionsReplyInput,
  104. QuestionsReplyOutput,
  105. QuestionsRejectInput,
  106. QuestionsRejectOutput,
  107. ReferencesListInput,
  108. ReferencesListOutput,
  109. ProjectCopiesCreateInput,
  110. ProjectCopiesCreateOutput,
  111. ProjectCopiesRemoveInput,
  112. ProjectCopiesRemoveOutput,
  113. ProjectCopiesRefreshInput,
  114. ProjectCopiesRefreshOutput,
  115. } from "./types"
  116. import { ClientError } from "./client-error"
  117. export interface ClientOptions {
  118. readonly baseUrl: string
  119. readonly fetch?: typeof globalThis.fetch
  120. readonly headers?: HeadersInit
  121. }
  122. export interface RequestOptions {
  123. readonly signal?: AbortSignal
  124. readonly headers?: HeadersInit
  125. }
  126. interface RequestDescriptor {
  127. readonly method: string
  128. readonly path: string
  129. readonly query?: Record<string, unknown>
  130. readonly headers?: Record<string, unknown>
  131. readonly body?: unknown
  132. readonly successStatus: number
  133. readonly declaredStatuses: ReadonlyArray<number>
  134. readonly empty: boolean
  135. }
  136. export function make(options: ClientOptions) {
  137. const fetch = options.fetch ?? globalThis.fetch
  138. const prepare = (descriptor: RequestDescriptor, requestOptions?: RequestOptions) => {
  139. const url = new URL(descriptor.path, options.baseUrl)
  140. for (const [key, value] of Object.entries(descriptor.query ?? {})) appendQuery(url.searchParams, key, value)
  141. const headers = new Headers(options.headers)
  142. for (const [key, value] of Object.entries(descriptor.headers ?? {})) {
  143. if (value !== undefined && value !== null) headers.set(key, String(value))
  144. }
  145. for (const [key, value] of new Headers(requestOptions?.headers)) headers.set(key, value)
  146. if (descriptor.body !== undefined && !headers.has("content-type")) headers.set("content-type", "application/json")
  147. return {
  148. url,
  149. init: {
  150. method: descriptor.method,
  151. signal: requestOptions?.signal,
  152. headers,
  153. body: descriptor.body === undefined ? undefined : JSON.stringify(descriptor.body),
  154. } satisfies RequestInit,
  155. }
  156. }
  157. const execute = async (descriptor: RequestDescriptor, requestOptions?: RequestOptions) => {
  158. try {
  159. const prepared = prepare(descriptor, requestOptions)
  160. return await fetch(prepared.url, prepared.init)
  161. } catch (cause) {
  162. throw new ClientError("Transport", { cause })
  163. }
  164. }
  165. const responseError = async (response: Response, descriptor: RequestDescriptor): Promise<never> => {
  166. if (descriptor.declaredStatuses.includes(response.status)) throw await json(response)
  167. try {
  168. await response.body?.cancel()
  169. } catch {}
  170. throw new ClientError("UnexpectedStatus", { cause: { status: response.status } })
  171. }
  172. const request = async <A>(descriptor: RequestDescriptor, requestOptions?: RequestOptions): Promise<A> => {
  173. const response = await execute(descriptor, requestOptions)
  174. if (response.status !== descriptor.successStatus) return responseError(response, descriptor)
  175. if (descriptor.empty) {
  176. try {
  177. await response.body?.cancel()
  178. } catch {}
  179. return undefined as A
  180. }
  181. return (await json(response)) as A
  182. }
  183. const sse = <A>(descriptor: RequestDescriptor, requestOptions?: RequestOptions): AsyncIterable<A> => ({
  184. async *[Symbol.asyncIterator]() {
  185. const response = await execute(descriptor, requestOptions)
  186. if (response.status !== descriptor.successStatus) await responseError(response, descriptor)
  187. if (!isContentType(response, "text/event-stream")) {
  188. try {
  189. await response.body?.cancel()
  190. } catch {}
  191. throw new ClientError("UnsupportedContentType")
  192. }
  193. if (response.body === null) throw new ClientError("MalformedResponse")
  194. const reader = response.body.getReader()
  195. const decoder = new TextDecoder()
  196. let buffer = ""
  197. try {
  198. while (true) {
  199. let next
  200. try {
  201. next = await reader.read()
  202. } catch (cause) {
  203. throw new ClientError("Transport", { cause })
  204. }
  205. buffer += decoder.decode(next.value, { stream: !next.done })
  206. if (buffer.length > 1_048_576) throw new ClientError("MalformedResponse")
  207. const trailingCarriageReturn = !next.done && buffer.endsWith("\r")
  208. if (trailingCarriageReturn) buffer = buffer.slice(0, -1)
  209. buffer = buffer.replaceAll("\r\n", "\n").replaceAll("\r", "\n")
  210. if (trailingCarriageReturn) buffer += "\r"
  211. if (next.done && buffer !== "") buffer += "\n\n"
  212. let boundary = buffer.indexOf("\n\n")
  213. while (boundary >= 0) {
  214. const block = buffer.slice(0, boundary)
  215. buffer = buffer.slice(boundary + 2)
  216. const data = block
  217. .split("\n")
  218. .flatMap((line) => (line.startsWith("data:") ? [line.slice(5).trimStart()] : []))
  219. .join("\n")
  220. if (data !== "") {
  221. try {
  222. yield JSON.parse(data) as A
  223. } catch (cause) {
  224. throw new ClientError("MalformedResponse", { cause })
  225. }
  226. }
  227. boundary = buffer.indexOf("\n\n")
  228. }
  229. if (next.done) return
  230. }
  231. } finally {
  232. try {
  233. await reader.cancel()
  234. } catch {}
  235. reader.releaseLock()
  236. }
  237. },
  238. })
  239. return {
  240. health: {
  241. get: (requestOptions?: RequestOptions) =>
  242. request<HealthGetOutput>(
  243. { method: "GET", path: `/api/health`, successStatus: 200, declaredStatuses: [401, 400], empty: false },
  244. requestOptions,
  245. ),
  246. },
  247. location: {
  248. get: (input?: LocationGetInput, requestOptions?: RequestOptions) =>
  249. request<LocationGetOutput>(
  250. {
  251. method: "GET",
  252. path: `/api/location`,
  253. query: { location: input?.["location"] },
  254. successStatus: 200,
  255. declaredStatuses: [401, 400],
  256. empty: false,
  257. },
  258. requestOptions,
  259. ),
  260. },
  261. agents: {
  262. list: (input?: AgentsListInput, requestOptions?: RequestOptions) =>
  263. request<AgentsListOutput>(
  264. {
  265. method: "GET",
  266. path: `/api/agent`,
  267. query: { location: input?.["location"] },
  268. successStatus: 200,
  269. declaredStatuses: [401, 400],
  270. empty: false,
  271. },
  272. requestOptions,
  273. ),
  274. },
  275. sessions: {
  276. list: (input?: SessionsListInput, requestOptions?: RequestOptions) =>
  277. request<SessionsListOutput>(
  278. {
  279. method: "GET",
  280. path: `/api/session`,
  281. query: {
  282. workspace: input?.["workspace"],
  283. limit: input?.["limit"],
  284. order: input?.["order"],
  285. search: input?.["search"],
  286. directory: input?.["directory"],
  287. project: input?.["project"],
  288. subpath: input?.["subpath"],
  289. cursor: input?.["cursor"],
  290. },
  291. successStatus: 200,
  292. declaredStatuses: [400, 401],
  293. empty: false,
  294. },
  295. requestOptions,
  296. ),
  297. create: (input?: SessionsCreateInput, requestOptions?: RequestOptions) =>
  298. request<{ readonly data: SessionsCreateOutput }>(
  299. {
  300. method: "POST",
  301. path: `/api/session`,
  302. body: {
  303. id: input?.["id"],
  304. agent: input?.["agent"],
  305. model: input?.["model"],
  306. location: input?.["location"],
  307. },
  308. successStatus: 200,
  309. declaredStatuses: [401, 400],
  310. empty: false,
  311. },
  312. requestOptions,
  313. ).then((value) => value.data),
  314. active: (requestOptions?: RequestOptions) =>
  315. request<{ readonly data: SessionsActiveOutput }>(
  316. {
  317. method: "GET",
  318. path: `/api/session/active`,
  319. successStatus: 200,
  320. declaredStatuses: [401, 400],
  321. empty: false,
  322. },
  323. requestOptions,
  324. ).then((value) => value.data),
  325. get: (input: SessionsGetInput, requestOptions?: RequestOptions) =>
  326. request<{ readonly data: SessionsGetOutput }>(
  327. {
  328. method: "GET",
  329. path: `/api/session/${encodeURIComponent(input.sessionID)}`,
  330. successStatus: 200,
  331. declaredStatuses: [404, 400, 401],
  332. empty: false,
  333. },
  334. requestOptions,
  335. ).then((value) => value.data),
  336. switchAgent: (input: SessionsSwitchAgentInput, requestOptions?: RequestOptions) =>
  337. request<SessionsSwitchAgentOutput>(
  338. {
  339. method: "POST",
  340. path: `/api/session/${encodeURIComponent(input.sessionID)}/agent`,
  341. body: { agent: input["agent"] },
  342. successStatus: 204,
  343. declaredStatuses: [404, 400, 401],
  344. empty: true,
  345. },
  346. requestOptions,
  347. ),
  348. switchModel: (input: SessionsSwitchModelInput, requestOptions?: RequestOptions) =>
  349. request<SessionsSwitchModelOutput>(
  350. {
  351. method: "POST",
  352. path: `/api/session/${encodeURIComponent(input.sessionID)}/model`,
  353. body: { model: input["model"] },
  354. successStatus: 204,
  355. declaredStatuses: [404, 400, 401],
  356. empty: true,
  357. },
  358. requestOptions,
  359. ),
  360. prompt: (input: SessionsPromptInput, requestOptions?: RequestOptions) =>
  361. request<{ readonly data: SessionsPromptOutput }>(
  362. {
  363. method: "POST",
  364. path: `/api/session/${encodeURIComponent(input.sessionID)}/prompt`,
  365. body: { id: input["id"], prompt: input["prompt"], delivery: input["delivery"], resume: input["resume"] },
  366. successStatus: 200,
  367. declaredStatuses: [409, 404, 400, 401],
  368. empty: false,
  369. },
  370. requestOptions,
  371. ).then((value) => value.data),
  372. compact: (input: SessionsCompactInput, requestOptions?: RequestOptions) =>
  373. request<SessionsCompactOutput>(
  374. {
  375. method: "POST",
  376. path: `/api/session/${encodeURIComponent(input.sessionID)}/compact`,
  377. successStatus: 204,
  378. declaredStatuses: [404, 503, 400, 401],
  379. empty: true,
  380. },
  381. requestOptions,
  382. ),
  383. wait: (input: SessionsWaitInput, requestOptions?: RequestOptions) =>
  384. request<SessionsWaitOutput>(
  385. {
  386. method: "POST",
  387. path: `/api/session/${encodeURIComponent(input.sessionID)}/wait`,
  388. successStatus: 204,
  389. declaredStatuses: [404, 503, 400, 401],
  390. empty: true,
  391. },
  392. requestOptions,
  393. ),
  394. stage: (input: SessionsStageInput, requestOptions?: RequestOptions) =>
  395. request<{ readonly data: SessionsStageOutput }>(
  396. {
  397. method: "POST",
  398. path: `/api/session/${encodeURIComponent(input.sessionID)}/revert/stage`,
  399. body: { messageID: input["messageID"], files: input["files"] },
  400. successStatus: 200,
  401. declaredStatuses: [404, 500, 400, 401],
  402. empty: false,
  403. },
  404. requestOptions,
  405. ).then((value) => value.data),
  406. clear: (input: SessionsClearInput, requestOptions?: RequestOptions) =>
  407. request<SessionsClearOutput>(
  408. {
  409. method: "POST",
  410. path: `/api/session/${encodeURIComponent(input.sessionID)}/revert/clear`,
  411. successStatus: 204,
  412. declaredStatuses: [404, 500, 400, 401],
  413. empty: true,
  414. },
  415. requestOptions,
  416. ),
  417. commit: (input: SessionsCommitInput, requestOptions?: RequestOptions) =>
  418. request<SessionsCommitOutput>(
  419. {
  420. method: "POST",
  421. path: `/api/session/${encodeURIComponent(input.sessionID)}/revert/commit`,
  422. successStatus: 204,
  423. declaredStatuses: [404, 400, 401],
  424. empty: true,
  425. },
  426. requestOptions,
  427. ),
  428. context: (input: SessionsContextInput, requestOptions?: RequestOptions) =>
  429. request<{ readonly data: SessionsContextOutput }>(
  430. {
  431. method: "GET",
  432. path: `/api/session/${encodeURIComponent(input.sessionID)}/context`,
  433. successStatus: 200,
  434. declaredStatuses: [404, 500, 400, 401],
  435. empty: false,
  436. },
  437. requestOptions,
  438. ).then((value) => value.data),
  439. history: (input: SessionsHistoryInput, requestOptions?: RequestOptions) =>
  440. request<SessionsHistoryOutput>(
  441. {
  442. method: "GET",
  443. path: `/api/session/${encodeURIComponent(input.sessionID)}/history`,
  444. query: { limit: input["limit"], after: input["after"] },
  445. successStatus: 200,
  446. declaredStatuses: [404, 400, 401],
  447. empty: false,
  448. },
  449. requestOptions,
  450. ),
  451. events: (input: SessionsEventsInput, requestOptions?: RequestOptions): AsyncIterable<SessionsEventsOutput> =>
  452. sse<SessionsEventsOutput>(
  453. {
  454. method: "GET",
  455. path: `/api/session/${encodeURIComponent(input.sessionID)}/event`,
  456. query: { after: input["after"] },
  457. successStatus: 200,
  458. declaredStatuses: [404, 400, 401],
  459. empty: false,
  460. },
  461. requestOptions,
  462. ),
  463. interrupt: (input: SessionsInterruptInput, requestOptions?: RequestOptions) =>
  464. request<SessionsInterruptOutput>(
  465. {
  466. method: "POST",
  467. path: `/api/session/${encodeURIComponent(input.sessionID)}/interrupt`,
  468. successStatus: 204,
  469. declaredStatuses: [404, 400, 401],
  470. empty: true,
  471. },
  472. requestOptions,
  473. ),
  474. message: (input: SessionsMessageInput, requestOptions?: RequestOptions) =>
  475. request<{ readonly data: SessionsMessageOutput }>(
  476. {
  477. method: "GET",
  478. path: `/api/session/${encodeURIComponent(input.sessionID)}/message/${encodeURIComponent(input.messageID)}`,
  479. successStatus: 200,
  480. declaredStatuses: [404, 400, 401],
  481. empty: false,
  482. },
  483. requestOptions,
  484. ).then((value) => value.data),
  485. },
  486. messages: {
  487. list: (input: MessagesListInput, requestOptions?: RequestOptions) =>
  488. request<MessagesListOutput>(
  489. {
  490. method: "GET",
  491. path: `/api/session/${encodeURIComponent(input.sessionID)}/message`,
  492. query: { limit: input["limit"], order: input["order"], cursor: input["cursor"] },
  493. successStatus: 200,
  494. declaredStatuses: [400, 404, 500, 401],
  495. empty: false,
  496. },
  497. requestOptions,
  498. ),
  499. },
  500. models: {
  501. list: (input?: ModelsListInput, requestOptions?: RequestOptions) =>
  502. request<ModelsListOutput>(
  503. {
  504. method: "GET",
  505. path: `/api/model`,
  506. query: { location: input?.["location"] },
  507. successStatus: 200,
  508. declaredStatuses: [503, 401, 400],
  509. empty: false,
  510. },
  511. requestOptions,
  512. ),
  513. },
  514. providers: {
  515. list: (input?: ProvidersListInput, requestOptions?: RequestOptions) =>
  516. request<ProvidersListOutput>(
  517. {
  518. method: "GET",
  519. path: `/api/provider`,
  520. query: { location: input?.["location"] },
  521. successStatus: 200,
  522. declaredStatuses: [503, 401, 400],
  523. empty: false,
  524. },
  525. requestOptions,
  526. ),
  527. get: (input: ProvidersGetInput, requestOptions?: RequestOptions) =>
  528. request<ProvidersGetOutput>(
  529. {
  530. method: "GET",
  531. path: `/api/provider/${encodeURIComponent(input.providerID)}`,
  532. query: { location: input["location"] },
  533. successStatus: 200,
  534. declaredStatuses: [404, 503, 401, 400],
  535. empty: false,
  536. },
  537. requestOptions,
  538. ),
  539. },
  540. integrations: {
  541. list: (input?: IntegrationsListInput, requestOptions?: RequestOptions) =>
  542. request<IntegrationsListOutput>(
  543. {
  544. method: "GET",
  545. path: `/api/integration`,
  546. query: { location: input?.["location"] },
  547. successStatus: 200,
  548. declaredStatuses: [401, 400],
  549. empty: false,
  550. },
  551. requestOptions,
  552. ),
  553. get: (input: IntegrationsGetInput, requestOptions?: RequestOptions) =>
  554. request<IntegrationsGetOutput>(
  555. {
  556. method: "GET",
  557. path: `/api/integration/${encodeURIComponent(input.integrationID)}`,
  558. query: { location: input["location"] },
  559. successStatus: 200,
  560. declaredStatuses: [401, 400],
  561. empty: false,
  562. },
  563. requestOptions,
  564. ),
  565. connectKey: (input: IntegrationsConnectKeyInput, requestOptions?: RequestOptions) =>
  566. request<IntegrationsConnectKeyOutput>(
  567. {
  568. method: "POST",
  569. path: `/api/integration/${encodeURIComponent(input.integrationID)}/connect/key`,
  570. query: { location: input["location"] },
  571. body: { key: input["key"], label: input["label"] },
  572. successStatus: 204,
  573. declaredStatuses: [400, 401],
  574. empty: true,
  575. },
  576. requestOptions,
  577. ),
  578. connectOauth: (input: IntegrationsConnectOauthInput, requestOptions?: RequestOptions) =>
  579. request<IntegrationsConnectOauthOutput>(
  580. {
  581. method: "POST",
  582. path: `/api/integration/${encodeURIComponent(input.integrationID)}/connect/oauth`,
  583. query: { location: input["location"] },
  584. body: { methodID: input["methodID"], inputs: input["inputs"], label: input["label"] },
  585. successStatus: 200,
  586. declaredStatuses: [400, 401],
  587. empty: false,
  588. },
  589. requestOptions,
  590. ),
  591. attemptStatus: (input: IntegrationsAttemptStatusInput, requestOptions?: RequestOptions) =>
  592. request<IntegrationsAttemptStatusOutput>(
  593. {
  594. method: "GET",
  595. path: `/api/integration/attempt/${encodeURIComponent(input.attemptID)}`,
  596. query: { location: input["location"] },
  597. successStatus: 200,
  598. declaredStatuses: [401, 400],
  599. empty: false,
  600. },
  601. requestOptions,
  602. ),
  603. attemptComplete: (input: IntegrationsAttemptCompleteInput, requestOptions?: RequestOptions) =>
  604. request<IntegrationsAttemptCompleteOutput>(
  605. {
  606. method: "POST",
  607. path: `/api/integration/attempt/${encodeURIComponent(input.attemptID)}/complete`,
  608. query: { location: input["location"] },
  609. body: { code: input["code"] },
  610. successStatus: 204,
  611. declaredStatuses: [400, 401],
  612. empty: true,
  613. },
  614. requestOptions,
  615. ),
  616. attemptCancel: (input: IntegrationsAttemptCancelInput, requestOptions?: RequestOptions) =>
  617. request<IntegrationsAttemptCancelOutput>(
  618. {
  619. method: "DELETE",
  620. path: `/api/integration/attempt/${encodeURIComponent(input.attemptID)}`,
  621. query: { location: input["location"] },
  622. successStatus: 204,
  623. declaredStatuses: [401, 400],
  624. empty: true,
  625. },
  626. requestOptions,
  627. ),
  628. },
  629. credentials: {
  630. update: (input: CredentialsUpdateInput, requestOptions?: RequestOptions) =>
  631. request<CredentialsUpdateOutput>(
  632. {
  633. method: "PATCH",
  634. path: `/api/credential/${encodeURIComponent(input.credentialID)}`,
  635. query: { location: input["location"] },
  636. body: { label: input["label"] },
  637. successStatus: 204,
  638. declaredStatuses: [401, 400],
  639. empty: true,
  640. },
  641. requestOptions,
  642. ),
  643. remove: (input: CredentialsRemoveInput, requestOptions?: RequestOptions) =>
  644. request<CredentialsRemoveOutput>(
  645. {
  646. method: "DELETE",
  647. path: `/api/credential/${encodeURIComponent(input.credentialID)}`,
  648. query: { location: input["location"] },
  649. successStatus: 204,
  650. declaredStatuses: [401, 400],
  651. empty: true,
  652. },
  653. requestOptions,
  654. ),
  655. },
  656. permissions: {
  657. listRequests: (input?: PermissionsListRequestsInput, requestOptions?: RequestOptions) =>
  658. request<PermissionsListRequestsOutput>(
  659. {
  660. method: "GET",
  661. path: `/api/permission/request`,
  662. query: { location: input?.["location"] },
  663. successStatus: 200,
  664. declaredStatuses: [401, 400],
  665. empty: false,
  666. },
  667. requestOptions,
  668. ),
  669. listSaved: (input?: PermissionsListSavedInput, requestOptions?: RequestOptions) =>
  670. request<{ readonly data: PermissionsListSavedOutput }>(
  671. {
  672. method: "GET",
  673. path: `/api/permission/saved`,
  674. query: { projectID: input?.["projectID"] },
  675. successStatus: 200,
  676. declaredStatuses: [401, 400],
  677. empty: false,
  678. },
  679. requestOptions,
  680. ).then((value) => value.data),
  681. removeSaved: (input: PermissionsRemoveSavedInput, requestOptions?: RequestOptions) =>
  682. request<PermissionsRemoveSavedOutput>(
  683. {
  684. method: "DELETE",
  685. path: `/api/permission/saved/${encodeURIComponent(input.id)}`,
  686. successStatus: 204,
  687. declaredStatuses: [401, 400],
  688. empty: true,
  689. },
  690. requestOptions,
  691. ),
  692. create: (input: PermissionsCreateInput, requestOptions?: RequestOptions) =>
  693. request<{ readonly data: PermissionsCreateOutput }>(
  694. {
  695. method: "POST",
  696. path: `/api/session/${encodeURIComponent(input.sessionID)}/permission`,
  697. body: {
  698. id: input["id"],
  699. action: input["action"],
  700. resources: input["resources"],
  701. save: input["save"],
  702. metadata: input["metadata"],
  703. source: input["source"],
  704. agent: input["agent"],
  705. },
  706. successStatus: 200,
  707. declaredStatuses: [404, 400, 401],
  708. empty: false,
  709. },
  710. requestOptions,
  711. ).then((value) => value.data),
  712. list: (input: PermissionsListInput, requestOptions?: RequestOptions) =>
  713. request<{ readonly data: PermissionsListOutput }>(
  714. {
  715. method: "GET",
  716. path: `/api/session/${encodeURIComponent(input.sessionID)}/permission`,
  717. successStatus: 200,
  718. declaredStatuses: [404, 400, 401],
  719. empty: false,
  720. },
  721. requestOptions,
  722. ).then((value) => value.data),
  723. get: (input: PermissionsGetInput, requestOptions?: RequestOptions) =>
  724. request<{ readonly data: PermissionsGetOutput }>(
  725. {
  726. method: "GET",
  727. path: `/api/session/${encodeURIComponent(input.sessionID)}/permission/${encodeURIComponent(input.requestID)}`,
  728. successStatus: 200,
  729. declaredStatuses: [404, 400, 401],
  730. empty: false,
  731. },
  732. requestOptions,
  733. ).then((value) => value.data),
  734. reply: (input: PermissionsReplyInput, requestOptions?: RequestOptions) =>
  735. request<PermissionsReplyOutput>(
  736. {
  737. method: "POST",
  738. path: `/api/session/${encodeURIComponent(input.sessionID)}/permission/${encodeURIComponent(input.requestID)}/reply`,
  739. body: { reply: input["reply"], message: input["message"] },
  740. successStatus: 204,
  741. declaredStatuses: [404, 400, 401],
  742. empty: true,
  743. },
  744. requestOptions,
  745. ),
  746. },
  747. files: {
  748. list: (input?: FilesListInput, requestOptions?: RequestOptions) =>
  749. request<FilesListOutput>(
  750. {
  751. method: "GET",
  752. path: `/api/fs/list`,
  753. query: { location: input?.["location"], path: input?.["path"] },
  754. successStatus: 200,
  755. declaredStatuses: [401, 400],
  756. empty: false,
  757. },
  758. requestOptions,
  759. ),
  760. find: (input: FilesFindInput, requestOptions?: RequestOptions) =>
  761. request<FilesFindOutput>(
  762. {
  763. method: "GET",
  764. path: `/api/fs/find`,
  765. query: { location: input["location"], query: input["query"], type: input["type"], limit: input["limit"] },
  766. successStatus: 200,
  767. declaredStatuses: [401, 400],
  768. empty: false,
  769. },
  770. requestOptions,
  771. ),
  772. },
  773. commands: {
  774. list: (input?: CommandsListInput, requestOptions?: RequestOptions) =>
  775. request<CommandsListOutput>(
  776. {
  777. method: "GET",
  778. path: `/api/command`,
  779. query: { location: input?.["location"] },
  780. successStatus: 200,
  781. declaredStatuses: [401, 400],
  782. empty: false,
  783. },
  784. requestOptions,
  785. ),
  786. },
  787. skills: {
  788. list: (input?: SkillsListInput, requestOptions?: RequestOptions) =>
  789. request<SkillsListOutput>(
  790. {
  791. method: "GET",
  792. path: `/api/skill`,
  793. query: { location: input?.["location"] },
  794. successStatus: 200,
  795. declaredStatuses: [401, 400],
  796. empty: false,
  797. },
  798. requestOptions,
  799. ),
  800. },
  801. events: {
  802. subscribe: (requestOptions?: RequestOptions): AsyncIterable<EventsSubscribeOutput> =>
  803. sse<EventsSubscribeOutput>(
  804. { method: "GET", path: `/api/event`, successStatus: 200, declaredStatuses: [401, 400], empty: false },
  805. requestOptions,
  806. ),
  807. },
  808. ptys: {
  809. list: (input?: PtysListInput, requestOptions?: RequestOptions) =>
  810. request<PtysListOutput>(
  811. {
  812. method: "GET",
  813. path: `/api/pty`,
  814. query: { location: input?.["location"] },
  815. successStatus: 200,
  816. declaredStatuses: [401, 400],
  817. empty: false,
  818. },
  819. requestOptions,
  820. ),
  821. create: (input?: PtysCreateInput, requestOptions?: RequestOptions) =>
  822. request<PtysCreateOutput>(
  823. {
  824. method: "POST",
  825. path: `/api/pty`,
  826. query: { location: input?.["location"] },
  827. body: {
  828. command: input?.["command"],
  829. args: input?.["args"],
  830. cwd: input?.["cwd"],
  831. title: input?.["title"],
  832. env: input?.["env"],
  833. },
  834. successStatus: 200,
  835. declaredStatuses: [401, 400],
  836. empty: false,
  837. },
  838. requestOptions,
  839. ),
  840. get: (input: PtysGetInput, requestOptions?: RequestOptions) =>
  841. request<PtysGetOutput>(
  842. {
  843. method: "GET",
  844. path: `/api/pty/${encodeURIComponent(input.ptyID)}`,
  845. query: { location: input["location"] },
  846. successStatus: 200,
  847. declaredStatuses: [404, 401, 400],
  848. empty: false,
  849. },
  850. requestOptions,
  851. ),
  852. update: (input: PtysUpdateInput, requestOptions?: RequestOptions) =>
  853. request<PtysUpdateOutput>(
  854. {
  855. method: "PUT",
  856. path: `/api/pty/${encodeURIComponent(input.ptyID)}`,
  857. query: { location: input["location"] },
  858. body: { title: input["title"], size: input["size"] },
  859. successStatus: 200,
  860. declaredStatuses: [404, 401, 400],
  861. empty: false,
  862. },
  863. requestOptions,
  864. ),
  865. remove: (input: PtysRemoveInput, requestOptions?: RequestOptions) =>
  866. request<PtysRemoveOutput>(
  867. {
  868. method: "DELETE",
  869. path: `/api/pty/${encodeURIComponent(input.ptyID)}`,
  870. query: { location: input["location"] },
  871. successStatus: 204,
  872. declaredStatuses: [404, 401, 400],
  873. empty: true,
  874. },
  875. requestOptions,
  876. ),
  877. },
  878. questions: {
  879. listRequests: (input?: QuestionsListRequestsInput, requestOptions?: RequestOptions) =>
  880. request<QuestionsListRequestsOutput>(
  881. {
  882. method: "GET",
  883. path: `/api/question/request`,
  884. query: { location: input?.["location"] },
  885. successStatus: 200,
  886. declaredStatuses: [401, 400],
  887. empty: false,
  888. },
  889. requestOptions,
  890. ),
  891. list: (input: QuestionsListInput, requestOptions?: RequestOptions) =>
  892. request<{ readonly data: QuestionsListOutput }>(
  893. {
  894. method: "GET",
  895. path: `/api/session/${encodeURIComponent(input.sessionID)}/question`,
  896. successStatus: 200,
  897. declaredStatuses: [404, 400, 401],
  898. empty: false,
  899. },
  900. requestOptions,
  901. ).then((value) => value.data),
  902. reply: (input: QuestionsReplyInput, requestOptions?: RequestOptions) =>
  903. request<QuestionsReplyOutput>(
  904. {
  905. method: "POST",
  906. path: `/api/session/${encodeURIComponent(input.sessionID)}/question/${encodeURIComponent(input.requestID)}/reply`,
  907. body: { answers: input["answers"] },
  908. successStatus: 204,
  909. declaredStatuses: [404, 400, 401],
  910. empty: true,
  911. },
  912. requestOptions,
  913. ),
  914. reject: (input: QuestionsRejectInput, requestOptions?: RequestOptions) =>
  915. request<QuestionsRejectOutput>(
  916. {
  917. method: "POST",
  918. path: `/api/session/${encodeURIComponent(input.sessionID)}/question/${encodeURIComponent(input.requestID)}/reject`,
  919. successStatus: 204,
  920. declaredStatuses: [404, 400, 401],
  921. empty: true,
  922. },
  923. requestOptions,
  924. ),
  925. },
  926. references: {
  927. list: (input?: ReferencesListInput, requestOptions?: RequestOptions) =>
  928. request<ReferencesListOutput>(
  929. {
  930. method: "GET",
  931. path: `/api/reference`,
  932. query: { location: input?.["location"] },
  933. successStatus: 200,
  934. declaredStatuses: [401, 400],
  935. empty: false,
  936. },
  937. requestOptions,
  938. ),
  939. },
  940. projectCopies: {
  941. create: (input: ProjectCopiesCreateInput, requestOptions?: RequestOptions) =>
  942. request<ProjectCopiesCreateOutput>(
  943. {
  944. method: "POST",
  945. path: `/experimental/project/${encodeURIComponent(input.projectID)}/copy`,
  946. query: { location: input["location"] },
  947. body: { strategy: input["strategy"], directory: input["directory"], name: input["name"] },
  948. successStatus: 200,
  949. declaredStatuses: [400, 401],
  950. empty: false,
  951. },
  952. requestOptions,
  953. ),
  954. remove: (input: ProjectCopiesRemoveInput, requestOptions?: RequestOptions) =>
  955. request<ProjectCopiesRemoveOutput>(
  956. {
  957. method: "DELETE",
  958. path: `/experimental/project/${encodeURIComponent(input.projectID)}/copy`,
  959. query: { location: input["location"] },
  960. body: { directory: input["directory"], force: input["force"] },
  961. successStatus: 204,
  962. declaredStatuses: [400, 401],
  963. empty: true,
  964. },
  965. requestOptions,
  966. ),
  967. refresh: (input: ProjectCopiesRefreshInput, requestOptions?: RequestOptions) =>
  968. request<ProjectCopiesRefreshOutput>(
  969. {
  970. method: "POST",
  971. path: `/experimental/project/${encodeURIComponent(input.projectID)}/copy/refresh`,
  972. query: { location: input["location"] },
  973. successStatus: 204,
  974. declaredStatuses: [400, 401],
  975. empty: true,
  976. },
  977. requestOptions,
  978. ),
  979. },
  980. }
  981. }
  982. function appendQuery(params: URLSearchParams, key: string, value: unknown): void {
  983. if (value === undefined || value === null) return
  984. if (Array.isArray(value)) {
  985. for (const item of value) appendQuery(params, key, item)
  986. return
  987. }
  988. if (typeof value === "object") {
  989. for (const [child, item] of Object.entries(value)) appendQuery(params, `${key}[${child}]`, item)
  990. return
  991. }
  992. params.append(key, String(value))
  993. }
  994. async function json(response: Response): Promise<unknown> {
  995. if (!isContentType(response, "application/json") && !response.headers.get("content-type")?.includes("+json")) {
  996. try {
  997. await response.body?.cancel()
  998. } catch {}
  999. throw new ClientError("UnsupportedContentType")
  1000. }
  1001. let text: string
  1002. try {
  1003. text = await response.text()
  1004. } catch (cause) {
  1005. throw new ClientError("Transport", { cause })
  1006. }
  1007. if (text === "") throw new ClientError("MalformedResponse")
  1008. try {
  1009. return JSON.parse(text)
  1010. } catch (cause) {
  1011. throw new ClientError("MalformedResponse", { cause })
  1012. }
  1013. }
  1014. function isContentType(response: Response, expected: string) {
  1015. return response.headers.get("content-type")?.split(";", 1)[0]?.trim().toLowerCase() === expected
  1016. }