@standards/client 1.0.0-alpha.419 → 1.0.0-alpha.425
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app-BgWz3r5k.js +9 -0
- package/dist/app-TJt8rk9y.mjs +9 -0
- package/dist/app-_CiXRLoD.d.mts +292 -0
- package/dist/app-_CiXRLoD.d.ts +292 -0
- package/dist/app.d.mts +2 -67
- package/dist/app.d.ts +2 -67
- package/dist/app.js +1 -1
- package/dist/app.mjs +1 -1
- package/dist/create-standards-2D3Tmvj1.js +4 -0
- package/dist/create-standards-CZ_ZYNz8.mjs +4 -0
- package/dist/{create-standards-BWOo2EZw.d.ts → create-standards-De7-xdtZ.d.ts} +129 -163
- package/dist/{create-standards-HiWpTAlP.d.mts → create-standards-lDN6ru8u.d.mts} +129 -163
- package/dist/index.d.mts +26 -9
- package/dist/index.d.ts +26 -9
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/dist/testing.d.mts +6 -4
- package/dist/testing.d.ts +6 -4
- package/dist/testing.js +1 -1
- package/dist/testing.mjs +1 -1
- package/package.json +2 -2
- package/dist/create-standards-Bl-VDgXY.js +0 -4
- package/dist/create-standards-Dn5ZKfjN.mjs +0 -4
- package/dist/http-transport-BxJhcXjy.d.mts +0 -161
- package/dist/http-transport-BxJhcXjy.d.ts +0 -161
- package/dist/http-transport-Dr0ZiTG1.js +0 -2
- package/dist/http-transport-GAQftrWY.mjs +0 -2
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/*! © 2025-2026 AND YOU CREATE SAS (RCS Paris 940 190 614). Proprietary — see LICENSE (Standards SDK License 1.0). */
|
|
2
|
+
let e=require("@standards/schema"),t=require("@standards/schema/api");function schemaApiErrorCode(e){if(typeof e!=`object`||!e||!(`code`in e))return;let{code:t}=e;return typeof t==`string`?t:void 0}const n=/* @__PURE__ */ new Set([e.SchemaErrorCode.CONFIGURATION_REQUIRED]);function isPermanentRefusal(e){let t=schemaApiErrorCode(e);return t!==void 0&&n.has(t)}function isObjectNotFound(t){if(typeof t!=`object`||!t)return!1;let{code:n,status:r}=t;return n===e.SchemaErrorCode.OBJECT_NOT_FOUND||r===404}function isDraftRevisionConflict(t){return schemaApiErrorCode(t)===e.SchemaErrorCode.DRAFT_REVISION_CONFLICT}const r=new Set(e.DRAFT_CONFLICT_KINDS);function draftConflictChanges(e){if(!isDraftRevisionConflict(e))return[];let t=e.details?.changes;return Array.isArray(t)?t.filter(e=>typeof e==`object`&&!!e&&typeof e.key==`string`&&typeof e.label==`string`&&typeof e.seen==`string`&&r.has(e.kind)):[]}function isViewNotFound(e){return typeof e!=`object`||!e?!1:e.status===404}var StandardsRequestError=class extends Error{constructor(e,t,n,r){super(t),this.name=`StandardsRequestError`,this.status=e,this.code=n,this.details=r}},StandardsAuthError=class extends StandardsRequestError{constructor(e,t,n,r){super(e,t,n,r),this.name=`StandardsAuthError`}},BundleConflictError=class extends StandardsRequestError{constructor(e,t,n){super(e,t,n),this.name=`BundleConflictError`;let r=/"([^"]+)" is owned by (\S+)/.exec(t);this.objectName=r?.[1]??``,this.owner=r?.[2]??``}},BundleValidationError=class extends StandardsRequestError{constructor(e,t,n){super(e,t,n),this.name=`BundleValidationError`}},StandardsConfigurationError=class extends Error{constructor(e){super(e),this.name=`StandardsConfigurationError`}};const i=[1e3,2e3,5e3],a=/* @__PURE__ */ new Set([`turn.completed`,`turn.failed`,`turn.cancelled`]);function parseSseFrame(e){let t,n=`message`,r,i=[];for(let a of e.split(`
|
|
3
|
+
`)){let e=a.endsWith(`\r`)?a.slice(0,-1):a;if(e===``||e.startsWith(`:`))continue;let o=e.indexOf(`:`),s=o===-1?e:e.slice(0,o),c=o===-1?``:e.slice(o+1);c.startsWith(` `)&&(c=c.slice(1)),s===`id`?t=c:s===`event`?n=c:s===`data`?i.push(c):s===`retry`&&/^\d+$/.test(c)&&(r=Number(c))}return{id:t,event:n,data:i.join(`
|
|
4
|
+
`),retry:r}}function parseEvent(t){let n;try{n=JSON.parse(t.data)}catch{return}if((0,e.isPlainRecord)(n)&&typeof n.type==`string`&&typeof n.seq==`number`&&Number.isSafeInteger(n.seq)&&n.seq>0&&(t.id===void 0||t.id===String(n.seq)))return n}function parseControl(t){let n;try{n=JSON.parse(t.data)}catch{return}if(!(0,e.isPlainRecord)(n))return;let r=n.control;return r===`up-to-date`||r===`lease-ended`||r===`inbox`?r:void 0}function isUnresolvableActor(e){return e.status===401&&e.code===`ACTOR_RESOLUTION_FAILED`}function isTerminalRefusal(e){return e.status===400||e.status===403||e.status===404||isUnresolvableActor(e)}function isCursorExpired(e){return e instanceof StandardsRequestError&&e.status===410&&e.code===`AGENT_SESSION_STREAM_CURSOR_EXPIRED`}function openAgentStream(e){let t=!1,n,r,a,o=1e3,s=0,c,l=e.subscribeAuthChanges?.(()=>{t||(s+=1,c?.(),c=void 0)});function endWait(){r!==void 0&&clearTimeout(r),r=void 0,a?.(),a=void 0}function close(){t||(t=!0,n?.abort(),endWait(),c?.(),c=void 0,l?.())}function waitForAuthChange(e){return t||s!==e?Promise.resolve():new Promise(e=>{c=e})}function sleep(e){return new Promise(t=>{a=t,r=setTimeout(endWait,e)})}function handleFrame(t){let n=parseSseFrame(t);if(n.retry!==void 0&&(o=n.retry),n.data===``)return`skipped`;if(n.event===`control`){let t=parseControl(n);return t&&e.onControl(t),t===`lease-ended`?`lease-ended`:`skipped`}if(n.event!==`event`)return`skipped`;let r=parseEvent(n);return r?r.seq<=e.cursor()?`skipped`:(e.onEvent(r),`delivered`):`malformed`}async function consume(e,n){let r=e.body;if(r===null)return{delivered:!1,end:`failed`};let i=r.getReader(),a=new TextDecoder,o=``,s=!1;try{for(;;){let{done:e,value:r}=await i.read();if(t||e)return{delivered:s,end:`clean`};o+=a.decode(r,{stream:!0}).replace(/\r\n/g,`
|
|
5
|
+
`);let c=o.indexOf(`
|
|
6
|
+
|
|
7
|
+
`);for(;c!==-1;){let e=o.slice(0,c);o=o.slice(c+2);let r=handleFrame(e);if(r===`delivered`&&(s=!0),t)return{delivered:s,end:`clean`};if(r===`malformed`)return n.abort(),{delivered:s,end:`malformed`};if(r===`lease-ended`)return{delivered:s,end:`lease-ended`};c=o.indexOf(`
|
|
8
|
+
|
|
9
|
+
`)}}}catch{return{delivered:s,end:`failed`}}finally{i.releaseLock()}}async function afterFailedOpen(t,n,r){if(isCursorExpired(t))try{return await e.onExpired(),r?`back-off`:`reopen`}catch{return`back-off`}return t instanceof StandardsRequestError?isTerminalRefusal(t)?(close(),e.onStatus(`error`,t),`stop`):t.status===401?(e.onStatus(`auth-blocked`,t),await waitForAuthChange(n),`reopen`):`back-off`:`back-off`}let u,d=0;async function rehydratedPastStall(t){if(e.cursor()!==t||(d=u===t?d+1:1,u=t,d<3))return!1;u=void 0,d=0;try{return await e.onExpired(),!0}catch{return!1}}function delayAfter(e,t){return e===`lease-ended`?0:e===`clean`||e===`malformed`?o:i[Math.min(t,i.length-1)]??5e3}async function run(){let r=!0,i=0,a=!1;for(;!t;){e.onStatus(r?`connecting`:`reconnecting`),r=!1;let o=new AbortController;n=o;let c=s,l=`failed`;try{let n=await e.open(e.sessionId,e.cursor(),o.signal,()=>{c=s});if(t)return;e.onStatus(`connected`);let r=e.cursor(),u=await consume(n,o);if(l=u.end,l===`malformed`&&await rehydratedPastStall(r)){if(t)return;continue}u.delivered&&(i=0,a=!1)}catch(e){if(t)return;let n=isCursorExpired(e),r=await afterFailedOpen(e,c,a);if(a=n,r===`stop`||t)return;if(r===`reopen`)continue}if(t)return;e.onStatus(`reconnecting`);let u=delayAfter(l,i);l===`failed`&&(i+=1),u>0&&await sleep(u)}}return run().catch(()=>void 0),{close,wake:endWait}}function parseContentDispositionFilename(e){if(!e)return;let t=e.match(/filename\*\s*=\s*(?:UTF-8|utf-8)''([^;]+)/i);if(t?.[1])try{return decodeURIComponent(t[1].trim())}catch{}let n=e.match(/filename\s*=\s*"([^"]*)"|filename\s*=\s*([^;]+)/i);return(n?.[1]??n?.[2])?.trim()||void 0}function recordsPath(e,...n){return[`/records`,...[e,...n].map(t.encodePathSegment)].join(`/`)}function resolveWithinBase(t,n){let r=t.endsWith(`/`)?t:`${t}/`,i=new URL(r),a=n.replace(/^\/+/,``),[o]=a.split(/[?#]/);if((o??``).split(`/`).some(e=>e===`..`||e===`.`))throw new e.ValidationError(`Request path "${n}" walks outside its own collection`,[]);let s=new URL(a,i);if(s.origin!==i.origin||!s.pathname.startsWith(i.pathname))throw new e.ValidationError(`Request path "${n}" resolves outside the API base "${i.pathname}"`,[]);return s}function readJson(e){return e.status===204||e.headers.get(`content-length`)===`0`?null:e.json()}async function readDownload(e){let t=await e.blob();return{blob:t,filename:parseContentDispositionFilename(e.headers.get(`Content-Disposition`)),mimeType:e.headers.get(`Content-Type`)??t.type}}function multipartBody(e,t){let n=new FormData;for(let[r,i]of Object.entries(t??{}))if(i!=null){if(r===e)for(let t of Array.isArray(i)?i:[i]){let r=t.name;typeof r==`string`?n.append(e,t,r):n.append(e,t)}else n.append(r,String(i))}return n}function headerRecord(e){return e===void 0?{}:e instanceof Headers?Object.fromEntries(e.entries()):Array.isArray(e)?Object.fromEntries(e):{...e}}function withoutContentType(e){return Object.fromEntries(Object.entries(e).filter(([e])=>e.toLowerCase()!==`content-type`))}function parseJsonObject(e){try{let t=JSON.parse(e);return typeof t==`object`&&t?t:{}}catch{return}}function refusalFrom(e,t,n){let r=parseJsonObject(t),i=r?.message??r?.error??r?.detail,a=i==null?n&&r===void 0&&t?t:`Request failed with status ${e}`:String(i),o=typeof r?.code==`string`?r.code:void 0;return new(e===401||e===403?StandardsAuthError:StandardsRequestError)(e,a,o,r?.details)}function refusalOf(e,t){return refusalFrom(e,t,!1)}async function readRefusal(e){return refusalOf(e.status,await e.text().catch(()=>``))}function isTimeout(e){return e instanceof DOMException&&e.name===`TimeoutError`}function trimSlashes(e,t){let n=0,r=e.length;for(;t&&n<r&&e[n]===`/`;)n+=1;for(;r>n&&e[r-1]===`/`;)--r;return e.slice(n,r)}function backoff(e){return new Promise(t=>setTimeout(t,1e3*2**e))}function abortReason(e){return e?.aborted?e.reason:new DOMException(`The operation was aborted.`,`AbortError`)}function canReportUploadProgress(e){return typeof XMLHttpRequest>`u`?!1:e.fetch===void 0||e.uploadAuthorization!==void 0}function sendWithProgress(e,t){let{signal:n}=e;return n?.aborted?Promise.reject(abortReason(n)):new Promise((r,i)=>{let a=new XMLHttpRequest;a.open(e.method,e.url);for(let[t,n]of Object.entries(e.headers))a.setRequestHeader(t,n);let o=Object.keys(e.headers).some(e=>e.toLowerCase()===`authorization`);e.token&&!o&&a.setRequestHeader(`Authorization`,`Bearer ${e.token}`),a.upload.addEventListener(`progress`,t=>{t.lengthComputable&&e.onUploadProgress({loaded:t.loaded,total:t.total})});let onAbort=()=>a.abort();n?.addEventListener(`abort`,onAbort,{once:!0});let settle=()=>n?.removeEventListener(`abort`,onAbort);a.addEventListener(`load`,()=>{if(settle(),a.status<200||a.status>=300)i(refusalOf(a.status,a.responseText));else try{r(t(a.responseText))}catch(e){i(e)}}),a.addEventListener(`error`,()=>{settle(),i(new StandardsRequestError(0,`Network request failed`))}),a.addEventListener(`abort`,()=>{settle(),i(abortReason(n))}),a.send(e.form)})}function createHttpTransport(e){let{baseUrl:n,onUnauthorized:r,getRetries:i=0}=e,a=e.timeoutMs??3e4,o=e.apiPrefix===void 0?void 0:trimSlashes(e.apiPrefix,!0),s=o?`${trimSlashes(n,!1)}/${o}`:n;function buildUrl(e,t){let n=resolveWithinBase(s,e);for(let[e,r]of Object.entries(t??{}))r!=null&&n.searchParams.set(e,String(r));return n.toString()}async function headersFor(t){let n={"Content-Type":`application/json`,...headerRecord(await e.headers?.()),...headerRecord(t.headers)};return t.body instanceof FormData?withoutContentType(n):n}function observe(t){try{e.onResponse?.(t)}catch{}}async function fetchOnce(t,n,r){let i=n.signal??void 0;i?.throwIfAborted();let a=r===null?void 0:AbortSignal.timeout(r),o=new AbortController,expire=()=>o.abort(a?.reason);a?.addEventListener(`abort`,expire,{once:!0});let s=i?AbortSignal.any([i,o.signal]):o.signal,c=new Promise((e,t)=>{s.addEventListener(`abort`,()=>t(s.reason),{once:!0})});try{let r=e.fetch??fetch,i=await headersFor(n);return await Promise.race([r(t,{...n,headers:i,signal:s}),c])}catch(e){throw i?.aborted?i.reason:e}finally{a?.removeEventListener(`abort`,expire)}}function connectionFailure(e){return e instanceof TypeError||isTimeout(e)?new StandardsRequestError(0,`Could not connect to ${n}`):e}async function refreshAndRetry(e,t,n){try{if(!await r?.())return;let i=await fetchOnce(e,t,n);return observe(i),i}catch{if(t.signal?.aborted)throw t.signal.reason;return}}async function readRefusalWithin(e){let t,n=new Promise(n=>{t=setTimeout(()=>n(refusalFrom(e.status,``,!1)),1500)});try{let t=e.text().catch(()=>``).then(t=>refusalFrom(e.status,t,!1));return await Promise.race([t,n])}finally{clearTimeout(t)}}async function send(e,t,n,o){let s=buildUrl(e,n.params),c=(t.method??`GET`).toUpperCase(),l=n.maxRetries??(c===`GET`?i:0),u=n.timeoutMs===void 0?a:n.timeoutMs;for(let e=0;;e++){let i=e<l,a;try{a=await fetchOnce(s,t,u)}catch(n){if(i&&n instanceof TypeError&&!t.signal?.aborted){await backoff(e);continue}throw connectionFailure(n)}if(observe(a),a.status>=500&&i){let t=await readRefusalWithin(a);if(isPermanentRefusal(t))throw t;await backoff(e)}else{if(a.status===401&&r&&(a=await refreshAndRetry(s,t,u)??a),!a.ok){let e=await a.text().catch(()=>``);throw refusalFrom(a.status,e,n.plainTextRefusal??!1)}return await o(a)}}}async function stream(n,i,a={}){let{path:o,query:s,body:c,headers:l}=(0,t.splitOperationInput)(n,i??{}),u=buildUrl(o,s),{signal:d,onRequest:f}=a,p=e.fetch??fetch,attempt=async()=>(f?.(),await p(u,{method:n.method,body:c===void 0?void 0:JSON.stringify(c),signal:d,headers:await headersFor({headers:{...l,...a.headers}})})),m=await attempt();if(m.status===401){let e=await readRefusal(m);if(e.code===`MFA_REQUIRED`||!r||!await r().catch(()=>!1))throw e;d?.throwIfAborted(),m=await attempt()}if(!m.ok)throw await readRefusal(m);return m}async function json(e,t,n){return await send(t,{method:e,body:n?JSON.stringify(n):void 0},{},readJson)}return{async call(n,r,i={}){if(n.response===`events`)return await stream(n,r,{signal:i.signal});let{path:a,query:o,body:s,headers:c}=(0,t.splitOperationInput)(n,r??{});if(n.upload!==void 0&&i.onUploadProgress&&canReportUploadProgress(e)){i.signal?.throwIfAborted();let r=await e.uploadAuthorization?.()??null;return await sendWithProgress({url:buildUrl(a,o),method:n.method,headers:withoutContentType({...headerRecord(await e.headers?.()),...c}),token:r,form:multipartBody(n.upload.field,s),onUploadProgress:i.onUploadProgress,signal:i.signal},e=>(0,t.decodeOperationOutput)(n,e?JSON.parse(e):null))}let l=n.upload===void 0?s===void 0?void 0:JSON.stringify(s):multipartBody(n.upload.field,s),u=n.response===`bytes`?readDownload:async e=>(0,t.decodeOperationOutput)(n,await readJson(e));return await send(a,{method:n.method,body:l,signal:i.signal,...c?{headers:c}:{},...i.keepalive?{keepalive:!0}:{}},{params:o,maxRetries:i.maxRetries,timeoutMs:i.timeoutMs},u)},stream,async get(e,t){return await send(e,{method:`GET`},{params:t},readJson)},post:(e,t)=>json(`POST`,e,t),patch:(e,t)=>json(`PATCH`,e,t),put:(e,t)=>json(`PUT`,e,t),delete:e=>json(`DELETE`,e),async getText(e,t){return await send(e,{method:`GET`},{params:t,plainTextRefusal:!0},e=>e.text())},async postRaw(e,t){return await send(e,{method:`POST`,body:JSON.stringify(t)},{plainTextRefusal:!0},e=>e)},async postMultipart(e,t,n={}){return await send(e,{method:`POST`,body:t},{timeoutMs:n.timeoutMs},readJson)}}}function createTransport(e){let{baseUrl:t,apiKey:n,tenantId:r,timeoutMs:i}=e,a={Authorization:`Bearer ${n}`,...r?{"X-Tenant-ID":r}:{}};return createHttpTransport({baseUrl:t,timeoutMs:i,headers:()=>a})}function asStrings(e){let t=Object.entries(e??{}).flatMap(([e,t])=>t==null?[]:[[e,String(t)]]);return Object.fromEntries(t)}async function uploadedPart(e){let t=e.name;return{name:typeof t==`string`?t:`blob`,mimeType:e.type===``?`application/octet-stream`:e.type,size:e.size,content:new Uint8Array(await e.arrayBuffer())}}async function wireRequest(e,n){let{query:r,body:i,headers:a}=(0,t.splitOperationInput)(e,n),o=Object.fromEntries((0,t.pathParamNames)(e.path).map(e=>[e,String(n[e])])),s=Object.fromEntries(Object.entries(a??{}).map(([e,t])=>[e.toLowerCase(),t])),c={params:o,query:asStrings(r),headers:s};if(e.upload===void 0)return{...c,body:i===void 0?void 0:JSON.parse(JSON.stringify(i))};let{[e.upload.field]:l,...u}=i??{},d=l==null?[]:Array.isArray(l)?l:[l];return{...c,body:asStrings(u),uploads:await Promise.all(d.map(uploadedPart))}}function downloaded(e){let t=typeof e.content==`string`?e.content:new Uint8Array(e.content);return{blob:new Blob([t],{type:e.mimeType}),filename:e.filename,mimeType:e.mimeType}}function createInProcessTransport(e){return transportActingAs(e,void 0)}function transportActingAs(e,n){async function call(r,i,a={}){if(a.signal?.throwIfAborted(),r.response===`events`)throw Error(`Operation ${r.name} streams over HTTP only`);let o=await wireRequest(r,i??{}),s;try{s=await e.execute(r,o,n)}catch(e){throw(0,t.isOperationRefused)(e)?refusalOf(e.status,JSON.stringify(e.body)):e}if(r.response===`bytes`)return downloaded(s);let c=s===void 0?null:JSON.parse(JSON.stringify(s));return(0,t.decodeOperationOutput)(r,c)}return{call,stream:e=>Promise.reject(/* @__PURE__ */ Error(`Operation ${e.name} streams over HTTP only`)),withCaller:t=>transportActingAs(e,t)}}function createAppClient(e){let n={},r=Object.values(t.appOperationGroups);for(let i of r.flatMap(e=>Object.values(e))){let r=(0,t.operationGroup)(i),a=i.name.slice(r.length+1);n[r]??={},n[r][a]=(t,n)=>i.response===`events`?e.stream(i,t,n):e.call(i,t,n)}return n}Object.defineProperty(exports,"_",{enumerable:!0,get:function(){return isDraftRevisionConflict}}),Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return readRefusal}}),Object.defineProperty(exports,"b",{enumerable:!0,get:function(){return isViewNotFound}}),Object.defineProperty(exports,"c",{enumerable:!0,get:function(){return parseContentDispositionFilename}}),Object.defineProperty(exports,"d",{enumerable:!0,get:function(){return BundleConflictError}}),Object.defineProperty(exports,"f",{enumerable:!0,get:function(){return BundleValidationError}}),Object.defineProperty(exports,"g",{enumerable:!0,get:function(){return draftConflictChanges}}),Object.defineProperty(exports,"h",{enumerable:!0,get:function(){return StandardsRequestError}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return createTransport}}),Object.defineProperty(exports,"l",{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,"m",{enumerable:!0,get:function(){return StandardsConfigurationError}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return createInProcessTransport}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return refusalOf}}),Object.defineProperty(exports,"p",{enumerable:!0,get:function(){return StandardsAuthError}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return createHttpTransport}}),Object.defineProperty(exports,"s",{enumerable:!0,get:function(){return recordsPath}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return createAppClient}}),Object.defineProperty(exports,"u",{enumerable:!0,get:function(){return openAgentStream}}),Object.defineProperty(exports,"v",{enumerable:!0,get:function(){return isObjectNotFound}}),Object.defineProperty(exports,"x",{enumerable:!0,get:function(){return schemaApiErrorCode}}),Object.defineProperty(exports,"y",{enumerable:!0,get:function(){return isPermanentRefusal}});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/*! © 2025-2026 AND YOU CREATE SAS (RCS Paris 940 190 614). Proprietary — see LICENSE (Standards SDK License 1.0). */
|
|
2
|
+
import{DRAFT_CONFLICT_KINDS as e,SchemaErrorCode as t,ValidationError as n,isPlainRecord as r}from"@standards/schema";import{appOperationGroups as i,decodeOperationOutput as a,encodePathSegment as o,isOperationRefused as s,operationGroup as c,pathParamNames as l,splitOperationInput as u}from"@standards/schema/api";function schemaApiErrorCode(e){if(typeof e!=`object`||!e||!(`code`in e))return;let{code:t}=e;return typeof t==`string`?t:void 0}const d=/* @__PURE__ */ new Set([t.CONFIGURATION_REQUIRED]);function isPermanentRefusal(e){let t=schemaApiErrorCode(e);return t!==void 0&&d.has(t)}function isObjectNotFound(e){if(typeof e!=`object`||!e)return!1;let{code:n,status:r}=e;return n===t.OBJECT_NOT_FOUND||r===404}function isDraftRevisionConflict(e){return schemaApiErrorCode(e)===t.DRAFT_REVISION_CONFLICT}const f=new Set(e);function draftConflictChanges(e){if(!isDraftRevisionConflict(e))return[];let t=e.details?.changes;return Array.isArray(t)?t.filter(e=>typeof e==`object`&&!!e&&typeof e.key==`string`&&typeof e.label==`string`&&typeof e.seen==`string`&&f.has(e.kind)):[]}function isViewNotFound(e){return typeof e!=`object`||!e?!1:e.status===404}var StandardsRequestError=class extends Error{constructor(e,t,n,r){super(t),this.name=`StandardsRequestError`,this.status=e,this.code=n,this.details=r}},StandardsAuthError=class extends StandardsRequestError{constructor(e,t,n,r){super(e,t,n,r),this.name=`StandardsAuthError`}},BundleConflictError=class extends StandardsRequestError{constructor(e,t,n){super(e,t,n),this.name=`BundleConflictError`;let r=/"([^"]+)" is owned by (\S+)/.exec(t);this.objectName=r?.[1]??``,this.owner=r?.[2]??``}},BundleValidationError=class extends StandardsRequestError{constructor(e,t,n){super(e,t,n),this.name=`BundleValidationError`}},StandardsConfigurationError=class extends Error{constructor(e){super(e),this.name=`StandardsConfigurationError`}};const p=[1e3,2e3,5e3],m=/* @__PURE__ */ new Set([`turn.completed`,`turn.failed`,`turn.cancelled`]);function parseSseFrame(e){let t,n=`message`,r,i=[];for(let a of e.split(`
|
|
3
|
+
`)){let e=a.endsWith(`\r`)?a.slice(0,-1):a;if(e===``||e.startsWith(`:`))continue;let o=e.indexOf(`:`),s=o===-1?e:e.slice(0,o),c=o===-1?``:e.slice(o+1);c.startsWith(` `)&&(c=c.slice(1)),s===`id`?t=c:s===`event`?n=c:s===`data`?i.push(c):s===`retry`&&/^\d+$/.test(c)&&(r=Number(c))}return{id:t,event:n,data:i.join(`
|
|
4
|
+
`),retry:r}}function parseEvent(e){let t;try{t=JSON.parse(e.data)}catch{return}if(r(t)&&typeof t.type==`string`&&typeof t.seq==`number`&&Number.isSafeInteger(t.seq)&&t.seq>0&&(e.id===void 0||e.id===String(t.seq)))return t}function parseControl(e){let t;try{t=JSON.parse(e.data)}catch{return}if(!r(t))return;let n=t.control;return n===`up-to-date`||n===`lease-ended`||n===`inbox`?n:void 0}function isUnresolvableActor(e){return e.status===401&&e.code===`ACTOR_RESOLUTION_FAILED`}function isTerminalRefusal(e){return e.status===400||e.status===403||e.status===404||isUnresolvableActor(e)}function isCursorExpired(e){return e instanceof StandardsRequestError&&e.status===410&&e.code===`AGENT_SESSION_STREAM_CURSOR_EXPIRED`}function openAgentStream(e){let t=!1,n,r,i,a=1e3,o=0,s,c=e.subscribeAuthChanges?.(()=>{t||(o+=1,s?.(),s=void 0)});function endWait(){r!==void 0&&clearTimeout(r),r=void 0,i?.(),i=void 0}function close(){t||(t=!0,n?.abort(),endWait(),s?.(),s=void 0,c?.())}function waitForAuthChange(e){return t||o!==e?Promise.resolve():new Promise(e=>{s=e})}function sleep(e){return new Promise(t=>{i=t,r=setTimeout(endWait,e)})}function handleFrame(t){let n=parseSseFrame(t);if(n.retry!==void 0&&(a=n.retry),n.data===``)return`skipped`;if(n.event===`control`){let t=parseControl(n);return t&&e.onControl(t),t===`lease-ended`?`lease-ended`:`skipped`}if(n.event!==`event`)return`skipped`;let r=parseEvent(n);return r?r.seq<=e.cursor()?`skipped`:(e.onEvent(r),`delivered`):`malformed`}async function consume(e,n){let r=e.body;if(r===null)return{delivered:!1,end:`failed`};let i=r.getReader(),a=new TextDecoder,o=``,s=!1;try{for(;;){let{done:e,value:r}=await i.read();if(t||e)return{delivered:s,end:`clean`};o+=a.decode(r,{stream:!0}).replace(/\r\n/g,`
|
|
5
|
+
`);let c=o.indexOf(`
|
|
6
|
+
|
|
7
|
+
`);for(;c!==-1;){let e=o.slice(0,c);o=o.slice(c+2);let r=handleFrame(e);if(r===`delivered`&&(s=!0),t)return{delivered:s,end:`clean`};if(r===`malformed`)return n.abort(),{delivered:s,end:`malformed`};if(r===`lease-ended`)return{delivered:s,end:`lease-ended`};c=o.indexOf(`
|
|
8
|
+
|
|
9
|
+
`)}}}catch{return{delivered:s,end:`failed`}}finally{i.releaseLock()}}async function afterFailedOpen(t,n,r){if(isCursorExpired(t))try{return await e.onExpired(),r?`back-off`:`reopen`}catch{return`back-off`}return t instanceof StandardsRequestError?isTerminalRefusal(t)?(close(),e.onStatus(`error`,t),`stop`):t.status===401?(e.onStatus(`auth-blocked`,t),await waitForAuthChange(n),`reopen`):`back-off`:`back-off`}let l,u=0;async function rehydratedPastStall(t){if(e.cursor()!==t||(u=l===t?u+1:1,l=t,u<3))return!1;l=void 0,u=0;try{return await e.onExpired(),!0}catch{return!1}}function delayAfter(e,t){return e===`lease-ended`?0:e===`clean`||e===`malformed`?a:p[Math.min(t,p.length-1)]??5e3}async function run(){let r=!0,i=0,a=!1;for(;!t;){e.onStatus(r?`connecting`:`reconnecting`),r=!1;let s=new AbortController;n=s;let c=o,l=`failed`;try{let n=await e.open(e.sessionId,e.cursor(),s.signal,()=>{c=o});if(t)return;e.onStatus(`connected`);let r=e.cursor(),u=await consume(n,s);if(l=u.end,l===`malformed`&&await rehydratedPastStall(r)){if(t)return;continue}u.delivered&&(i=0,a=!1)}catch(e){if(t)return;let n=isCursorExpired(e),r=await afterFailedOpen(e,c,a);if(a=n,r===`stop`||t)return;if(r===`reopen`)continue}if(t)return;e.onStatus(`reconnecting`);let u=delayAfter(l,i);l===`failed`&&(i+=1),u>0&&await sleep(u)}}return run().catch(()=>void 0),{close,wake:endWait}}function parseContentDispositionFilename(e){if(!e)return;let t=e.match(/filename\*\s*=\s*(?:UTF-8|utf-8)''([^;]+)/i);if(t?.[1])try{return decodeURIComponent(t[1].trim())}catch{}let n=e.match(/filename\s*=\s*"([^"]*)"|filename\s*=\s*([^;]+)/i);return(n?.[1]??n?.[2])?.trim()||void 0}function recordsPath(e,...t){return[`/records`,...[e,...t].map(o)].join(`/`)}function resolveWithinBase(e,t){let r=e.endsWith(`/`)?e:`${e}/`,i=new URL(r),a=t.replace(/^\/+/,``),[o]=a.split(/[?#]/);if((o??``).split(`/`).some(e=>e===`..`||e===`.`))throw new n(`Request path "${t}" walks outside its own collection`,[]);let s=new URL(a,i);if(s.origin!==i.origin||!s.pathname.startsWith(i.pathname))throw new n(`Request path "${t}" resolves outside the API base "${i.pathname}"`,[]);return s}function readJson(e){return e.status===204||e.headers.get(`content-length`)===`0`?null:e.json()}async function readDownload(e){let t=await e.blob();return{blob:t,filename:parseContentDispositionFilename(e.headers.get(`Content-Disposition`)),mimeType:e.headers.get(`Content-Type`)??t.type}}function multipartBody(e,t){let n=new FormData;for(let[r,i]of Object.entries(t??{}))if(i!=null){if(r===e)for(let t of Array.isArray(i)?i:[i]){let r=t.name;typeof r==`string`?n.append(e,t,r):n.append(e,t)}else n.append(r,String(i))}return n}function headerRecord(e){return e===void 0?{}:e instanceof Headers?Object.fromEntries(e.entries()):Array.isArray(e)?Object.fromEntries(e):{...e}}function withoutContentType(e){return Object.fromEntries(Object.entries(e).filter(([e])=>e.toLowerCase()!==`content-type`))}function parseJsonObject(e){try{let t=JSON.parse(e);return typeof t==`object`&&t?t:{}}catch{return}}function refusalFrom(e,t,n){let r=parseJsonObject(t),i=r?.message??r?.error??r?.detail,a=i==null?n&&r===void 0&&t?t:`Request failed with status ${e}`:String(i),o=typeof r?.code==`string`?r.code:void 0;return new(e===401||e===403?StandardsAuthError:StandardsRequestError)(e,a,o,r?.details)}function refusalOf(e,t){return refusalFrom(e,t,!1)}async function readRefusal(e){return refusalOf(e.status,await e.text().catch(()=>``))}function isTimeout(e){return e instanceof DOMException&&e.name===`TimeoutError`}function trimSlashes(e,t){let n=0,r=e.length;for(;t&&n<r&&e[n]===`/`;)n+=1;for(;r>n&&e[r-1]===`/`;)--r;return e.slice(n,r)}function backoff(e){return new Promise(t=>setTimeout(t,1e3*2**e))}function abortReason(e){return e?.aborted?e.reason:new DOMException(`The operation was aborted.`,`AbortError`)}function canReportUploadProgress(e){return typeof XMLHttpRequest>`u`?!1:e.fetch===void 0||e.uploadAuthorization!==void 0}function sendWithProgress(e,t){let{signal:n}=e;return n?.aborted?Promise.reject(abortReason(n)):new Promise((r,i)=>{let a=new XMLHttpRequest;a.open(e.method,e.url);for(let[t,n]of Object.entries(e.headers))a.setRequestHeader(t,n);let o=Object.keys(e.headers).some(e=>e.toLowerCase()===`authorization`);e.token&&!o&&a.setRequestHeader(`Authorization`,`Bearer ${e.token}`),a.upload.addEventListener(`progress`,t=>{t.lengthComputable&&e.onUploadProgress({loaded:t.loaded,total:t.total})});let onAbort=()=>a.abort();n?.addEventListener(`abort`,onAbort,{once:!0});let settle=()=>n?.removeEventListener(`abort`,onAbort);a.addEventListener(`load`,()=>{if(settle(),a.status<200||a.status>=300)i(refusalOf(a.status,a.responseText));else try{r(t(a.responseText))}catch(e){i(e)}}),a.addEventListener(`error`,()=>{settle(),i(new StandardsRequestError(0,`Network request failed`))}),a.addEventListener(`abort`,()=>{settle(),i(abortReason(n))}),a.send(e.form)})}function createHttpTransport(e){let{baseUrl:t,onUnauthorized:n,getRetries:r=0}=e,i=e.timeoutMs??3e4,o=e.apiPrefix===void 0?void 0:trimSlashes(e.apiPrefix,!0),s=o?`${trimSlashes(t,!1)}/${o}`:t;function buildUrl(e,t){let n=resolveWithinBase(s,e);for(let[e,r]of Object.entries(t??{}))r!=null&&n.searchParams.set(e,String(r));return n.toString()}async function headersFor(t){let n={"Content-Type":`application/json`,...headerRecord(await e.headers?.()),...headerRecord(t.headers)};return t.body instanceof FormData?withoutContentType(n):n}function observe(t){try{e.onResponse?.(t)}catch{}}async function fetchOnce(t,n,r){let i=n.signal??void 0;i?.throwIfAborted();let a=r===null?void 0:AbortSignal.timeout(r),o=new AbortController,expire=()=>o.abort(a?.reason);a?.addEventListener(`abort`,expire,{once:!0});let s=i?AbortSignal.any([i,o.signal]):o.signal,c=new Promise((e,t)=>{s.addEventListener(`abort`,()=>t(s.reason),{once:!0})});try{let r=e.fetch??fetch,i=await headersFor(n);return await Promise.race([r(t,{...n,headers:i,signal:s}),c])}catch(e){throw i?.aborted?i.reason:e}finally{a?.removeEventListener(`abort`,expire)}}function connectionFailure(e){return e instanceof TypeError||isTimeout(e)?new StandardsRequestError(0,`Could not connect to ${t}`):e}async function refreshAndRetry(e,t,r){try{if(!await n?.())return;let i=await fetchOnce(e,t,r);return observe(i),i}catch{if(t.signal?.aborted)throw t.signal.reason;return}}async function readRefusalWithin(e){let t,n=new Promise(n=>{t=setTimeout(()=>n(refusalFrom(e.status,``,!1)),1500)});try{let t=e.text().catch(()=>``).then(t=>refusalFrom(e.status,t,!1));return await Promise.race([t,n])}finally{clearTimeout(t)}}async function send(e,t,a,o){let s=buildUrl(e,a.params),c=(t.method??`GET`).toUpperCase(),l=a.maxRetries??(c===`GET`?r:0),u=a.timeoutMs===void 0?i:a.timeoutMs;for(let e=0;;e++){let r=e<l,i;try{i=await fetchOnce(s,t,u)}catch(n){if(r&&n instanceof TypeError&&!t.signal?.aborted){await backoff(e);continue}throw connectionFailure(n)}if(observe(i),i.status>=500&&r){let t=await readRefusalWithin(i);if(isPermanentRefusal(t))throw t;await backoff(e)}else{if(i.status===401&&n&&(i=await refreshAndRetry(s,t,u)??i),!i.ok){let e=await i.text().catch(()=>``);throw refusalFrom(i.status,e,a.plainTextRefusal??!1)}return await o(i)}}}async function stream(t,r,i={}){let{path:a,query:o,body:s,headers:c}=u(t,r??{}),l=buildUrl(a,o),{signal:d,onRequest:f}=i,p=e.fetch??fetch,attempt=async()=>(f?.(),await p(l,{method:t.method,body:s===void 0?void 0:JSON.stringify(s),signal:d,headers:await headersFor({headers:{...c,...i.headers}})})),m=await attempt();if(m.status===401){let e=await readRefusal(m);if(e.code===`MFA_REQUIRED`||!n||!await n().catch(()=>!1))throw e;d?.throwIfAborted(),m=await attempt()}if(!m.ok)throw await readRefusal(m);return m}async function json(e,t,n){return await send(t,{method:e,body:n?JSON.stringify(n):void 0},{},readJson)}return{async call(t,n,r={}){if(t.response===`events`)return await stream(t,n,{signal:r.signal});let{path:i,query:o,body:s,headers:c}=u(t,n??{});if(t.upload!==void 0&&r.onUploadProgress&&canReportUploadProgress(e)){r.signal?.throwIfAborted();let n=await e.uploadAuthorization?.()??null;return await sendWithProgress({url:buildUrl(i,o),method:t.method,headers:withoutContentType({...headerRecord(await e.headers?.()),...c}),token:n,form:multipartBody(t.upload.field,s),onUploadProgress:r.onUploadProgress,signal:r.signal},e=>a(t,e?JSON.parse(e):null))}let l=t.upload===void 0?s===void 0?void 0:JSON.stringify(s):multipartBody(t.upload.field,s),d=t.response===`bytes`?readDownload:async e=>a(t,await readJson(e));return await send(i,{method:t.method,body:l,signal:r.signal,...c?{headers:c}:{},...r.keepalive?{keepalive:!0}:{}},{params:o,maxRetries:r.maxRetries,timeoutMs:r.timeoutMs},d)},stream,async get(e,t){return await send(e,{method:`GET`},{params:t},readJson)},post:(e,t)=>json(`POST`,e,t),patch:(e,t)=>json(`PATCH`,e,t),put:(e,t)=>json(`PUT`,e,t),delete:e=>json(`DELETE`,e),async getText(e,t){return await send(e,{method:`GET`},{params:t,plainTextRefusal:!0},e=>e.text())},async postRaw(e,t){return await send(e,{method:`POST`,body:JSON.stringify(t)},{plainTextRefusal:!0},e=>e)},async postMultipart(e,t,n={}){return await send(e,{method:`POST`,body:t},{timeoutMs:n.timeoutMs},readJson)}}}function createTransport(e){let{baseUrl:t,apiKey:n,tenantId:r,timeoutMs:i}=e,a={Authorization:`Bearer ${n}`,...r?{"X-Tenant-ID":r}:{}};return createHttpTransport({baseUrl:t,timeoutMs:i,headers:()=>a})}function asStrings(e){let t=Object.entries(e??{}).flatMap(([e,t])=>t==null?[]:[[e,String(t)]]);return Object.fromEntries(t)}async function uploadedPart(e){let t=e.name;return{name:typeof t==`string`?t:`blob`,mimeType:e.type===``?`application/octet-stream`:e.type,size:e.size,content:new Uint8Array(await e.arrayBuffer())}}async function wireRequest(e,t){let{query:n,body:r,headers:i}=u(e,t),a=Object.fromEntries(l(e.path).map(e=>[e,String(t[e])])),o=Object.fromEntries(Object.entries(i??{}).map(([e,t])=>[e.toLowerCase(),t])),s={params:a,query:asStrings(n),headers:o};if(e.upload===void 0)return{...s,body:r===void 0?void 0:JSON.parse(JSON.stringify(r))};let{[e.upload.field]:c,...d}=r??{},f=c==null?[]:Array.isArray(c)?c:[c];return{...s,body:asStrings(d),uploads:await Promise.all(f.map(uploadedPart))}}function downloaded(e){let t=typeof e.content==`string`?e.content:new Uint8Array(e.content);return{blob:new Blob([t],{type:e.mimeType}),filename:e.filename,mimeType:e.mimeType}}function createInProcessTransport(e){return transportActingAs(e,void 0)}function transportActingAs(e,t){async function call(n,r,i={}){if(i.signal?.throwIfAborted(),n.response===`events`)throw Error(`Operation ${n.name} streams over HTTP only`);let o=await wireRequest(n,r??{}),c;try{c=await e.execute(n,o,t)}catch(e){throw s(e)?refusalOf(e.status,JSON.stringify(e.body)):e}if(n.response===`bytes`)return downloaded(c);let l=c===void 0?null:JSON.parse(JSON.stringify(c));return a(n,l)}return{call,stream:e=>Promise.reject(/* @__PURE__ */ Error(`Operation ${e.name} streams over HTTP only`)),withCaller:t=>transportActingAs(e,t)}}function createAppClient(e){let t={},n=Object.values(i);for(let r of n.flatMap(e=>Object.values(e))){let n=c(r),i=r.name.slice(n.length+1);t[n]??={},t[n][i]=(t,n)=>r.response===`events`?e.stream(r,t,n):e.call(r,t,n)}return t}export{isDraftRevisionConflict as _,readRefusal as a,isViewNotFound as b,parseContentDispositionFilename as c,BundleConflictError as d,BundleValidationError as f,draftConflictChanges as g,StandardsRequestError as h,createTransport as i,m as l,StandardsConfigurationError as m,createInProcessTransport as n,refusalOf as o,StandardsAuthError as p,createHttpTransport as r,recordsPath as s,createAppClient as t,openAgentStream as u,isObjectNotFound as v,schemaApiErrorCode as x,isPermanentRefusal as y};
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
|
|
2
|
+
import { AgentSessionEvent, AgentStreamControlFrame, DraftConflictChange } from "@standards/schema";
|
|
3
|
+
import { Operation, OperationCaller, OperationHost, OperationInput, OperationResult, appOperationGroups } from "@standards/schema/api";
|
|
4
|
+
/**
|
|
5
|
+
* Any non-2xx answer from a Standards API. `code` is the server's `SchemaErrorCode` when it sent
|
|
6
|
+
* one; `details` is the body's `details` field, kept as the server sent it.
|
|
7
|
+
*/
|
|
8
|
+
declare class StandardsRequestError extends Error {
|
|
9
|
+
readonly status: number;
|
|
10
|
+
readonly code?: string;
|
|
11
|
+
readonly details?: unknown;
|
|
12
|
+
constructor(status: number, message: string, code?: string, details?: unknown);
|
|
13
|
+
}
|
|
14
|
+
/** 401 or 403: the key is missing, invalid, or lacks the permission the route requires. */
|
|
15
|
+
declare class StandardsAuthError extends StandardsRequestError {
|
|
16
|
+
constructor(status: number, message: string, code?: string, details?: unknown);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* 409 from `PUT /bundles/:name`: a name this bundle declares is owned by core or another bundle.
|
|
20
|
+
* A declared view that clashes with the workspace's views (a second default for the same object
|
|
21
|
+
* and context, or a name held by a system view) is a 409 too; its message names no owner, so
|
|
22
|
+
* `objectName` and `owner` are empty.
|
|
23
|
+
*/
|
|
24
|
+
declare class BundleConflictError extends StandardsRequestError {
|
|
25
|
+
/** The object or `object:view` name that clashed. */
|
|
26
|
+
readonly objectName: string;
|
|
27
|
+
/** `core` or `bundle:<name>`. */
|
|
28
|
+
readonly owner: string;
|
|
29
|
+
constructor(status: number, message: string, code: string | undefined);
|
|
30
|
+
}
|
|
31
|
+
/** 400 from `PUT /bundles/:name`: bad name, oversize payload, hash mismatch, invalid definition, or an unresolved migration. */
|
|
32
|
+
declare class BundleValidationError extends StandardsRequestError {
|
|
33
|
+
constructor(status: number, message: string, code: string | undefined);
|
|
34
|
+
}
|
|
35
|
+
/** The client was constructed in a way it refuses to run (e.g. an API key in a browser). */
|
|
36
|
+
declare class StandardsConfigurationError extends Error {
|
|
37
|
+
constructor(message: string);
|
|
38
|
+
}
|
|
39
|
+
/** Per-request overrides a multipart upload may carry. */
|
|
40
|
+
interface MultipartRequestOptions {
|
|
41
|
+
/** This request's timeout in ms, instead of the client's `timeoutMs`. */
|
|
42
|
+
timeoutMs?: number;
|
|
43
|
+
}
|
|
44
|
+
interface HttpTransportConfig {
|
|
45
|
+
baseUrl: string;
|
|
46
|
+
/** A path joined between `baseUrl` and every request path. */
|
|
47
|
+
apiPrefix?: string;
|
|
48
|
+
fetch?: typeof fetch;
|
|
49
|
+
/** Read before every attempt, so a refreshed token reaches the retry. */
|
|
50
|
+
headers?: () => HeadersInit | Promise<HeadersInit>;
|
|
51
|
+
/** Asked on a 401; `true` means the credentials were refreshed and the request is sent once more. */
|
|
52
|
+
onUnauthorized?: () => Promise<boolean>;
|
|
53
|
+
/** Sees every response — success, refusal, and the retry after a refresh. Read-only: the body belongs to the request. */
|
|
54
|
+
onResponse?: (response: Response) => void;
|
|
55
|
+
/** Per attempt, in ms. Defaults to 30 000. */
|
|
56
|
+
timeoutMs?: number;
|
|
57
|
+
/** Extra attempts after the first for a GET (5xx and network failures). Defaults to 0. */
|
|
58
|
+
getRetries?: number;
|
|
59
|
+
/**
|
|
60
|
+
* The bearer an upload sent over XMLHttpRequest carries (to report its
|
|
61
|
+
* progress): XHR cannot run an injected `fetch`, where an app's auth lives,
|
|
62
|
+
* so with an injected `fetch` and no `uploadAuthorization` an upload goes
|
|
63
|
+
* through `fetch` and reports no progress.
|
|
64
|
+
*/
|
|
65
|
+
uploadAuthorization?: () => Promise<string | null>;
|
|
66
|
+
}
|
|
67
|
+
/** Bytes of a multipart body sent so far, out of its total. */
|
|
68
|
+
interface UploadProgress {
|
|
69
|
+
loaded: number;
|
|
70
|
+
total: number;
|
|
71
|
+
}
|
|
72
|
+
/** Per-call options of one operation. */
|
|
73
|
+
interface OperationCallOptions {
|
|
74
|
+
/** Aborts the call: it rejects with the signal's reason (an `AbortError` by default). */
|
|
75
|
+
signal?: AbortSignal;
|
|
76
|
+
/** Extra attempts after the first; defaults to `getRetries` for a GET and 0 otherwise. */
|
|
77
|
+
maxRetries?: number;
|
|
78
|
+
/**
|
|
79
|
+
* This call's wait for the response headers, in ms, instead of the client's
|
|
80
|
+
* `timeoutMs`; `null` waits as long as it takes (an upload's body is sent
|
|
81
|
+
* before the headers come back, so a large one outlives any fixed deadline).
|
|
82
|
+
*/
|
|
83
|
+
timeoutMs?: number | null;
|
|
84
|
+
/**
|
|
85
|
+
* Lets the request outlive the page that sent it (`fetch`'s `keepalive`),
|
|
86
|
+
* on every attempt: for a write taken right before a navigation, which the
|
|
87
|
+
* browser would otherwise cancel in flight.
|
|
88
|
+
*/
|
|
89
|
+
keepalive?: boolean;
|
|
90
|
+
/**
|
|
91
|
+
* The bytes of an `upload` operation's body sent so far. `fetch` cannot
|
|
92
|
+
* report them, so the upload goes over XMLHttpRequest — one attempt, no
|
|
93
|
+
* deadline, no refresh on a 401 — when the transport can authenticate it
|
|
94
|
+
* there (see `uploadAuthorization`); otherwise it goes through `fetch` and
|
|
95
|
+
* reports nothing.
|
|
96
|
+
*/
|
|
97
|
+
onUploadProgress?: (progress: UploadProgress) => void;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Per-call options of an `"events"` operation. No deadline and no retry: a
|
|
101
|
+
* stream outlives any request timeout, so its signal is the only abort.
|
|
102
|
+
*/
|
|
103
|
+
interface OperationStreamOptions {
|
|
104
|
+
signal?: AbortSignal;
|
|
105
|
+
/** Merged over the configured headers (`Accept: text/event-stream`). */
|
|
106
|
+
headers?: Record<string, string>;
|
|
107
|
+
/**
|
|
108
|
+
* Observes each HTTP attempt, the one after a 401 refresh included, so a
|
|
109
|
+
* reader can tell which credential a refusal answered.
|
|
110
|
+
*/
|
|
111
|
+
onRequest?: () => void;
|
|
112
|
+
}
|
|
113
|
+
interface HttpTransport {
|
|
114
|
+
/**
|
|
115
|
+
* Sends one operation: path parameters fill the path; the rest is the query
|
|
116
|
+
* for a GET, otherwise the body, except the keys the operation lists in `query`.
|
|
117
|
+
* An `upload` operation sends its body as multipart, its files under the
|
|
118
|
+
* operation's field; a `response: "bytes"` one resolves to a `DownloadedFile`.
|
|
119
|
+
*/
|
|
120
|
+
call<O extends Operation>(op: O, input: OperationInput<O>, options?: OperationCallOptions): Promise<OperationResult<O>>;
|
|
121
|
+
/**
|
|
122
|
+
* Opens an `"events"` operation and resolves to its `Response` once the
|
|
123
|
+
* headers are in, for the caller to read: no deadline, no retry, one
|
|
124
|
+
* refresh on a 401 (never on `MFA_REQUIRED`, which a token cannot satisfy).
|
|
125
|
+
* Any refusal is read and thrown as the typed error before a byte streams.
|
|
126
|
+
*/
|
|
127
|
+
stream<O extends Operation>(op: O, input: OperationInput<O>, options?: OperationStreamOptions): Promise<Response>;
|
|
128
|
+
get<T = unknown>(path: string, params?: Record<string, unknown>): Promise<T>;
|
|
129
|
+
post<T = unknown>(path: string, body?: unknown): Promise<T>;
|
|
130
|
+
patch<T = unknown>(path: string, body?: unknown): Promise<T>;
|
|
131
|
+
put<T = unknown>(path: string, body?: unknown): Promise<T>;
|
|
132
|
+
delete<T = unknown>(path: string): Promise<T>;
|
|
133
|
+
getText(path: string, params?: Record<string, unknown>): Promise<string>;
|
|
134
|
+
/**
|
|
135
|
+
* POST that hands back the unread `Response` so a caller can stream a large
|
|
136
|
+
* body (the CSV export). A refusal is read here and thrown as the typed error.
|
|
137
|
+
*/
|
|
138
|
+
postRaw(path: string, body: unknown): Promise<Response>;
|
|
139
|
+
postMultipart<T>(path: string, form: FormData, options?: MultipartRequestOptions): Promise<T>;
|
|
140
|
+
}
|
|
141
|
+
/** The verbs the records, files and schema layers use; `createTransport` returns their superset. */
|
|
142
|
+
/** What `createAppClient` calls: every operation, and a stream for an `"events"` one. */
|
|
143
|
+
type OperationTransport = Pick<HttpTransport, "call" | "stream">;
|
|
144
|
+
type Transport = Pick<HttpTransport, "call" | "get" | "post" | "patch" | "put" | "delete" | "getText" | "postRaw" | "postMultipart">;
|
|
145
|
+
interface TransportConfig {
|
|
146
|
+
baseUrl: string;
|
|
147
|
+
apiKey: string;
|
|
148
|
+
tenantId?: string;
|
|
149
|
+
timeoutMs?: number;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* A refusal read from its status and body text, for a response that is not a
|
|
153
|
+
* `Response` (an XMLHttpRequest upload): the same error the transport throws.
|
|
154
|
+
*/
|
|
155
|
+
declare function refusalOf(status: number, text: string): StandardsRequestError;
|
|
156
|
+
/** Reads a refused `Response` into the error the transport itself throws. */
|
|
157
|
+
declare function readRefusal(response: Response): Promise<StandardsRequestError>;
|
|
158
|
+
declare function createHttpTransport(config: HttpTransportConfig): HttpTransport;
|
|
159
|
+
/**
|
|
160
|
+
* The API-key transport the public SDK documents: `createHttpTransport` with
|
|
161
|
+
* the bearer key and tenant header, one attempt, no refresh.
|
|
162
|
+
*/
|
|
163
|
+
declare function createTransport(config: TransportConfig): HttpTransport;
|
|
164
|
+
/** The server's `SchemaErrorCode` on a failed call, when it sent one. */
|
|
165
|
+
declare function schemaApiErrorCode(error: unknown): string | undefined;
|
|
166
|
+
/** Whether a failure is an answer, and so must not be asked again. */
|
|
167
|
+
declare function isPermanentRefusal(error: unknown): boolean;
|
|
168
|
+
/**
|
|
169
|
+
* Whether a failure says the object does not exist, rather than that the read
|
|
170
|
+
* failed (#3290): with a definition seeded from the cached catalogue, a 500 and
|
|
171
|
+
* a 404 are opposite answers — a transient failure may be ridden out, an
|
|
172
|
+
* authoritative not-found may not.
|
|
173
|
+
*
|
|
174
|
+
* Either signal is enough, deliberately: reading only the code would tolerate a
|
|
175
|
+
* deleted object behind a plainer not-found, reading only the status would miss
|
|
176
|
+
* a coded refusal carrying no status.
|
|
177
|
+
*/
|
|
178
|
+
declare function isObjectNotFound(error: unknown): boolean;
|
|
179
|
+
/**
|
|
180
|
+
* Whether a write was refused because the draft moved since it was read
|
|
181
|
+
* (`DRAFT_REVISION_CONFLICT`, a 409): only a fresh read of the draft makes the
|
|
182
|
+
* next attempt mean something (#4899).
|
|
183
|
+
*/
|
|
184
|
+
declare function isDraftRevisionConflict(error: unknown): boolean;
|
|
185
|
+
/**
|
|
186
|
+
* What a publish refused for a conflict found published on its targets since
|
|
187
|
+
* the draft captured them (#5936). Empty for any other refusal, a conflict on
|
|
188
|
+
* the draft's own revision included: that one is answered by reading it again.
|
|
189
|
+
*/
|
|
190
|
+
declare function draftConflictChanges(error: unknown): DraftConflictChange[];
|
|
191
|
+
/**
|
|
192
|
+
* Whether a view read failed because the object simply has no view for that
|
|
193
|
+
* context (#2659) — a working object not laid out yet, not a failure.
|
|
194
|
+
*
|
|
195
|
+
* Status-only: the view routes' not-found carries the generic
|
|
196
|
+
* `SCHEMA_RECORD_NOT_FOUND` code, which says nothing view-specific. Call it
|
|
197
|
+
* ONLY on a view query's error — on any other query a 404 means something
|
|
198
|
+
* else entirely.
|
|
199
|
+
*/
|
|
200
|
+
declare function isViewNotFound(error: unknown): boolean;
|
|
201
|
+
type AgentStreamStatus = "connecting" | "connected" | "reconnecting" | "error" | "auth-blocked";
|
|
202
|
+
type AgentStreamHandle = {
|
|
203
|
+
close(): void;
|
|
204
|
+
/** Ends a pending reconnect delay now (the tab came back, the network returned). */
|
|
205
|
+
wake(): void;
|
|
206
|
+
};
|
|
207
|
+
type AgentStreamControl = AgentStreamControlFrame["control"];
|
|
208
|
+
type OpenAgentStreamOptions = {
|
|
209
|
+
/**
|
|
210
|
+
* Opens the HTTP stream after `cursor` — the client method from agent-api.
|
|
211
|
+
* The transport (auth headers, 401 refresh) lives here; this loop owns only
|
|
212
|
+
* the parser and the reconnect policy.
|
|
213
|
+
*/
|
|
214
|
+
open(sessionId: string, cursor: number, signal: AbortSignal, onRequest?: () => void): Promise<Response>;
|
|
215
|
+
sessionId: string;
|
|
216
|
+
/** The cursor every (re)connection opens after: the last seq the caller holds. */
|
|
217
|
+
cursor(): number;
|
|
218
|
+
/** One event, in seq order; the caller advances its cursor before returning. */
|
|
219
|
+
onEvent(event: AgentSessionEvent): void;
|
|
220
|
+
onControl(control: AgentStreamControl): void;
|
|
221
|
+
onStatus(status: AgentStreamStatus, error?: StandardsRequestError): void;
|
|
222
|
+
/**
|
|
223
|
+
* The server no longer holds the events after the cursor (410
|
|
224
|
+
* `AGENT_SESSION_STREAM_CURSOR_EXPIRED`): rehydrate, which moves the cursor
|
|
225
|
+
* to the history's `committedSeq`, then the loop reopens there.
|
|
226
|
+
*/
|
|
227
|
+
onExpired(): Promise<void>;
|
|
228
|
+
/** Changed credentials only; independent of Presence authorization. */
|
|
229
|
+
subscribeAuthChanges?(listener: () => void): () => void;
|
|
230
|
+
};
|
|
231
|
+
/** The event types that end a turn. */
|
|
232
|
+
declare const TURN_END_TYPES: ReadonlySet<AgentSessionEvent["type"]>;
|
|
233
|
+
/**
|
|
234
|
+
* Read the session's durable event stream (spec §9.4) and keep it open.
|
|
235
|
+
*
|
|
236
|
+
* Fetch-based on purpose: `EventSource` cannot see the 410's code. Every
|
|
237
|
+
* connection opens after `cursor()`, so a reconnect — a 60 s lease ending, a
|
|
238
|
+
* network error — resumes exactly where the caller is, and an event at or
|
|
239
|
+
* below the cursor is never delivered twice. A 410 rehydrates once
|
|
240
|
+
* (`onExpired`), then reopens at the new cursor; 400/403/404 and an
|
|
241
|
+
* unresolvable actor are terminal; a 401 waits for a credential change.
|
|
242
|
+
*/
|
|
243
|
+
declare function openAgentStream(options: OpenAgentStreamOptions): AgentStreamHandle;
|
|
244
|
+
/**
|
|
245
|
+
* Parse the download filename out of a `Content-Disposition` response header.
|
|
246
|
+
*
|
|
247
|
+
* The server is the single naming source (see `contentDispositionFilename` in
|
|
248
|
+
* adapter-nestjs): it emits both the RFC 5987 `filename*=UTF-8''...` form
|
|
249
|
+
* (accent-safe, percent-encoded) and a sanitized ASCII `filename="..."`
|
|
250
|
+
* fallback. We prefer the extended form and percent-decode it so accented,
|
|
251
|
+
* title-based names ("Pièce d'identité – 2.jpg") survive the round trip.
|
|
252
|
+
*
|
|
253
|
+
* Returns `undefined` when the header is absent or carries no filename, letting
|
|
254
|
+
* callers fall back to a client-side name.
|
|
255
|
+
*/
|
|
256
|
+
declare function parseContentDispositionFilename(header: string | null | undefined): string | undefined;
|
|
257
|
+
/**
|
|
258
|
+
* The in-process transport: an {@link OperationTransport} that can also be
|
|
259
|
+
* bound to who acts, which a transport over HTTP cannot (its identity is the
|
|
260
|
+
* API key's).
|
|
261
|
+
*/
|
|
262
|
+
interface InProcessTransport extends OperationTransport {
|
|
263
|
+
/** The same transport, every call acting as `caller`. */
|
|
264
|
+
withCaller(caller: OperationCaller): InProcessTransport;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* A transport over operations run in this process (the runtime's
|
|
268
|
+
* `createOperationHost`), for a server that embeds Standards: the same
|
|
269
|
+
* `createAppClient` API, inputs, answers and errors as over HTTP, without a
|
|
270
|
+
* socket. Each call acts as the actor the ambient context implies (the
|
|
271
|
+
* request's, the job's, the system where none runs), or as the one
|
|
272
|
+
* `withCaller` names, and each operation's permissions are checked as the
|
|
273
|
+
* HTTP API checks them. A refusal rejects with the `StandardsRequestError`
|
|
274
|
+
* (`StandardsAuthError` for 401/403) the HTTP transport would throw.
|
|
275
|
+
*
|
|
276
|
+
* Streams (`"events"` operations) are served over HTTP only.
|
|
277
|
+
*/
|
|
278
|
+
declare function createInProcessTransport(host: OperationHost): InProcessTransport;
|
|
279
|
+
type AppOperationGroups = typeof appOperationGroups;
|
|
280
|
+
type AppOperation = { [K in keyof AppOperationGroups]: AppOperationGroups[K][keyof AppOperationGroups[K]]; }[keyof AppOperationGroups];
|
|
281
|
+
type NamespaceOf<N> = N extends `${infer G}.${string}` ? G : never;
|
|
282
|
+
type VerbOf<N> = N extends `${string}.${infer V}` ? V : never;
|
|
283
|
+
/** An `"events"` operation opens a stream (`transport.stream`); any other is one call. */
|
|
284
|
+
type OptionsOf<O extends Operation> = O extends {
|
|
285
|
+
readonly response: "events";
|
|
286
|
+
} ? OperationStreamOptions : OperationCallOptions;
|
|
287
|
+
/** An input the schema defaults (`.default({})`) may be left out; `options` carries the call's signal. */
|
|
288
|
+
type OperationCall<O extends Operation> = (...args: undefined extends OperationInput<O> ? [input?: OperationInput<O>, options?: OptionsOf<O>] : [input: OperationInput<O>, options?: OptionsOf<O>]) => Promise<OperationResult<O>>;
|
|
289
|
+
type AppClient = { readonly [G in NamespaceOf<AppOperation["name"]>]: { readonly [O in AppOperation as NamespaceOf<O["name"]> extends G ? VerbOf<O["name"]> : never]: OperationCall<O>; }; };
|
|
290
|
+
/** The namespaced client over every app operation: `client.apiKeys.revoke({ id })`. */
|
|
291
|
+
declare function createAppClient(transport: OperationTransport): AppClient;
|
|
292
|
+
export { refusalOf as A, OperationTransport as C, createHttpTransport as D, UploadProgress as E, StandardsRequestError as F, BundleValidationError as M, StandardsAuthError as N, createTransport as O, StandardsConfigurationError as P, OperationStreamOptions as S, TransportConfig as T, schemaApiErrorCode as _, parseContentDispositionFilename as a, MultipartRequestOptions as b, AgentStreamStatus as c, openAgentStream as d, draftConflictChanges as f, isViewNotFound as g, isPermanentRefusal as h, createInProcessTransport as i, BundleConflictError as j, readRefusal as k, OpenAgentStreamOptions as l, isObjectNotFound as m, createAppClient as n, AgentStreamControl as o, isDraftRevisionConflict as p, InProcessTransport as r, AgentStreamHandle as s, AppClient as t, TURN_END_TYPES as u, HttpTransport as v, Transport as w, OperationCallOptions as x, HttpTransportConfig as y };
|