@timeback/sdk 0.2.4-beta.20260422095241 → 0.2.4

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/index.js CHANGED
@@ -1 +1 @@
1
- import"./chunk-ae6bkfs5.js";import{a as E,b as O$,c as D$}from"./chunk-nrn5gjey.js";import{e as N$,f as I$,g as b$,h as h$,i as S$,j as E$,k as xJ}from"./chunk-qpzke7wy.js";import{l as Y1}from"./server/adapters/native.js";import{m as d,n as F2,o as O2,p as _2,q as o2,r as h2,s as DJ}from"./chunk-k1awna2q.js";import{t as FJ,u as R,v as L2,w as P$,y as T$,z as R$}from"./chunk-b49f5qfw.js";import"./chunk-3pf3cpfk.js";import{G as f8,H as L$,I as S2,J as u,K as OJ,L as P,M,N as $8,Q as W1}from"./chunk-dbcsf5tk.js";import{R as M8,U as j8}from"./chunk-1s709w5e.js";import{TimebackClient as H1}from"@timeback/core";import{getServiceUrlsForEnv as T0}from"@timeback/core";class s extends Error{statusCode;response;name="ApiError";constructor($,J,Z){super($);this.statusCode=J,this.response=Z}get minorCodes(){let $=this.response;if(!$?.imsx_CodeMinor?.imsx_codeMinorField)return[];return $.imsx_CodeMinor.imsx_codeMinorField.map((J)=>({field:J.imsx_codeMinorFieldName,value:J.imsx_codeMinorFieldValue}))}get details(){return this.response?.imsx_error_details??[]}}class $9 extends s{name="UnauthorizedError";constructor($="Unauthorized",J){super($,401,J)}}class J9 extends s{name="ForbiddenError";constructor($="Forbidden",J){super($,403,J)}}class Z9 extends s{name="NotFoundError";constructor($="Not Found",J){super($,404,J)}}class H9 extends s{name="ValidationError";constructor($="Validation Error",J){super($,422,J)}}class K9 extends s{name="InputValidationError";issues;constructor($,J){let Z={imsx_codeMajor:"failure",imsx_severity:"error",imsx_description:$,imsx_error_details:J.map((H)=>({path:H.path,message:H.message}))};super($,400,Z);this.issues=J}}function N2($,J){return new K9($,J)}function MJ($){if(!($ instanceof Error))return!1;return"statusCode"in $&&"response"in $}var jJ="BEYOND_AI",X9="LEARNWITH_AI",W9=jJ,LJ={staging:"https://staging-beyond-timeback-api-2-idp.auth.us-east-1.amazoncognito.com/oauth2/token",production:"https://prod-beyond-timeback-api-2-idp.auth.us-east-1.amazoncognito.com/oauth2/token"},VJ={staging:"https://api.staging.alpha-1edtech.ai",production:"https://api.alpha-1edtech.ai"},kJ={staging:"https://caliper.staging.alpha-1edtech.ai",production:"https://caliper.alpha-1edtech.ai"},qJ={staging:"https://qti.alpha-1edtech.ai/api",production:"https://qti.alpha-1edtech.ai/api"},CJ={staging:"https://platform.dev.timeback.com/auth/1.0/token",production:"https://platform.timeback.com/auth/1.0/token"},AJ={staging:"https://platform.dev.timeback.com",production:"https://platform.timeback.com"},zJ={staging:"https://platform.dev.timeback.com",production:"https://platform.timeback.com"},PJ={staging:"https://platform.dev.timeback.com",production:"https://platform.timeback.com"},TJ={BEYOND_AI:{token:LJ,tokenScope:void 0,api:VJ,caliper:kJ,qti:qJ},LEARNWITH_AI:{token:CJ,tokenScope:"https://purl.imsglobal.org/spec/caliper/v1p2/scope/events.write",api:AJ,caliper:zJ,qti:PJ}},RJ={tsc:"tsc",nativePreview:"@typescript/native-preview"},_1={package:RJ.nativePreview,bin:"tsgo"},e=null,L8=!1,V8=!1;function Y9(){try{let $=process.env.DEBUG?.trim();if(!$)return!1;return $.split(",").some((J)=>J.trim().length>0)}catch{return!1}}function s8($){let Z=$.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${Z}$`)}function NJ(){if(e!==null)return;if(e=[],!Y9()){V8=!1;return}V8=!0;let $=process.env.DEBUG.trim();if($==="1"||$==="true"||$==="*"){L8=!0;return}let J=$.split(",").map((H)=>H.trim()).filter(Boolean);for(let H of J)if(H.startsWith("-"))e.push({regex:s8(H.slice(1)),exclude:!0});else e.push({regex:s8(H),exclude:!1});if(!e.some((H)=>!H.exclude)&&e.length>0)L8=!0}function IJ($){if(NJ(),!V8)return!0;if(L8){if($){for(let J of e)if(J.exclude&&J.regex.test($))return!1}return!0}if(!$)return!1;for(let J of e)if(J.exclude&&J.regex.test($))return!1;for(let J of e)if(!J.exclude&&J.regex.test($))return!0;return!1}function Q9(){return typeof globalThis<"u"&&"window"in globalThis}function bJ(){if(Q9())return"browser";if(typeof process<"u"&&process.env){if(process.env.CI||process.env.GITHUB_ACTIONS||process.env.GITLAB_CI||process.env.CIRCLECI||process.env.JENKINS_URL||process.env.BUILDKITE)return"ci"}return"terminal"}var k8;if(!Q9())try{k8=(await import("./chunk-kkajswjx.js")).inspect}catch{}var $2={reset:"\x1B[0m",bold:"\x1B[1m",dim:"\x1B[2m",red:"\x1B[31m",yellow:"\x1B[33m",blue:"\x1B[34m",cyan:"\x1B[36m"};function hJ($){switch($){case"debug":return $2.blue;case"info":return $2.cyan;case"warn":return $2.yellow;case"error":return $2.red}}function SJ($){switch($){case"debug":return console.debug;case"info":return console.info;case"warn":return console.warn;case"error":return console.error}}function EJ($){if(k8)return k8($,{depth:null,colors:!0,breakLength:80,compact:!1});return JSON.stringify($,null,2)}var vJ=($)=>{let J=hJ($.level),Z=SJ($.level),H=$.level.toUpperCase().padEnd(5),K=$.timestamp.toISOString().replace(/\.\d{3}Z$/,""),W=`${$2.dim}[${K}]${$2.reset}`,_=`${J}${H}${$2.reset}`,F=$.scope?`${$2.bold}[${$.scope}]${$2.reset} `:"",O=`${W} ${_} ${F}${$.message}`;if($.context&&Object.keys($.context).length>0)Z(O,EJ($.context));else Z(O)},yJ={debug:"[DEBUG]",info:"[INFO]",warn:"[WARN]",error:"[ERROR]"};function fJ($){return Object.entries($).map(([J,Z])=>`${J}=${gJ(Z)}`).join(" ")}function gJ($){if(typeof $==="string")return $;if(typeof $==="number")return String($);if(typeof $==="boolean")return String($);if($===null)return"null";if($===void 0)return"undefined";return JSON.stringify($)}var dJ=($)=>{let J=[];if(J.push($.timestamp.toISOString()),J.push(yJ[$.level]),$.scope)J.push(`[${$.scope}]`);if(J.push($.message),$.context&&Object.keys($.context).length>0)J.push(fJ($.context));console.log(J.join(" "))},mJ=($)=>{let J={timestamp:$.timestamp.toISOString(),level:$.level,...$.scope&&{scope:$.scope},msg:$.message};if($.context&&Object.keys($.context).length>0)Object.assign(J,$.context);console.log(JSON.stringify(J))},lJ={debug:"color: gray",info:"color: #0ea5e9",warn:"color: #f59e0b",error:"color: #ef4444; font-weight: bold"},uJ={debug:"log",info:"info",warn:"warn",error:"error"},cJ=($)=>{let J=uJ[$.level],Z=lJ[$.level],K=`%c${$.scope?`[${$.scope}]`:""} ${$.message}`;if($.context&&Object.keys($.context).length>0)console[J](K,Z,$.context);else console[J](K,Z)},o8=["debug","info","warn","error"],n8=Symbol.for("@timeback/internal-logger/config");function pJ(){try{return process.env.TIMEBACK_INTERNAL_LOGGER==="silent"}catch{return!1}}function aJ(){let $=globalThis;return $[n8]??={},$[n8]}function iJ($){switch($){case"terminal":return vJ;case"ci":return dJ;case"production":return mJ;case"browser":return cJ;case"test":return()=>{}}}function sJ(){if(Y9())return"debug";return"info"}function oJ($,J){return J??aJ().formatter??(pJ()?()=>{}:iJ($))}function nJ($,J){return o8.indexOf($)>=o8.indexOf(J)}class g2{scope;minLevel;environment;explicitFormatter;defaultContext;constructor($={}){this.scope=$.scope,this.minLevel=$.minLevel??sJ(),this.defaultContext=$.defaultContext??{},this.environment=$.environment??bJ(),this.explicitFormatter=$.formatter}child($){let J=this.scope?`${this.scope}:${$}`:$;return new g2({scope:J,minLevel:this.minLevel,environment:this.environment,defaultContext:{...this.defaultContext},formatter:this.explicitFormatter})}withContext($){return new g2({scope:this.scope,minLevel:this.minLevel,environment:this.environment,defaultContext:{...this.defaultContext,...$},formatter:this.explicitFormatter})}debug($,J){this.log("debug",$,J)}info($,J){this.log("info",$,J)}warn($,J){this.log("warn",$,J)}error($,J){this.log("error",$,J)}log($,J,Z){if($==="debug"&&!IJ(this.scope))return;if(!nJ($,this.minLevel))return;let H={level:$,message:J,scope:this.scope,context:Z||Object.keys(this.defaultContext).length>0?{...this.defaultContext,...Z}:void 0,timestamp:new Date};oJ(this.environment,this.explicitFormatter)(H)}}function G9($={}){return new g2($)}function rJ(){try{let $=typeof process>"u"?void 0:process.env.DEBUG;return $==="1"||$==="true"}catch{return!1}}class d2{config;accessToken=null;tokenExpiry=0;pendingRequest=null;fetchFn;log;constructor($){this.config=$,this.fetchFn=$.fetch??globalThis.fetch.bind(globalThis),this.log=$.logger??G9({scope:"auth",minLevel:rJ()?"debug":"warn"})}async getToken(){if(this.accessToken&&Date.now()<this.tokenExpiry)return this.log.debug("Using cached token"),this.accessToken;if(this.pendingRequest)return this.log.debug("Waiting for in-flight token request"),this.pendingRequest;this.pendingRequest=this.fetchToken();try{return await this.pendingRequest}finally{this.pendingRequest=null}}async fetchToken(){this.log.debug("Fetching new access token...");let{clientId:$,clientSecret:J}=this.config.credentials,Z=btoa(`${$}:${J}`),H=performance.now(),K=await this.fetchFn(this.config.tokenUrl,{method:"POST",headers:{Authorization:`Basic ${Z}`,"Content-Type":"application/x-www-form-urlencoded"},body:this.config.scope?`grant_type=client_credentials&scope=${encodeURIComponent(this.config.scope)}`:"grant_type=client_credentials"}),W=Math.round(performance.now()-H);if(!K.ok)throw this.log.error(`Token request failed: ${K.status} ${K.statusText}`),Error(`Failed to obtain access token: ${K.status} ${K.statusText}`);let _=await K.json();return this.accessToken=_.access_token,this.tokenExpiry=Date.now()+(_.expires_in-60)*1000,this.log.debug(`Token acquired (${W}ms, expires in ${_.expires_in}s)`),this.accessToken}invalidate(){this.log.debug("Token invalidated"),this.accessToken=null,this.tokenExpiry=0}}var m2={caliper:{send:"/caliper/event",validate:"/caliper/event/validate",list:"/caliper/events",get:"/caliper/events/{id}",jobStatus:"/jobs/{id}/status"},oneroster:{rostering:"/ims/oneroster/rostering/v1p2",gradebook:"/ims/oneroster/gradebook/v1p2",resources:"/ims/oneroster/resources/v1p2"},edubridge:{base:"/edubridge"},powerpath:{base:"/powerpath"},clr:{credentials:"/ims/clr/v2p0/credentials",discovery:"/ims/clr/v2p0/discovery"},case:{base:"/ims/case/v1p1"},webhooks:{webhookList:"/webhooks/",webhookGet:"/webhooks/{id}",webhookCreate:"/webhooks/",webhookUpdate:"/webhooks/{id}",webhookDelete:"/webhooks/{id}",webhookActivate:"/webhooks/{id}/activate",webhookDeactivate:"/webhooks/{id}/deactivate",webhookFilterList:"/webhook-filters/",webhookFilterGet:"/webhook-filters/{id}",webhookFilterCreate:"/webhook-filters/",webhookFilterUpdate:"/webhook-filters/{id}",webhookFilterDelete:"/webhook-filters/{id}",webhookFiltersByWebhook:"/webhook-filters/webhook/{webhookId}"},reporting:{mcp:"/mcp/reporting",savedQueryExecute:"/reporting/saved-queries/{id}",adminGroupCheck:"/mcp/admin/users/{email}/group",adminGroupAdd:"/mcp/admin/users/{email}/group",adminGroupRemove:"/mcp/admin/users/{email}/group"}},tJ={caliper:{send:"/caliper/v1p2",validate:null,list:null,get:null,jobStatus:null},oneroster:{rostering:"/rostering/1.0",gradebook:"/gradebook/1.0",resources:"/resources/1.0"},webhooks:null,reporting:null,edubridge:null,powerpath:null,clr:null,case:{base:"/case/1.1"}},B9={BEYOND_AI:m2,LEARNWITH_AI:tJ};function eJ($){return"env"in $&&!("baseUrl"in $)&&!("services"in $)}function $5($){return"baseUrl"in $&&!("services"in $)}function J5($){return"services"in $}function r8($,J){let Z=$?B9[$]??m2:m2;return{caliper:J?.caliper??Z.caliper,oneroster:J?.oneroster??Z.oneroster,webhooks:J?.webhooks??Z.webhooks,reporting:J?.reporting??Z.reporting,edubridge:J?.edubridge??Z.edubridge,powerpath:J?.powerpath??Z.powerpath,clr:J?.clr??Z.clr,case:J?.case??Z.case}}class I2{platform;env;auth;timeout;_endpoints;_authUrl;_tokenScope;_pathProfiles;_tokenManagers=new Map;constructor($){if(this.timeout=$.timeout??30000,eJ($)){this.auth=$.auth;let J=$.platform??W9,Z=$.env;this.platform=J,this.env=Z;let H=TJ[J];if(!H)throw Error(`Unknown platform: ${J}`);this._authUrl=H.token[Z],this._tokenScope=H.tokenScope??void 0,this._pathProfiles=B9[J]??m2,this._endpoints={oneroster:{baseUrl:H.api[Z],authUrl:this._authUrl},edubridge:{baseUrl:H.api[Z],authUrl:this._authUrl},powerpath:{baseUrl:H.api[Z],authUrl:this._authUrl},clr:{baseUrl:H.api[Z],authUrl:this._authUrl},case:{baseUrl:H.api[Z],authUrl:this._authUrl},caliper:{baseUrl:H.caliper[Z],authUrl:this._authUrl},webhooks:{baseUrl:H.caliper[Z],authUrl:this._authUrl},reporting:{baseUrl:H.api[Z],authUrl:this._authUrl},qti:{baseUrl:H.qti[Z],authUrl:this._authUrl}}}else if($5($))this.auth=$.auth,this._authUrl=$.authUrl,this._pathProfiles=r8($.pathProfile,$.paths),this._endpoints={oneroster:{baseUrl:$.baseUrl,authUrl:this._authUrl},edubridge:{baseUrl:$.baseUrl,authUrl:this._authUrl},powerpath:{baseUrl:$.baseUrl,authUrl:this._authUrl},clr:{baseUrl:$.baseUrl,authUrl:this._authUrl},case:{baseUrl:$.baseUrl,authUrl:this._authUrl},caliper:{baseUrl:$.baseUrl,authUrl:this._authUrl},webhooks:{baseUrl:$.baseUrl,authUrl:this._authUrl},reporting:{baseUrl:$.baseUrl,authUrl:this._authUrl},qti:{baseUrl:$.baseUrl,authUrl:this._authUrl}};else if(J5($)){this.auth=$.auth,this._authUrl=$.authUrl,this._pathProfiles=r8($.pathProfile,$.paths),this._endpoints={};for(let[J,Z]of Object.entries($.services))if(Z)this._endpoints[J]={baseUrl:Z,authUrl:this._authUrl}}else throw Error("Invalid provider configuration");for(let J of Object.keys(this._pathProfiles))if(this._pathProfiles[J]===null)delete this._endpoints[J]}getEndpoint($){let J=this._endpoints[$];if(!J){let Z=$;if(Z in this._pathProfiles&&this._pathProfiles[Z]===null)throw Error(`Service "${$}" is not supported on ${this.platform??"this"} platform.`);throw Error(`Service "${$}" is not configured in this provider`)}return J}hasService($){return $ in this._endpoints}getAvailableServices(){return Object.keys(this._endpoints)}getTokenUrl(){return this._authUrl}getEndpointWithPaths($){let J=this.getEndpoint($),Z=this.getServicePaths($);return{...J,paths:Z}}getPaths(){return this._pathProfiles}getServicePaths($){let J=this._pathProfiles[$];if(!J)throw Error(`Service "${$}" is not supported on ${this.platform??"this"} platform.`);return J}hasServiceSupport($){return this._pathProfiles[$]!==null}getTokenProvider($){let J=this.getEndpoint($),{authUrl:Z}=J;if(!Z)return;if(!this.auth)throw Error(`Service "${$}" requires authentication but no credentials were provided`);let H=this._tokenManagers.get(Z);if(!H)H=new d2({tokenUrl:Z,credentials:{clientId:this.auth.clientId,clientSecret:this.auth.clientSecret},scope:this._tokenScope}),this._tokenManagers.set(Z,H);return H}async checkAuth(){if(!this._authUrl||!this.auth)throw Error("No auth configured on this provider");let $=Date.now(),J=this._tokenManagers.get(this._authUrl);if(!J)J=new d2({tokenUrl:this._authUrl,credentials:{clientId:this.auth.clientId,clientSecret:this.auth.clientSecret},scope:this._tokenScope}),this._tokenManagers.set(this._authUrl,J);try{return await J.getToken(),{ok:!0,latencyMs:Date.now()-$,checks:{tokenAcquisition:!0}}}catch(Z){return{ok:!1,latencyMs:Date.now()-$,error:Z instanceof Error?Z.message:String(Z),checks:{tokenAcquisition:!1}}}}invalidateTokens(){for(let $ of this._tokenManagers.values())$.invalidate?.();this._tokenManagers.clear()}}function b($){try{if(typeof process>"u")return;if(typeof $==="string")return process.env[$];for(let J of $){let Z=process.env[J];if(Z!==void 0)return Z}return}catch{return}}function D2(){let $=b("DEBUG");return $==="1"||$==="true"}function Z5(){return Math.random().toString(16).slice(2,10)}function q8($){return G9({scope:$,minLevel:D2()?"debug":"warn"})}var l2={defaultPlatform:W9,templates:{BEYOND_AI:{staging:{platform:"BEYOND_AI",env:"staging"},production:{platform:"BEYOND_AI",env:"production"}},LEARNWITH_AI:{staging:{platform:"LEARNWITH_AI",env:"staging"},production:{platform:"LEARNWITH_AI",env:"production"}}}};function H5($){if(typeof $==="string")return $;if($.length===0)throw Error(`Missing env var key: ${$}`);return $[0]}function w2($){return H5($)}function _9($){if($!=="staging"&&$!=="production")throw Error(`Invalid env "${$}": must be "staging" or "production"`);return $}function F9($,J){let Z=$?.clientId??b(J.clientId),H=$?.clientSecret??b(J.clientSecret);if(!Z)throw Error(`Missing clientId: provide in config or set ${w2(J.clientId)}`);if(!H)throw Error(`Missing clientSecret: provide in config or set ${w2(J.clientSecret)}`);return{clientId:Z,clientSecret:H}}function K5($,J,Z){if(!Z)return;return F9($,J)}function X5($){let J=b($.baseUrl),Z=b($.authUrl),H=b($.clientId),K=b($.clientSecret);if(J===void 0&&H===void 0)return`Missing env: provide in config or set ${w2($.env??$.baseUrl)}`;let W=[];if(J===void 0)W.push(w2($.env??$.baseUrl));if(J!==void 0&&Z===void 0)W.push(w2($.authUrl));if(H===void 0)W.push(w2($.clientId));if(K===void 0)W.push(w2($.clientSecret));return`Missing environment variables: ${W.join(", ")}`}var W5={name:"transport",matches($){return"transport"in $&&!!$.transport},resolve($){return{mode:"transport",transport:$.transport}}},Y5={name:"provider",matches($){return"provider"in $&&!!$.provider},resolve($){return{mode:"provider",provider:$.provider}}},Q5={name:"env-config",matches($){return"env"in $},resolve($,J,Z){let H=$,K=_9(H.env),W=F9(H.auth,J),_=H.platform??Z.defaultPlatform,F=Z.templates[_];if(!F){let x=Object.keys(Z.templates).join(", ");throw Error(`Unknown platform "${_}": available platforms are ${x}`)}let O=F[K];if(!O){let x=Object.keys(F).join(", ");throw Error(`Unknown env "${K}" for platform "${_}": available environments are ${x}`)}return{mode:"provider",provider:new I2({platform:O.platform,env:O.env,auth:W,timeout:H.timeout})}}},G5={name:"explicit-config",matches($){return"baseUrl"in $},resolve($,J){let Z=$,H=Z.authUrl??Z.auth?.authUrl,K=!!H,W=K5(Z.auth,J,K);return{mode:"provider",provider:new I2({baseUrl:Z.baseUrl,authUrl:H,auth:W,timeout:Z.timeout,pathProfile:Z.pathProfile,paths:Z.paths})}}},B5={name:"env-fallback-platform",matches($,J){if(Object.keys($).length>0)return!1;let Z=J.env?b(J.env):void 0,H=b(J.clientId),K=b(J.clientSecret);return Z!==void 0&&H!==void 0&&K!==void 0},resolve($,J,Z){let H=_9(b(J.env)),K=b(J.clientId),W=b(J.clientSecret),_=Z.defaultPlatform,F=Z.templates[_]?.[H];if(!F)throw Error(`Unknown env "${H}" for platform "${_}"`);return{mode:"provider",provider:new I2({platform:F.platform,env:F.env,auth:{clientId:K,clientSecret:W}})}}},_5={name:"env-fallback-explicit",matches($,J){if(Object.keys($).length>0)return!1;let Z=b(J.baseUrl),H=b(J.authUrl),K=b(J.clientId),W=b(J.clientSecret);return Z!==void 0&&H!==void 0&&K!==void 0&&W!==void 0},resolve($,J){let Z=b(J.baseUrl),H=b(J.authUrl),K=b(J.clientId),W=b(J.clientSecret);return{mode:"provider",provider:new I2({baseUrl:Z,authUrl:H,auth:{clientId:K,clientSecret:W}})}}},F5={name:"token-provider",matches($){return"tokenProvider"in $},resolve(){throw Error("TokenProvider mode is not supported with provider pattern. Use { provider: TimebackProvider } or { env, auth } instead.")}},O5=[W5,Y5,Q5,F5,G5,B5,_5];function O9($,J,Z=l2){for(let H of O5)if(H.matches($,J))return H.resolve($,J,Z);throw Error(X5(J))}var U8=3,D5=[429,503],t8=1000;class C8{config;log;constructor($){let{config:J,logger:Z}=$,H=J.fetch??globalThis.fetch.bind(globalThis),K;if("tokenProvider"in J&&J.tokenProvider)K=J.tokenProvider;else if("auth"in J&&J.auth)K=new d2({tokenUrl:J.auth.authUrl,credentials:{clientId:J.auth.clientId,clientSecret:J.auth.clientSecret},fetch:H});let W=J.baseUrl.endsWith("/")?J.baseUrl:`${J.baseUrl}/`;this.config={baseUrl:W,timeout:J.timeout??30000,fetch:H,tokenProvider:K},this.log=Z.child("http")}get baseUrl(){return this.config.baseUrl}async request($,J={}){let Z=await this.requestRaw($,J);return this.handleResponse(Z)}async exists($,J={}){try{return await this.requestRaw($,J),!0}catch(Z){if(MJ(Z)&&Z.statusCode===404)return!1;throw Z}}async requestRaw($,J={}){let{method:Z="GET",params:H,body:K,headers:W={}}=J,_=this.buildUrl($,H),F=J.requestId??Z5(),x=Date.now()+this.config.timeout;for(let V=0;V<U8;V++){let A=x-Date.now();if(A<=0)throw this.log.error("Request timeout before attempt",D2()?{requestId:F,path:$}:{path:$}),new s("Request timeout",408);let C=await this.getAccessToken(),q=V===U8-1,z=performance.now();this.log.debug(`→ ${Z} ${_}`,{requestId:F,attempt:V>0?V+1:void 0});let N={"Content-Type":"application/json",Accept:"application/json","X-Request-ID":F,...W};if(C)N.Authorization=`Bearer ${C}`;let I=await this.config.fetch(_,{method:Z,headers:N,body:K?JSON.stringify(K):void 0,signal:AbortSignal.timeout(Math.min(A,this.config.timeout))}),r=Math.round(performance.now()-z);if(this.log.debug(`← ${I.status} ${I.statusText} (${r}ms)`,{requestId:F}),D5.includes(I.status)&&!q){let v2=I.headers.get("Retry-After"),p=this.parseRetryAfter(v2,V),i8=x-Date.now();if(p>=i8)throw this.log.error("Request timeout during retry backoff",D2()?{requestId:F,path:$}:{path:$}),new s("Request timeout",408);this.log.warn(`Retrying in ${p}ms (attempt ${V+1}/${U8})`,{...D2()&&{requestId:F},status:I.status}),await this.sleep(p);continue}if(!I.ok)return this.handleErrorResponse(I,F);return I}throw this.log.error("Max retries exceeded",D2()?{requestId:F,path:$}:{path:$}),new s("Max retries exceeded")}getAccessToken(){if(!this.config.tokenProvider)return Promise.resolve(void 0);return this.config.tokenProvider.getToken()}buildUrl($,J){if(/^[a-z][a-z0-9+.-]*:/i.test($))throw Error(`Absolute URLs are not allowed in path: ${$}. Use relative paths only.`);let Z=$.startsWith("/")?$.slice(1):$,H=new URL(Z,this.config.baseUrl);if(J){for(let[K,W]of Object.entries(J))if(W!==void 0)H.searchParams.set(K,String(W))}return H.toString()}async handleResponse($){if(!$.ok)await this.handleErrorResponse($);if($.status===204)return;if($.headers.get("content-length")==="0")return;return this.parseJsonResponse($)}async parseJsonResponse($){let J=await $.text();if(!J||J.trim()==="")return;try{return JSON.parse(J)}catch(Z){let H=J.length>200?J.slice(0,200)+"...":J,K=Z instanceof Error?Z.message:String(Z),W=$.url||"unknown";throw this.log.error("Failed to parse JSON response",{url:W,status:$.status,contentType:$.headers.get("content-type"),bodyPreview:H,error:K}),new s(`Invalid JSON response from ${W}`,$.status,{parseError:K,body:H})}}async handleErrorResponse($,J){let Z,H=await $.text().catch(()=>"");if(H)try{Z=JSON.parse(H)}catch(W){let _=W instanceof Error?W.message:"Unknown parse error";Z={rawBody:H.slice(0,500),parseError:_},this.log.warn("Failed to parse error response as JSON",{...D2()&&{requestId:J},url:$.url,status:$.status,parseError:_,bodyPreview:H.slice(0,200)})}let K=this.extractErrorMessage(Z,$.statusText);if($.status!==404)this.log.error(`Request failed: ${$.status} ${K}`,D2()?{requestId:J}:void 0);switch($.status){case 401:throw this.config.tokenProvider?.invalidate?.(),new $9(K,Z);case 403:throw new J9(K,Z);case 404:throw new Z9(K,Z);case 422:throw new H9(K,Z);default:throw new s(K,$.status,Z)}}extractErrorMessage($,J){if(typeof $==="object"&&$!==null){let Z=$;if(typeof Z.message==="string")return Z.message;if(typeof Z.error==="string")return Z.error;if(typeof Z.imsx_description==="string")return Z.imsx_description}return J}sleep($){return new Promise((J)=>{setTimeout(J,$)})}parseRetryAfter($,J){if(!$)return t8*Math.pow(2,J);let Z=parseInt($,10);if(!isNaN(Z))return Z*1000;let H=Date.parse($);if(!isNaN(H)){let K=H-Date.now();return Math.max(0,K)}return t8*Math.pow(2,J)}}function w5($){if($ instanceof Date)return $.toISOString();if(typeof $==="boolean")return $?"true":"false";if(typeof $==="number")return String($);return $.replaceAll("'","''")}function t($){let J=w5($);return typeof $==="string"||$ instanceof Date?`'${J}'`:J}function x5($,J){if(typeof J==="string"||typeof J==="number"||typeof J==="boolean"||J instanceof Date)return[`${$}=${t(J)}`];if(typeof J==="object"&&J!==null){let Z=J,H=[];if(Z.ne!==void 0)H.push(`${$}!=${t(Z.ne)}`);if(Z.gt!==void 0)H.push(`${$}>${t(Z.gt)}`);if(Z.gte!==void 0)H.push(`${$}>=${t(Z.gte)}`);if(Z.lt!==void 0)H.push(`${$}<${t(Z.lt)}`);if(Z.lte!==void 0)H.push(`${$}<=${t(Z.lte)}`);if(Z.contains!==void 0)H.push(`${$}~${t(Z.contains)}`);if(Z.in!==void 0&&Z.in.length>0){let K=Z.in.map((_)=>`${$}=${t(_)}`),W=K.join(" OR ");H.push(K.length>1?`(${W})`:W)}if(Z.notIn!==void 0&&Z.notIn.length>0){let K=Z.notIn.map((W)=>`${$}!=${t(W)}`);H.push(K.join(" AND "))}return H}return[]}function U5($){return"OR"in $&&Array.isArray($.OR)}function D9($){if(U5($)){let Z=$.OR.map((H)=>D9(H)).filter((H)=>H!==void 0);return Z.length>0?Z.join(" OR "):void 0}let J=[];for(let[Z,H]of Object.entries($))if(H!==void 0)J.push(...x5(Z,H));return J.length>0?J.join(" AND "):void 0}var e8=100,M5=1e4;class A8{fetcher;path;params;max;unwrapKey;log;transform;paginationStyle;constructor($){this.fetcher=$.fetcher,this.path=$.path,this.params=$.params??{},this.max=$.max,this.unwrapKey=$.unwrapKey,this.log=$.logger?.child("pagination")??q8("pagination"),this.transform=$.transform,this.paginationStyle=$.paginationStyle??"offset"}buildRequestParams($,J){let{where:Z,fields:H,offset:K,limit:W,..._}=this.params,F={..._,filter:Z?D9(Z):void 0,fields:H?.join(","),limit:$};if(this.paginationStyle==="page"){let O=Math.floor(J/$)+1;return{...F,page:O}}return{...F,offset:J}}extractItems($,J){let Z;if(this.unwrapKey)Z=$[this.unwrapKey]??[];else Z=$;return this.validateItems(Z,J)}validateItems($,J){if($===null||$===void 0)return this.log.warn(`Page ${J}: response data is ${$}, treating as empty`),[];if(!Array.isArray($))throw Error(`Expected array for page ${J}, got ${typeof $}. `+(this.unwrapKey?`Check unwrapKey '${this.unwrapKey}' is correct.`:""));return $}hasMorePages($,J,Z,H){if(J===0)return!1;let K=$.hasMore,W=$.total!==void 0&&Z+J<$.total;return K||W||J===H&&$.total===void 0}async*[Symbol.asyncIterator](){let $=this.params.offset??0,J=this.params.limit??e8,Z=!0,H=1,K=0;while(Z){this.log.debug(`Fetching page ${H} (offset: ${$}, limit: ${J})`);let W=await this.fetcher(this.path,{params:this.buildRequestParams(J,$)}),_=this.extractItems(W.data,H);this.log.debug(`Page ${H}: ${_.length} items`);for(let F of _)if(yield this.transform?this.transform(F):F,K++,this.max!==void 0&&K>=this.max){this.log.debug(`Pagination complete: reached max of ${this.max} items`);return}Z=this.hasMorePages(W,_.length,$,J),$+=_.length,H++}this.log.debug(`Pagination complete: ${K} total items`)}async toArray($={}){let J=$.maxItems??M5,Z=[];for await(let H of this){if(Z.length>=J)throw Error(`toArray() exceeded maxItems limit of ${J}. Use 'for await...of' to stream large datasets, or increase maxItems.`);Z.push(H)}return Z}async firstPage(){let $=this.params.limit??e8,J=this.params.offset??0,Z=await this.fetcher(this.path,{params:this.buildRequestParams($,J)}),H=this.extractItems(Z.data,1),K=this.transform?H.map(this.transform):H,W=this.hasMorePages(Z,K.length,J,$);return this.log.debug(`First page: ${K.length} items, total: ${Z.total}, hasMore: ${W}`),{data:K,hasMore:W,total:Z.total,nextOffset:W?J+K.length:void 0}}}function f2($,J){return{path:$,message:J}}function o($,J,Z){let H=$.safeParse(J);if(H.success)return H.data;let K=H.error.issues.map((W)=>({path:W.path.join(".")||"(root)",message:W.message}));throw N2(`Invalid ${Z} data`,K)}function u2($,J){if(typeof $!=="string"||$.trim()==="")throw N2(`Invalid ${J}`,[f2(J,"Must be a non-empty string")])}function z8($){if(!$)return;let J=[];if($.limit!==void 0){if(!Number.isInteger($.limit)||$.limit<=0)J.push(f2("limit","Must be a positive integer"))}if($.offset!==void 0){if(!Number.isInteger($.offset)||$.offset<0)J.push(f2("offset","Must be a non-negative integer"))}if($.max!==void 0){if(!Number.isInteger($.max)||$.max<=0)J.push(f2("max","Must be a positive integer"))}if(J.length>0)throw N2("Invalid list parameters",J)}var w9={baseUrl:["TIMEBACK_API_BASE_URL","TIMEBACK_BASE_URL","CALIPER_BASE_URL"],authUrl:["TIMEBACK_API_AUTH_URL","TIMEBACK_AUTH_URL","CALIPER_TOKEN_URL"],clientId:["TIMEBACK_API_CLIENT_ID","TIMEBACK_CLIENT_ID","CALIPER_CLIENT_ID"],clientSecret:["TIMEBACK_API_CLIENT_SECRET","TIMEBACK_CLIENT_SECRET","CALIPER_CLIENT_SECRET"]},k2="http://purl.imsglobal.org/ctx/caliper/v1p2",x9="QUESTION_RESULT";import{z as j}from"zod/v4";import{z as Y}from"zod/v4";import{z as Z2}from"zod/v4";import{z as U}from"zod/v4";import{z as w}from"zod/v4";import{z as k}from"zod/v4";import{z as D}from"zod/v4";import{z as g}from"zod/v4";import{z as Q}from"zod/v4";import{z as B}from"zod/v4";import{z as G}from"zod/v4";import{z as A2}from"zod/v4";var S=q8("caliper");class q9 extends C8{paths;constructor($){super({config:$,logger:S});this.paths=$.paths}async requestPaginated($,J={}){let Z=await this.request($,J),{events:H,pagination:K}=Z,_=(J.params?.offset??0)+H.length<K.total;return{data:H,hasMore:_,total:K.total}}}class C9 extends A8{constructor($,J,Z={}){z8(Z);let{max:H,...K}=Z;super({fetcher:(W,_)=>$.requestPaginated(W,_),path:J,params:K,max:H,logger:S})}}function P8($){let J=$.id??`urn:uuid:${crypto.randomUUID()}`,Z=$.metricsId??`urn:uuid:${crypto.randomUUID()}`;return{"@context":k2,id:J,type:"ActivityEvent",action:"Completed",actor:$.actor,object:$.object,eventTime:$.eventTime??new Date().toISOString(),profile:"TimebackProfile",generated:{id:Z,type:"TimebackActivityMetricsCollection",items:$.metrics,...$.attempt===void 0?{}:{attempt:$.attempt},...$.generatedExtensions?{extensions:$.generatedExtensions}:{}},extensions:$.extensions,...$.edApp===void 0?{}:{edApp:$.edApp},...$.session===void 0?{}:{session:$.session}}}function T8($){let J=$.id??`urn:uuid:${crypto.randomUUID()}`,Z=$.metricsId??`urn:uuid:${crypto.randomUUID()}`;return{"@context":k2,id:J,type:"TimeSpentEvent",action:"SpentTime",actor:$.actor,object:$.object,eventTime:$.eventTime??new Date().toISOString(),profile:"TimebackProfile",generated:{id:Z,type:"TimebackTimeSpentMetricsCollection",items:$.metrics},extensions:$.extensions,...$.edApp===void 0?{}:{edApp:$.edApp},...$.session===void 0?{}:{session:$.session}}}function j5($){return{"@context":k2,id:$.id??`urn:uuid:${crypto.randomUUID()}`,type:"AssessmentItemEvent",action:"Started",profile:"AssessmentProfile",actor:$.actor,object:{...$.object,type:"AssessmentItem"},eventTime:$.eventTime??new Date().toISOString(),edApp:$.edApp,...$.session===void 0?{}:{session:$.session},...$.extensions===void 0?{}:{extensions:$.extensions}}}function L5($){return{"@context":k2,id:$.id??`urn:uuid:${crypto.randomUUID()}`,type:"AssessmentItemEvent",action:"Completed",profile:"AssessmentProfile",actor:$.actor,object:{...$.object,type:"AssessmentItem"},eventTime:$.eventTime??new Date().toISOString(),edApp:$.edApp,...$.generated===void 0?{}:{generated:{...$.generated,type:"Response"}},...$.session===void 0?{}:{session:$.session},...$.extensions===void 0?{}:{extensions:$.extensions}}}function V5($){let{id:J,...Z}=$.generated;return{"@context":k2,id:$.id??`urn:uuid:${crypto.randomUUID()}`,type:"GradeEvent",action:"Graded",profile:"GradingProfile",actor:$.actor,object:$.object,eventTime:$.eventTime??new Date().toISOString(),edApp:$.edApp,generated:{...Z,id:J??`urn:uuid:${crypto.randomUUID()}`,type:"Score",scoreType:x9},...$.session===void 0?{}:{session:$.session},...$.extensions===void 0?{}:{extensions:$.extensions}}}var k5="http://purl.imsglobal.org/ctx/caliper/v1p2",q5="urn:tag:auto-attach",Q2={PERSON:"Person",ASSIGNABLE_DIGITAL_RESOURCE:"AssignableDigitalResource",ACTIVITY_METRIC:"ActivityMetric",TIME_SPENT_METRIC:"TimeSpentMetric",ACTIVITY_METRICS_COLLECTION:"ActivityMetricsCollection",TIME_SPENT_METRICS_COLLECTION:"TimeSpentMetricsCollection",COURSE_OFFERING:"CourseOffering",SOFTWARE_APPLICATION:"SoftwareApplication"},C5=new Set(["ActivityEvent","TimeSpentEvent","AssignableEvent","ViewEvent"]);class A9{transformEnvelope($){let{data:J}=$;if(!Array.isArray(J))return $;let Z=J.map((H)=>x2(H)?A5(H):H);return{...$,data:Z}}}function A5($){let J={...$};if(!("@context"in J))J["@context"]=k5;if(J.profile==="TimebackProfile")J.profile="AggregationProfile";if(x2(J.actor)&&J.actor.type==="TimebackUser")J.actor=z5(J.actor);if(x2(J.object))J.object=P5(J.object,J.type);if(x2(J.generated)){let Z=J.type;if(Z==="ActivityEvent")J.generated=T5(J.generated);else if(Z==="TimeSpentEvent")J.generated=R5(J.generated)}if(!J.session)J.session=q5;return J}function z5($){return{type:Q2.PERSON,id:$.id}}function P5($,J){if(!($.type==="TimebackActivityContext"&&J!==void 0&&C5.has(J)))return{...$};let H={type:Q2.ASSIGNABLE_DIGITAL_RESOURCE,id:$.id};if($.name)H.name=$.name;if(x2($.course)){let K={type:Q2.COURSE_OFFERING,id:$.course.id};if($.course.name)K.name=$.course.name;H.isPartOf=K}if(x2($.app))H.extensions={app:{name:$.app.name,type:$.app.type??Q2.SOFTWARE_APPLICATION}};return H}function z9($,J,Z,H){let W={id:typeof $?.id==="string"?$.id:`urn:uuid:${crypto.randomUUID()}`,type:J};if(Array.isArray($.items))W.items=$.items.map((_)=>{if(!x2(_))return _;let F=typeof _.type==="string"?_.type:"",O=F?F[0].toUpperCase()+F.slice(1):H;return{id:`urn:uuid:${crypto.randomUUID()}`,type:Z,metricType:O,metricValue:_.value}});for(let[_,F]of Object.entries($))if(_!=="id"&&_!=="type"&&_!=="items")W[_]=F;return W}function T5($){return z9($,Q2.ACTIVITY_METRICS_COLLECTION,Q2.ACTIVITY_METRIC,"")}function R5($){return z9($,Q2.TIME_SPENT_METRICS_COLLECTION,Q2.TIME_SPENT_METRIC,"Active")}function x2($){return typeof $==="object"&&$!==null&&!Array.isArray($)}function N5($,J=l2){return O9($,w9,J)}var I5=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/,y=j.string().min(1).regex(I5,"must be a valid ISO 8601 datetime"),C2=j.string().min(1).regex(/^\d{4}-\d{2}-\d{2}$/,"must be a valid ISO 8601 date (YYYY-MM-DD)"),X=j.string().trim().min(1),X2=j.enum(["Reading","Language","Vocabulary","Social Studies","Writing","Science","FastMath","Math","None","Other"]).meta({id:"TimebackSubject",description:"Subject area"}),b5=j.union([j.literal(-1),j.literal(0),j.literal(1),j.literal(2),j.literal(3),j.literal(4),j.literal(5),j.literal(6),j.literal(7),j.literal(8),j.literal(9),j.literal(10),j.literal(11),j.literal(12),j.literal(13)]),h5=j.string().transform(($,J)=>{let Z=$.toLowerCase().trim().replaceAll("_"," ");if(Z==="")return J.addIssue({code:"custom",message:"must be a valid Timeback grade"}),j.NEVER;let H=Z.replace(/\bgrade\b/g,"").replace(/(\d+)(st|nd|rd|th)\b/g,"$1").trim();if(H==="")return J.addIssue({code:"custom",message:"must be a valid Timeback grade"}),j.NEVER;if(H==="pre-k"||H==="pk")return-1;if(H==="k")return 0;if(H==="middle school")return 7;let W=H.replace(/\s+/g,"").replace(/^0+/,"")||"0",_=Number(W);if(!Number.isInteger(_))return J.addIssue({code:"custom",message:"must be a valid Timeback grade"}),j.NEVER;return _}),n=j.union([j.number(),h5]).pipe(b5).meta({id:"TimebackGrade",description:"Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"}),S5=j.enum(["exempt","fully graded","not submitted","partially graded","submitted"]),E5=j.enum(["department","school","district","local","state","national"]),P9=j.enum(["administrator","aide","guardian","parent","proctor","relative","student","teacher"]),v5=j.enum(["administrator","proctor","student","teacher"]),y5=j.enum(["qti","text","audio","video","interactive","visual","course-material","assessment-bank"]),f5=j.enum(["qti-test","qti-question","qti-stimulus","qti-test-bank"]),g5=j.enum(["unit","course","resource-collection"]),d5=j.enum(["choice","order","associate","match","hotspot","hottext","select-point","graphic-order","graphic-associate","graphic-gap-match","text-entry","extended-text","inline-choice","upload","slider","drawing","media","custom"]),m5=j.enum(["easy","medium","hard"]),T9=j.array(j.object({source:j.string(),learningObjectiveIds:j.array(j.string())})),R9=j.object({consecutive_failures:j.number().int().min(1).optional(),stagnation_limit:j.number().int().min(1).optional()}).optional(),l5=j.enum(["powerpath-100","quiz","test-out","placement","unit-test","alpha-read-article"]).nullable(),R1=j.object({imsx_codeMajor:j.enum(["failure","success"]),imsx_severity:j.enum(["error","warning","status"]),imsx_description:j.string(),imsx_CodeMinor:j.object({imsx_codeMinorField:j.array(j.object({imsx_codeMinorFieldName:j.string(),imsx_codeMinorFieldValue:j.string()}))}).optional()}),u5=Y.union([Y.url(),Y.string().regex(/^urn:/,"Must be a URL or URN")]),U2=Y.object({id:Y.url(),type:Y.literal("TimebackUser"),email:Y.string()}),R8=Y.object({id:Y.url(),type:Y.literal("TimebackActivityContext"),subject:X2,app:Y.object({name:Y.string()}),activity:Y.object({id:Y.url().optional(),name:Y.string()}).strict().optional(),course:Y.object({id:Y.url().optional(),name:Y.string().optional()}).strict(),process:Y.boolean().optional()}),N9=Y.object({"@context":Y.literal("http://purl.imsglobal.org/ctx/caliper/v1p2"),id:Y.string().regex(/^urn:uuid:/,"Event id must start with urn:uuid:"),type:Y.string(),eventTime:y,profile:Y.literal("TimebackProfile"),actor:U2,action:Y.string(),object:R8,edApp:Y.object({id:Y.string(),name:Y.string().optional()}).optional()}),I9=Y.object({type:Y.enum(["totalQuestions","correctQuestions","xpEarned","masteredUnits"]),value:Y.number()}),c5=Y.object({id:Y.url(),type:Y.literal("TimebackActivityMetricsCollection"),attempt:Y.number().optional(),items:Y.array(I9),extensions:Y.record(Y.string(),Y.unknown()).optional()}),p5=N9.extend({type:Y.literal("ActivityEvent"),action:Y.literal("Completed"),generated:c5}),b9=Y.object({type:Y.enum(["active","inactive","waste","unknown","anti-pattern"]),value:Y.number(),subType:Y.string().optional()}),a5=Y.object({id:Y.url(),type:Y.literal("TimebackTimeSpentMetricsCollection"),items:Y.array(b9)}),i5=N9.extend({type:Y.literal("TimeSpentEvent"),action:Y.literal("SpentTime"),generated:a5}),s5=Y.object({actor:U2,object:R8,metrics:Y.array(I9).min(1,"metrics must contain at least one metric"),eventTime:y.optional(),metricsId:Y.string().optional(),id:Y.string().optional(),extensions:Y.record(Y.string(),Y.unknown()).optional(),edApp:Y.union([Y.string(),Y.record(Y.string(),Y.unknown())]).optional(),session:Y.union([Y.string(),Y.record(Y.string(),Y.unknown())]).optional(),attempt:Y.number().int().min(1).optional(),generatedExtensions:Y.object({pctCompleteApp:Y.number().optional()}).loose().optional()}).strict(),o5=Y.object({actor:U2,object:R8,metrics:Y.array(b9).min(1,"metrics must contain at least one metric"),eventTime:y.optional(),metricsId:Y.string().optional(),id:Y.string().optional(),extensions:Y.record(Y.string(),Y.unknown()).optional(),edApp:Y.union([Y.string(),Y.record(Y.string(),Y.unknown())]).optional(),session:Y.union([Y.string(),Y.record(Y.string(),Y.unknown())]).optional()}).strict(),n5=Y.union([p5,i5]),N1=Y.object({sensor:Y.string(),sendTime:y,dataVersion:Y.literal("http://purl.imsglobal.org/ctx/caliper/v1p2"),data:Y.array(n5)}),r5=Y.enum(["AnnotationProfile","AssessmentProfile","ToolUseProfile","GeneralProfile","FeedbackProfile","MediaProfile","SurveyProfile","ResourceManagementProfile","ForumProfile","AssignableProfile","GradingProfile","ReadingProfile","SessionProfile","SearchProfile","ToolLaunchProfile","TimebackProfile"]),l=Y.union([Y.string(),Y.record(Y.string(),Y.unknown())]),c2=Y.object({id:u5,type:Y.string(),name:Y.string().optional(),extensions:Y.record(Y.string(),Y.unknown()).optional()}).strict(),h9=Y.object({"@context":Y.string().optional(),id:Y.string().regex(/^urn:uuid:/,"Event id must start with urn:uuid:"),type:Y.string(),actor:Y.union([Y.string(),c2,U2]),action:Y.string(),object:l,eventTime:y,profile:r5,edApp:l.optional(),generated:l.optional(),target:l.optional(),referrer:l.optional(),group:l.optional(),membership:l.optional(),session:l.optional(),federatedSession:l.optional(),extensions:Y.record(Y.string(),Y.unknown()).optional()}).strict(),U9=Y.object({sensor:X,sendTime:y,dataVersion:Y.literal("http://purl.imsglobal.org/ctx/caliper/v1p2"),data:Y.array(h9).min(1,"data must contain at least one event")}),t5=Y.object({sensor:X,events:Y.array(h9).min(1,"events must contain at least one event")}),M9=Y.object({limit:Y.number().int().positive().optional(),offset:Y.number().int().min(0).optional(),sensor:X.optional(),startDate:y.optional(),endDate:y.optional(),actorId:X.optional(),actorEmail:Y.email().optional()}).strict(),S9=Y.object({id:Y.string(),name:Y.string().optional(),isPartOf:l.optional(),extensions:Y.record(Y.string(),Y.unknown()).optional()}),e5=Y.object({id:Y.string(),attempt:Y.union([Y.string(),Y.record(Y.string(),Y.unknown())]).optional(),startedAtTime:y.optional(),endedAtTime:y.optional(),duration:Y.string().optional(),extensions:Y.record(Y.string(),Y.unknown()).optional()}),$Z=Y.object({id:Y.string().optional(),scoreGiven:Y.number(),maxScore:Y.number().optional(),attempt:Y.union([Y.string(),Y.record(Y.string(),Y.unknown())]).optional(),comment:Y.string().optional(),extensions:Y.record(Y.string(),Y.unknown()).optional()}),JZ=Y.object({actor:Y.union([Y.string(),c2,U2]),object:S9,edApp:l,id:Y.string().optional(),eventTime:y.optional(),session:l.optional(),extensions:Y.record(Y.string(),Y.unknown()).optional()}).strict(),ZZ=Y.object({actor:Y.union([Y.string(),c2,U2]),object:S9,edApp:l,generated:e5.optional(),id:Y.string().optional(),eventTime:y.optional(),session:l.optional(),extensions:Y.record(Y.string(),Y.unknown()).optional()}).strict(),HZ=Y.object({actor:Y.union([Y.string(),c2,U2]),object:Y.string(),generated:$Z,edApp:l,id:Y.string().optional(),eventTime:y.optional(),session:l.optional(),extensions:Y.record(Y.string(),Y.unknown()).optional()}).strict(),I1=Z2.object({name:X,targetUrl:Z2.url("targetUrl must be a valid URL"),secret:X,active:Z2.boolean(),sensor:Z2.string().nullable().optional(),description:Z2.string().nullable().optional()}).strict(),KZ=Z2.enum(["string","number","boolean"]),XZ=Z2.enum(["eq","neq","gt","gte","lt","lte","contains","notContains","in","notIn","startsWith","endsWith","regexp"]),b1=Z2.object({webhookId:X,filterKey:X,filterValue:X,filterType:KZ,filterOperator:XZ,active:Z2.boolean()}).strict(),p2=U.string().uuid(),j9=U.object({title:X,identifier:p2,uri:X}),WZ=U.object({identifier:p2,uri:X,lastChangeDateTime:X,title:X,creator:X,officialSourceURL:U.string().optional(),publisher:U.string().optional(),description:U.string().optional(),language:U.string().optional(),version:U.string().optional(),caseVersion:U.string().optional(),adoptionStatus:U.string().optional(),statusStartDate:U.string().optional(),statusEndDate:U.string().optional(),licenseUri:U.string().optional(),notes:U.string().optional(),subject:U.array(U.string()).optional(),extensions:U.unknown().optional()}),YZ=U.object({identifier:p2,uri:X,lastChangeDateTime:X,fullStatement:X,alternativeLabel:U.string().optional(),CFItemType:U.string().optional(),cfItemType:U.string().optional(),humanCodingScheme:U.string().optional(),listEnumeration:U.string().optional(),abbreviatedStatement:U.string().optional(),conceptKeywords:U.array(U.string()).optional(),notes:U.string().optional(),subject:U.array(U.string()).optional(),language:U.string().optional(),educationLevel:U.array(U.string()).optional(),CFItemTypeURI:U.unknown().optional(),licenseURI:U.unknown().optional(),statusStartDate:U.string().optional(),statusEndDate:U.string().optional(),extensions:U.unknown().optional()}),QZ=U.object({identifier:p2,uri:X,lastChangeDateTime:X,associationType:X,originNodeURI:j9,destinationNodeURI:j9,sequenceNumber:U.number().optional(),extensions:U.unknown().optional()}),GZ=U.object({CFItemTypes:U.array(U.unknown()).optional(),CFSubjects:U.array(U.unknown()).optional(),CFConcepts:U.array(U.unknown()).optional(),CFLicenses:U.array(U.unknown()).optional(),CFAssociationGroupings:U.array(U.unknown()).optional(),extensions:U.unknown().optional()}),h1=U.object({CFDocument:WZ,CFItems:U.array(YZ),CFAssociations:U.array(QZ),CFDefinitions:GZ.optional(),extensions:U.unknown().optional()}),L9="https://www.w3.org/ns/credentials/v2",BZ=w.array(w.url()).min(3,"@context must include W3C, CLR, and OB context URLs").refine(($)=>$[0]===L9,`First @context entry must be "${L9}"`),E9=w.object({id:w.url(),type:w.literal("Image"),caption:w.string().optional()}),N8=w.object({id:w.url(),type:w.array(w.string()).min(1).refine(($)=>$.includes("Profile"),'type must include "Profile"'),name:w.string().optional(),url:w.string().url().optional(),phone:w.string().optional(),description:w.string().optional(),image:E9.optional(),email:w.string().email().optional()}),v9=w.object({type:X,proofPurpose:X,verificationMethod:X,created:w.iso.datetime(),proofValue:X,cryptosuite:w.string().optional()}),_Z=w.object({id:X,type:w.literal("1EdTechJsonSchemaValidator2019")}),FZ=w.object({id:w.string().url().optional(),narrative:w.string().optional()}),OZ=w.object({id:w.url(),type:w.array(w.string()).min(1).refine(($)=>$.includes("Achievement"),'type must include "Achievement"'),name:X,description:X,criteria:FZ,image:E9.optional(),achievementType:w.string().optional(),creator:N8.optional()}),DZ=w.object({type:w.literal("IdentityObject"),identityHash:X,identityType:X,hashed:w.boolean(),salt:w.string().optional()}),wZ=w.enum(["exactMatchOf","isChildOf","isParentOf","isPartOf","isPeerOf","isRelatedTo","precedes","replacedBy"]),xZ=w.object({type:w.literal("Association"),associationType:wZ,sourceId:w.url(),targetId:w.url()}),UZ=w.object({"@context":w.array(w.string()).min(1),id:w.url(),type:w.array(w.string()).min(1).refine(($)=>$.includes("VerifiableCredential"),'type must include "VerifiableCredential"'),issuer:N8,validFrom:w.iso.datetime(),validUntil:w.string().datetime().optional(),credentialSubject:w.object({id:w.string().optional()}),proof:w.array(v9).optional()}),MZ=w.object({id:w.string().url().optional(),type:w.array(w.string()).min(1).refine(($)=>$.includes("ClrSubject"),'type must include "ClrSubject"'),identifier:w.array(DZ).optional(),achievement:w.array(OZ).optional(),verifiableCredential:w.array(UZ).min(1),association:w.array(xZ).optional()}),S1=w.object({"@context":BZ,id:w.url(),type:w.array(w.string()).min(1).refine(($)=>$.includes("VerifiableCredential")&&$.includes("ClrCredential"),'type must include "VerifiableCredential" and "ClrCredential"'),issuer:N8,name:X,description:w.string().optional(),validFrom:w.iso.datetime(),validUntil:w.iso.datetime().optional(),credentialSubject:MZ,proof:w.array(v9).optional(),credentialSchema:w.array(_Z).optional()}),jZ=k.object({staging:k.string().meta({description:"Course ID in staging environment"}).optional(),production:k.string().meta({description:"Course ID in production environment"}).optional()}).meta({id:"CourseIds",description:"Environment-specific course IDs (populated by sync)"}),LZ=k.enum(["base","hole-filling","optional"]).meta({id:"CourseType",description:"Course classification type"}),VZ=k.enum(["draft","testing","published","deactivated"]).meta({id:"PublishStatus",description:"Course publication status"}),kZ=k.object({dailyXp:k.number().int().positive().meta({description:"Target XP to earn per day"}).optional(),dailyLessons:k.number().int().positive().meta({description:"Target lessons to complete per day"}).optional(),dailyActiveMinutes:k.number().int().positive().meta({description:"Target active learning minutes per day"}).optional(),dailyAccuracy:k.number().int().min(0).max(100).meta({description:"Target accuracy percentage (0-100)"}).optional(),dailyMasteredUnits:k.number().int().positive().meta({description:"Target units to master per day"}).optional()}).meta({id:"CourseGoals",description:"Daily learning goals for a course"}),qZ=k.object({totalXp:k.number().int().positive().meta({description:"Total XP available in the course"}).optional(),totalLessons:k.number().int().positive().meta({description:"Total number of lessons/activities"}).optional(),totalGrades:k.number().int().positive().meta({description:"Total grade levels covered"}).optional()}).meta({id:"CourseMetrics",description:"Aggregate metrics for a course"}),y9=k.object({courseType:LZ.optional(),isSupplemental:k.boolean().meta({description:"Whether this is supplemental to a base course"}).optional(),isCustom:k.boolean().meta({description:"Whether this is a custom course for an individual student"}).optional(),publishStatus:VZ.optional(),contactEmail:k.email().meta({description:"Contact email for course issues"}).optional(),primaryApp:k.string().meta({description:"Primary application identifier"}).optional(),goals:kZ.optional(),metrics:qZ.optional()}).meta({id:"CourseMetadata",description:"Course metadata (matches API metadata object)"}),f9=k.object({courseCode:k.string().meta({description:"Course code (e.g., 'MATH101')"}).optional(),level:k.string().meta({description:"Course level (e.g., 'AP', 'Honors')"}).optional(),metadata:y9.optional()}).meta({id:"CourseDefaults",description:"Default properties that apply to all courses unless overridden"}),V9=k.object({level:k.string().meta({description:"Course level for this environment"}).optional(),sensor:k.url().meta({description:"Caliper sensor endpoint URL for this environment"}).optional(),launchUrl:k.url().meta({description:"LTI launch URL for this environment"}).optional(),metadata:y9.optional()}).meta({id:"CourseEnvOverrides",description:"Environment-specific course overrides (non-identity fields)"}),CZ=k.object({staging:V9.meta({description:"Overrides for staging environment"}).optional(),production:V9.meta({description:"Overrides for production environment"}).optional()}).meta({id:"CourseOverrides",description:"Per-environment course overrides"}),AZ=f9.extend({subject:X2.meta({description:"Subject area for this course"}),grade:n.meta({description:"Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"}).optional(),ids:jZ.nullable().optional(),sensor:k.url().meta({description:"Caliper sensor endpoint URL for this course"}).optional(),launchUrl:k.url().meta({description:"LTI launch URL for this course"}).optional(),overrides:CZ.optional()}).meta({id:"CourseConfig",description:"Configuration for a single course. Must have either grade or courseCode (or both)."}),E1=k.object({$schema:k.string().meta({description:"JSON Schema reference for editor support"}).optional(),name:k.string().min(1,"App name is required").meta({description:"Display name for your app"}),defaults:f9.meta({description:"Default properties applied to all courses"}).optional(),courses:k.array(AZ).min(1,"At least one course is required").meta({description:"Courses available in this app"}),sensor:k.url().meta({description:"Default Caliper sensor endpoint URL for all courses"}).optional(),launchUrl:k.url().meta({description:"Default LTI launch URL for all courses"}).optional(),studio:k.object({telemetry:k.boolean().meta({description:"Enable anonymous usage telemetry for Studio (default: true)"}).optional().default(!0)}).meta({description:"Studio-specific configuration"}).optional()}).meta({id:"TimebackConfig",title:"Timeback Config",description:"Configuration schema for timeback.config.json files"}).refine(($)=>{return $.courses.every((J)=>J.grade!==void 0||J.courseCode!==void 0)},{message:"Each course must have either a grade or a courseCode",path:["courses"]}).refine(($)=>{let Z=$.courses.filter((H)=>H.grade!==void 0).map((H)=>`${H.subject}:${H.grade}`);return new Set(Z).size===Z.length},{message:"Duplicate (subject, grade) pair found; each must be unique",path:["courses"]}).refine(($)=>{let Z=$.courses.filter((H)=>H.courseCode!==void 0).map((H)=>H.courseCode);return new Set(Z).size===Z.length},{message:"Duplicate courseCode found; each must be unique",path:["courses"]}).refine(($)=>{return $.courses.every((J)=>{if(J.sensor!==void 0||$.sensor!==void 0)return!0;return[J.launchUrl,$.launchUrl,J.overrides?.staging?.launchUrl,J.overrides?.production?.launchUrl].filter(Boolean).length>0})},{message:"Each course must have an effective sensor. Either set `sensor` explicitly (top-level or per-course), or provide a `launchUrl` so sensor can be derived from its origin.",path:["courses"]}),H2=D.union([y,C2]),v1=D.object({id:D.string(),role:D.string(),beginDate:H2.nullable(),endDate:H2.nullable(),metadata:D.object({goals:D.object({dailyXp:D.number().optional()}).optional(),metrics:D.object({totalXp:D.number().optional(),totalLessons:D.number().optional()}).optional()}).optional(),course:D.object({id:D.string(),title:D.string(),subjects:D.array(D.string()).nullable(),grades:D.array(D.string()).nullable()}),school:D.object({id:D.string(),name:D.string()}),testOutSupported:D.boolean(),testOutEligible:D.boolean()}),zZ=D.object({activityMetrics:D.object({xpEarned:D.number(),totalQuestions:D.number(),correctQuestions:D.number(),masteredUnits:D.number()}),timeSpentMetrics:D.object({activeSeconds:D.number(),inactiveSeconds:D.number(),wasteSeconds:D.number()}),apps:D.array(D.string())}),PZ=D.record(D.string(),D.record(D.string(),zZ)),y1=D.object({message:D.string(),enrollmentId:D.string(),startDate:H2,endDate:H2,facts:PZ,factsByApp:D.unknown()}),g9=D.object({email:D.email().optional(),studentId:X.optional()}).superRefine(($,J)=>{if(!$.email&&!$.studentId)J.addIssue({code:D.ZodIssueCode.custom,message:"must provide either email or studentId",path:["email"]}),J.addIssue({code:D.ZodIssueCode.custom,message:"must provide either email or studentId",path:["studentId"]})}),f1=D.object({subject:X,grade:X,courseId:X,orgSourcedId:X.optional()}),g1=D.object({userId:X}),d1=D.object({sourcedId:X.optional(),role:v5.optional(),beginDate:y.optional(),metadata:D.record(D.string(),D.unknown()).optional()}),m1=D.object({fields:D.string().optional(),limit:D.number().int().positive().optional(),offset:D.number().int().nonnegative().optional(),sort:D.string().optional(),orderBy:D.enum(["asc","desc"]).optional(),filter:D.string().optional(),search:D.string().optional(),roles:D.array(P9).min(1),orgSourcedIds:D.array(X).optional()}),l1=g9.extend({startDate:H2,endDate:H2,timezone:D.string().optional()}),u1=g9.extend({weekDate:H2,timezone:D.string().optional()}),c1=D.object({enrollmentId:X,startDate:H2.optional(),endDate:H2.optional(),timezone:D.string().optional()}),p1=g.object({email:g.email()}),a1=g.object({name:X.optional(),timeback_id:X.optional(),grade:X.optional(),subject:X.optional(),all:g.boolean().optional()}),i1=g.object({student_email:g.email(),timeback_id:X.optional(),subject:X.optional(),grade_rank:g.number().int().min(0).max(12).optional(),assessment_line_item_sourced_id:X.optional(),assessment_result_sourced_id:X.optional()}).superRefine(($,J)=>{let Z=!!$.timeback_id,H=!!$.subject,K=$.grade_rank!==void 0;if(!Z&&!H)J.addIssue({code:g.ZodIssueCode.custom,message:"must provide either timeback_id or subject",path:["timeback_id"]}),J.addIssue({code:g.ZodIssueCode.custom,message:"must provide either timeback_id or subject",path:["subject"]});if(K&&!H)J.addIssue({code:g.ZodIssueCode.custom,message:"grade_rank requires subject",path:["grade_rank"]});let W=!!$.assessment_line_item_sourced_id,_=!!$.assessment_result_sourced_id;if(W!==_)J.addIssue({code:g.ZodIssueCode.custom,message:"assessment_line_item_sourced_id and assessment_result_sourced_id must be provided together",path:W?["assessment_result_sourced_id"]:["assessment_line_item_sourced_id"]})}),s1=g.object({student_email:g.email(),assignment_id:g.number().int().positive().optional(),timeback_id:X.optional(),subject:X.optional(),grade_rank:g.number().int().min(0).max(12).optional()}).superRefine(($,J)=>{let Z=$.assignment_id!==void 0,H=!!$.timeback_id,K=!!$.subject&&$.grade_rank!==void 0;if(!Z&&!H&&!K)J.addIssue({code:g.ZodIssueCode.custom,message:"Either assignment_id, timeback_id, or (subject and grade_rank) is required",path:["assignment_id"]});if($.grade_rank!==void 0&&!$.subject)J.addIssue({code:g.ZodIssueCode.custom,message:"grade_rank requires subject",path:["grade_rank"]})}),f=Q.enum(["active","tobedeleted"]),v=Q.record(Q.string(),Q.unknown()).nullable().optional(),L=Q.object({sourcedId:X,type:Q.string().optional(),href:Q.string().optional()}).strict(),TZ=Q.enum(["academicSession","assessmentLineItem","category","class","course","demographics","enrollment","gradingPeriod","lineItem","org","resource","result","scoreScale","student","teacher","term","user","componentResource","courseComponent"]),RZ=Q.object({sourcedId:X,type:TZ,href:Q.url()}).strict(),K2=Q.union([C2,y]).transform(($)=>$.includes("T")?$:`${$}T00:00:00Z`),NZ=Q.object({learningObjectiveId:Q.string(),score:Q.number().optional(),textScore:Q.string().optional()}),d9=Q.array(Q.object({source:Q.string(),learningObjectiveResults:Q.array(NZ)})),IZ=Q.object({roleType:Q.enum(["primary","secondary"]),role:P9,org:L,userProfile:Q.string().optional(),metadata:v,beginDate:K2.optional(),endDate:K2.optional()}).strict(),o1=Q.object({sourcedId:X.describe("sourcedId must be a non-empty string"),status:f.optional(),enabledUser:Q.union([Q.boolean(),Q.enum(["true","false"]).transform(($)=>$==="true")]),givenName:X.describe("givenName must be a non-empty string"),familyName:X.describe("familyName must be a non-empty string"),middleName:X.nullable().optional(),preferredFirstName:X.nullable().optional(),preferredMiddleName:X.nullable().optional(),preferredLastName:X.nullable().optional(),username:X.nullable().optional(),email:Q.email(),userMasterIdentifier:Q.string().nullable().optional(),roles:Q.array(IZ).min(1,"roles must include at least one role"),userIds:Q.array(Q.object({type:X,identifier:X}).strict()).optional(),agents:Q.array(L).optional(),primaryOrg:L.optional(),grades:Q.array(n).optional(),sms:X.nullable().optional(),phone:X.nullable().optional(),pronouns:X.nullable().optional(),password:X.nullable().optional(),metadata:v}).strict(),n1=Q.object({sourcedId:X.describe("sourcedId must be a non-empty string").optional(),status:f,title:X.describe("title must be a non-empty string"),org:L,courseCode:X.nullable().optional(),subjects:Q.array(X2).nullable().optional(),subjectCodes:Q.array(Q.string()).nullable().optional(),grades:Q.array(n).nullable().optional(),level:X.nullable().optional(),academicSession:L.nullable().optional(),schoolYear:RZ.nullable().optional(),gradingScheme:X.nullable().optional(),metadata:v}).strict(),r1=Q.object({sourcedId:X.describe("sourcedId must be a non-empty string").optional(),status:f.optional(),title:X.describe("title must be a non-empty string"),terms:Q.array(L).min(1,"terms must have at least one item"),course:L,org:L,classCode:X.nullable().optional(),classType:Q.enum(["homeroom","scheduled"]).optional(),location:X.nullable().optional(),grades:Q.array(n).optional(),subjects:Q.array(X2).optional(),subjectCodes:Q.array(X).optional(),periods:Q.array(X).optional(),metadata:v}).strict(),J2=Q.enum(["true","false"]),t1=Q.object({sourcedId:X.describe("sourcedId must be a non-empty string").optional(),status:f.optional(),user:L,class:L,school:L.optional(),role:Q.enum(["administrator","proctor","student","teacher"]),primary:J2.optional(),beginDate:C2.optional(),endDate:C2.optional(),metadata:v}).strict(),e1=Q.object({sourcedId:X.optional(),title:X.describe("title must be a non-empty string"),status:f,weight:Q.number().nullable().optional(),metadata:v}).strict(),$6=Q.object({sourcedId:X.optional(),title:X.describe("title must be a non-empty string"),class:L,school:L,category:L,assignDate:K2,dueDate:K2,status:f.optional(),description:Q.string().nullable().optional(),resultValueMin:Q.number().nullable().optional(),resultValueMax:Q.number().nullable().optional(),gradingPeriod:L.nullable().optional(),academicSession:L.nullable().optional(),scoreScale:L.nullable().optional(),learningObjectiveSet:T9.nullable().optional(),metadata:v}).strict(),J6=Q.object({sourcedId:X.optional(),lineItem:L,student:L,class:L.nullable().optional(),scoreDate:K2,scoreStatus:Q.enum(["exempt","fully graded","not submitted","partially graded","submitted"]),score:Q.number().nullable().optional(),textScore:Q.string().nullable().optional(),status:f,scoreScale:L.nullable().optional(),comment:Q.string().nullable().optional(),learningObjectiveSet:d9.nullable().optional(),inProgress:Q.string().optional(),incomplete:Q.string().optional(),late:Q.string().optional(),missing:Q.string().optional(),metadata:v}).strict(),Z6=Q.object({sourcedId:X.optional(),title:X.describe("title must be a non-empty string"),status:f,type:X,class:L,course:L.nullable().optional(),scoreScaleValue:Q.array(Q.object({itemValueLHS:X,itemValueRHS:X,value:Q.string().optional(),description:Q.string().optional()}).strict()),metadata:v}).strict(),H6=Q.object({sourcedId:X.optional(),status:f,dateLastModified:y.optional(),title:X.describe("title must be a non-empty string"),description:Q.string().nullable().optional(),class:L.nullable().optional(),parentAssessmentLineItem:L.nullable().optional(),scoreScale:L.nullable().optional(),resultValueMin:Q.number().nullable().optional(),resultValueMax:Q.number().nullable().optional(),component:L.nullable().optional(),componentResource:L.nullable().optional(),learningObjectiveSet:Q.array(Q.object({source:Q.string(),learningObjectiveIds:Q.array(Q.string())})).optional().nullable(),course:L.nullable().optional(),metadata:v}).strict(),K6=Q.object({sourcedId:X.optional(),status:f,dateLastModified:y.optional(),metadata:v,assessmentLineItem:L,student:L,score:Q.number().nullable().optional(),textScore:Q.string().nullable().optional(),scoreDate:K2,scoreScale:L.nullable().optional(),scorePercentile:Q.number().nullable().optional(),scoreStatus:Q.enum(["exempt","fully graded","not submitted","partially graded","submitted"]),comment:Q.string().nullable().optional(),learningObjectiveSet:d9.nullable().optional(),inProgress:Q.string().nullable().optional(),incomplete:Q.string().nullable().optional(),late:Q.string().nullable().optional(),missing:Q.string().nullable().optional()}).strict(),X6=Q.object({sourcedId:X.optional(),status:f.optional(),name:X.describe("name must be a non-empty string"),type:E5,identifier:Q.string().nullish(),parent:L.optional(),metadata:v}).strict(),W6=Q.object({sourcedId:X.optional(),status:f.optional(),name:X.describe("name must be a non-empty string"),type:Q.literal("school").default("school"),identifier:Q.string().nullish(),parent:L.optional(),metadata:v}).strict(),Y6=Q.object({sourcedId:X.describe("sourcedId must be a non-empty string"),status:f,title:X.describe("title must be a non-empty string"),startDate:K2,endDate:K2,type:Q.enum(["gradingPeriod","semester","schoolYear","term"]),schoolYear:X.describe("schoolYear must be a non-empty string"),org:L,parent:L.optional(),children:Q.array(L).optional(),metadata:v}).strict(),Q6=Q.object({sourcedId:X,title:X.describe("title must be a non-empty string"),courseComponent:L,resource:L,status:f,sortOrder:Q.number().optional(),lessonType:l5.optional(),metadata:v}).strict(),G6=Q.object({sourcedId:X.optional(),title:X.describe("title must be a non-empty string"),course:L,status:f,sortOrder:Q.number().optional(),parent:L.nullable().optional(),courseComponent:L.nullable().optional(),prerequisites:Q.array(Q.string()).nullable().optional(),prerequisiteCriteria:Q.string().nullable().optional(),unlockDate:K2.nullable().optional(),metadata:v}).strict().transform(({courseComponent:$,parent:J,...Z})=>({...Z,parent:J===void 0?$??void 0:J})),B6=Q.object({sourcedId:X.describe("sourcedId must be a non-empty string"),role:Q.enum(["student","teacher"]),primary:J2.optional(),beginDate:C2.optional(),endDate:C2.optional(),metadata:v}).strict(),_6=Q.object({agentSourcedId:X.describe("agentSourcedId must be a non-empty string")}).strict(),F6=Q.object({applicationName:X.describe("applicationName must be a non-empty string"),credentials:Q.object({username:X.describe("username must be a non-empty string"),password:X.describe("password must be a non-empty string")})}).strict(),O6=Q.object({sourcedId:X.describe("sourcedId must be a non-empty string"),status:f.optional(),metadata:v,birthDate:Q.string().regex(/^\d{4}-\d{2}-\d{2}$/).nullable().optional(),sex:Q.enum(["male","female"]).nullable().optional(),americanIndianOrAlaskaNative:J2.nullable().optional(),asian:J2.nullable().optional(),blackOrAfricanAmerican:J2.nullable().optional(),nativeHawaiianOrOtherPacificIslander:J2.nullable().optional(),white:J2.nullable().optional(),demographicRaceTwoOrMoreRaces:J2.nullable().optional(),hispanicOrLatinoEthnicity:J2.nullable().optional(),countryOfBirthCode:Q.string().nullable().optional(),stateOfBirthAbbreviation:Q.string().nullable().optional(),cityOfBirth:Q.string().nullable().optional(),publicSchoolResidenceStatus:Q.string().nullable().optional()}).strict(),G2=Q.object({type:y5,subject:X2.nullish(),grades:Q.array(n).nullish(),language:Q.string().nullish(),xp:Q.number().nullish(),url:Q.url().nullish(),keywords:Q.array(Q.string()).nullish(),learningObjectiveSet:T9.nullish(),lessonType:Q.string().nullish()}).passthrough(),bZ=G2.extend({type:Q.literal("qti"),subType:f5,questionType:d5.optional(),difficulty:m5.optional()}),hZ=G2.extend({type:Q.literal("text"),format:Q.string(),author:Q.string().optional(),pageCount:Q.number().optional()}),SZ=G2.extend({type:Q.literal("audio"),duration:Q.string().regex(/^\d{2}:\d{2}:\d{2}(\.\d{2})?$/).optional(),format:Q.string(),speaker:Q.string().optional()}),EZ=G2.extend({type:Q.literal("video"),duration:Q.string().regex(/^\d{2}:\d{2}:\d{2}(\.\d{2})?$/).optional(),captionsAvailable:Q.boolean().optional(),format:Q.string()}),vZ=G2.extend({type:Q.literal("interactive"),launchUrl:Q.url().optional(),toolProvider:Q.string().optional(),instructionalMethod:Q.string().optional(),courseIdOnFail:Q.string().nullable().optional(),fail_fast:R9}),yZ=G2.extend({type:Q.literal("visual"),format:Q.string(),resolution:Q.string().optional()}),fZ=G2.extend({type:Q.literal("course-material"),subType:g5,author:Q.string().optional(),format:Q.string(),instructionalMethod:Q.string().optional()}),gZ=G2.extend({type:Q.literal("assessment-bank"),resources:Q.array(Q.string())}),dZ=Q.discriminatedUnion("type",[bZ,hZ,SZ,EZ,vZ,yZ,fZ,gZ]),mZ=new Set(["type","subject","grades","language","xp","url","keywords","learningObjectiveSet","lessonType","subType","questionType","difficulty","format","author","pageCount","duration","speaker","captionsAvailable","launchUrl","toolProvider","instructionalMethod","courseIdOnFail","resolution","resources"]),lZ=Q.record(Q.string(),Q.unknown()).superRefine(($,J)=>{if("fail_fast"in $){let H=R9.safeParse($.fail_fast);if(!H.success)for(let K of H.error.issues)J.addIssue({...K,path:["fail_fast",...K.path]})}let Z=Object.keys($).filter((H)=>mZ.has(H));if(Z.length===0)return;J.addIssue({code:"custom",message:`metadata keys ${Z.map((H)=>`\`${H}\``).join(", ")} require a valid \`type\` discriminator`})}),D6=Q.object({sourcedId:X.optional(),title:X.describe("title must be a non-empty string"),vendorResourceId:X.describe("vendorResourceId must be a non-empty string"),roles:Q.array(Q.enum(["primary","secondary"])).optional(),importance:Q.enum(["primary","secondary"]).optional(),vendorId:X.nullable().optional(),applicationId:X.nullable().optional(),status:f.optional(),metadata:Q.union([dZ,lZ]).nullable().optional()}).strict(),uZ=Q.object({url:X.describe("courseStructure.url must be a non-empty string"),skillCode:X.describe("courseStructure.skillCode must be a non-empty string"),lessonCode:X.describe("courseStructure.lessonCode must be a non-empty string"),title:X.describe("courseStructure.title must be a non-empty string"),"unit-title":X.describe("courseStructure.unit-title must be a non-empty string"),status:X.describe("courseStructure.status must be a non-empty string"),xp:Q.number()}).loose(),w6=Q.object({course:Q.object({sourcedId:X.describe("course.sourcedId must be a non-empty string").optional(),title:X.describe("course.title must be a non-empty string"),org:L,status:f,metadata:v}).strict(),courseStructure:Q.record(Q.string(),uZ)}).strict(),cZ=Q.object({student:L}).loose(),x6=Q.array(cZ).min(1,"results must have at least one item"),pZ=B.enum(["edulastic","mastery-track"]),aZ=B.enum(["powerpath-100","quiz","test-out","placement","unit-test","alpha-read-article"]),m9=B.array(n),l9=B.record(B.string(),B.unknown()).optional(),u9=B.object({courseId:X,lessonTitle:X.optional(),launchUrl:X.optional(),toolProvider:pZ,unitTitle:X.optional(),courseComponentSourcedId:X.optional(),vendorId:X.optional(),description:X.optional(),resourceMetadata:l9.nullable().optional(),grades:m9}),U6=u9.extend({lessonType:B.literal("test-out"),xp:B.number()}),M6=u9.extend({lessonType:B.literal("placement"),courseIdOnFail:X.nullable().optional(),xp:B.number().optional()}),k9=B.object({courseId:X,lessonType:aZ,lessonTitle:X.optional(),unitTitle:X.optional(),courseComponentSourcedId:X.optional(),resourceMetadata:l9.nullable().optional(),xp:B.number().optional(),grades:m9.optional(),courseIdOnFail:X.nullable().optional()}),j6=B.discriminatedUnion("testType",[k9.extend({testType:B.literal("qti"),qti:B.object({url:B.url(),title:X.optional(),metadata:B.record(B.string(),B.unknown()).optional()})}),k9.extend({testType:B.literal("assessment-bank"),assessmentBank:B.object({resources:B.array(B.object({url:B.url(),title:X.optional(),metadata:B.record(B.string(),B.unknown()).optional()})).min(1)})})]),L6=B.object({student:X,lesson:X}),V6=B.object({student:X,lesson:X}),k6=B.object({courseId:X,userId:X,classId:X.optional()}),q2=B.object({type:B.enum(["component","resource"]),id:X}),iZ=B.union([B.object({type:B.literal("set-skipped"),payload:B.object({target:q2,value:B.boolean()})}),B.object({type:B.literal("add-custom-resource"),payload:B.object({resource_id:X,parent_component_id:X,skipped:B.boolean().optional()})}),B.object({type:B.literal("move-item-before"),payload:B.object({target:q2,reference_id:X})}),B.object({type:B.literal("move-item-after"),payload:B.object({target:q2,reference_id:X})}),B.object({type:B.literal("move-item-to-start"),payload:B.object({target:q2})}),B.object({type:B.literal("move-item-to-end"),payload:B.object({target:q2})}),B.object({type:B.literal("change-item-parent"),payload:B.object({target:q2,new_parent_id:X,position:B.enum(["start","end"]).optional()})})]),q6=B.object({operation:iZ,reason:X.optional()}),C6=B.object({studentId:X,componentResourceId:X,result:B.object({status:B.enum(["active","tobedeleted"]),metadata:B.record(B.string(),B.unknown()).optional(),score:B.number().optional(),textScore:X.optional(),scoreDate:B.string().datetime(),scorePercentile:B.number().optional(),scoreStatus:S5,comment:X.optional(),learningObjectiveSet:B.array(B.object({source:X,learningObjectiveResults:B.array(B.object({learningObjectiveId:X,score:B.number().optional(),textScore:X.optional()}))})).optional(),inProgress:X.optional(),incomplete:X.optional(),late:X.optional(),missing:X.optional()})}),A6=B.object({student:X,lesson:X,applicationName:X.optional(),testId:X.optional(),skipCourseEnrollment:B.boolean().optional()}),z6=B.object({student:X,subject:X2}),P6=B.object({student:X,lesson:X}),T6=B.object({userId:X}),R6=B.object({userId:X,subject:B.enum(["Math","Reading","Language","Science"])}),N6=B.object({student:X,subject:X2,grade:n,testName:X.optional()}),I6=B.object({testName:X}),sZ=B.object({student:X,subject:X2,grade:n,testName:X.optional()}),b6=B.object({items:B.array(sZ)}),h6=B.object({spreadsheetUrl:B.url(),sheet:X}),S6=B.object({student:X,status:B.enum(["assigned","in_progress","completed","failed","expired","cancelled"]).optional(),subject:X.optional(),grade:n.optional(),limit:B.number().int().positive().max(3000).optional(),offset:B.number().int().nonnegative().optional()}),E6=B.object({student:X.optional(),status:B.enum(["assigned","in_progress","completed","failed","expired","cancelled"]).optional(),subject:X.optional(),grade:n.optional(),limit:B.number().int().positive().max(3000).optional(),offset:B.number().int().nonnegative().optional()}),v6=B.object({student:X,question:X,response:B.union([X,B.array(X)]).optional(),responses:B.record(B.string(),B.union([X,B.array(X)])).optional(),lesson:X,rendererOutcomes:B.object({score:B.number(),maxScore:B.number().min(0),isCorrect:B.boolean()}).optional(),playerState:B.string().optional()}).refine(($)=>$.response!==void 0||$.responses!==void 0,{message:"Either 'response' or 'responses' must be provided",path:["response","responses"]}).transform(($)=>{if($.response!==void 0&&$.responses===void 0)return{...$,responses:{RESPONSE:$.response}};return $}),y6=B.object({student:X,lesson:X,attempt:B.number().int().positive().optional()}),f6=B.object({student:X,lesson:X}),g6=B.object({student:X,lesson:X}),d6=B.object({student:X,course:X}),m6=B.object({student:X,lesson:X,applicationName:X.optional()}),l6=B.object({student:X,subject:X2}),u6=B.object({oneRosterSourcedId:X,subject:X}),c6=B.object({courseIds:B.array(X).min(1),rendererId:X,rendererUrl:B.url(),rendererVersion:X.optional(),suppressFeedback:B.boolean().optional(),suppressCorrectResponse:B.boolean().optional()}),p6=B.object({status:B.enum(["active","tobedeleted"]).optional()}),c9=G.enum(["choice","text-entry","extended-text","inline-choice","match","order","associate","select-point","graphic-order","graphic-associate","graphic-gap-match","hotspot","hottext","slider","drawing","media","upload"]),I8=G.enum(["single","multiple","ordered","record"]),b8=G.enum(["identifier","boolean","integer","float","string","point","pair","directedPair","duration","file","uri"]),oZ=G.enum(["easy","medium","hard"]),nZ=G.enum(["linear","nonlinear"]),rZ=G.enum(["individual","simultaneous"]),h8=G.enum(["show","hide"]),p9=G.enum(["test","item","stimulus"]),a6=G.enum(["QUESTION","LESSON"]),tZ=G.object({value:G.array(G.string())}).strict(),a9=G.object({identifier:X,cardinality:I8,baseType:b8.optional(),correctResponse:tZ}).strict(),i9=G.object({identifier:X,cardinality:I8,baseType:b8.optional()}).strict(),s9=G.object({identifier:X,cardinality:I8.optional(),baseType:b8,normalMaximum:G.number().optional(),normalMinimum:G.number().optional(),defaultValue:G.object({value:G.unknown().optional()}).strict().optional()}).strict(),eZ=G.object({outcomeIdentifier:X,variableIdentifier:X}).strict(),o9=G.object({templateType:G.enum(["match_correct","map_response"]),responseDeclarationIdentifier:X,outcomeIdentifier:X,correctResponseIdentifier:X,incorrectResponseIdentifier:X,inlineFeedback:eZ.optional()}).strict(),$0=G.object({source:X,learningObjectiveIds:G.array(G.string())}).strict(),S8=G.object({subject:G.string().optional(),grade:n.optional(),difficulty:oZ.optional(),learningObjectiveSet:G.array($0).optional()}).loose(),n9=G.object({outcomeIdentifier:X,identifier:X,showHide:h8,content:G.string(),title:G.string()}).strict(),r9=G.object({outcomeIdentifier:X,identifier:X,showHide:h8,content:G.string(),class:G.array(G.string())}).strict(),t9=G.object({outcomeIdentifier:X,identifier:X,showHide:h8,content:G.string(),class:G.array(G.string())}).strict(),e9=G.object({href:X,type:X}).strict(),$$=G.object({id:X,support:G.string(),content:G.string()}).strict(),i6=G.object({page:G.number().int().positive().optional(),limit:G.number().int().positive().optional(),sort:G.string().optional(),order:G.enum(["asc","desc"]).optional()}).strict(),J0=G.object({format:G.string().pipe(G.literal("xml")),xml:X,metadata:S8.optional()}).strict(),Z0=G.object({identifier:X,title:X,type:c9,qtiVersion:G.string().optional(),timeDependent:G.boolean().optional(),adaptive:G.boolean().optional(),responseDeclarations:G.array(a9).optional(),outcomeDeclarations:G.array(i9).optional(),responseProcessing:o9.optional(),metadata:S8.optional(),modalFeedback:G.array(n9).optional(),feedbackInline:G.array(r9).optional(),feedbackBlock:G.array(t9).optional()}).strict(),s6=G.union([J0,Z0]),o6=G.object({identifier:X.optional(),title:X,type:c9,qtiVersion:G.string().optional(),timeDependent:G.boolean().optional(),adaptive:G.boolean().optional(),responseDeclarations:G.array(a9).optional(),outcomeDeclarations:G.array(i9).optional(),responseProcessing:o9.optional(),metadata:S8.optional(),modalFeedback:G.array(n9).optional(),feedbackInline:G.array(r9).optional(),feedbackBlock:G.array(t9).optional(),rawXml:G.string(),content:G.record(G.string(),G.unknown())}).strict(),n6=G.object({identifier:X,response:G.union([G.string(),G.array(G.string())])}).strict(),J$=G.object({identifier:X,href:X,sequence:G.number().int().positive().optional()}).strict(),H0=G.object({identifier:X,title:X,visible:G.boolean(),required:G.boolean().optional(),fixed:G.boolean().optional(),sequence:G.number().int().positive(),"qti-assessment-item-ref":G.array(J$).optional()}).strict(),Z$=G.object({identifier:X,navigationMode:G.string().pipe(nZ),submissionMode:G.string().pipe(rZ),"qti-assessment-section":G.array(H0)}).strict(),r6=G.object({items:G.array(J$).min(1)}).strict(),t6=G.object({metadata:G.record(G.string(),G.unknown()).optional()}).strict(),e6=G.object({identifier:X,title:X,qtiVersion:G.string().optional(),toolName:G.string().optional(),toolVersion:G.string().optional(),timeLimit:G.number().optional(),maxAttempts:G.number().optional(),toolsEnabled:G.record(G.string(),G.boolean()).optional(),metadata:G.record(G.string(),G.unknown()).optional(),"qti-test-part":G.array(Z$),"qti-outcome-declaration":G.array(s9).optional()}).strict(),$7=G.object({identifier:X.optional(),title:X,qtiVersion:G.string().optional(),toolName:G.string().optional(),toolVersion:G.string().optional(),timeLimit:G.number().optional(),maxAttempts:G.number().optional(),toolsEnabled:G.record(G.string(),G.boolean()).optional(),metadata:G.record(G.string(),G.unknown()).optional(),"qti-test-part":G.array(Z$),"qti-outcome-declaration":G.array(s9).optional()}).strict(),J7=G.object({identifier:X,title:X,label:G.string().optional(),language:G.string().optional(),stylesheet:e9.optional(),content:G.string(),catalogInfo:G.array($$).optional(),toolName:G.string().optional(),toolVersion:G.string().optional(),metadata:G.record(G.string(),G.unknown()).optional()}).strict(),Z7=G.object({identifier:X.optional(),title:X,label:G.string().optional(),language:G.string().optional(),stylesheet:e9.optional(),content:G.string(),catalogInfo:G.array($$).optional(),toolName:G.string().optional(),toolVersion:G.string().optional(),metadata:G.record(G.string(),G.unknown()).optional()}).strict(),H7=G.object({xml:G.string().optional(),schema:p9,entityId:G.string().optional()}).strict(),K7=G.object({xml:G.array(G.string()),schema:p9,entityIds:G.array(G.string())}).strict(),X7=G.object({questionId:G.string().optional(),userId:X,feedback:X,lessonId:X,humanApproved:G.boolean().optional()}).strict(),K0=A2.enum(["creator_only","same_org","all_orgs"]),X0=A2.string().uuid(),W7=A2.email(),Y7=A2.object({sql:X}),Q7=A2.object({endpointName:X,sql:X,authMode:K0,description:X.optional()}),G7=A2.object({endpointId:X0});class H${transport;eventTransformer;constructor($,J){this.transport=$,this.eventTransformer=J?.eventTransformer}send($,J){o(t5,{sensor:$,events:J},"send events");let Z={sensor:$,sendTime:new Date().toISOString(),dataVersion:"http://purl.imsglobal.org/ctx/caliper/v1p2",data:J};return this.sendEnvelope(Z)}async sendEnvelope($){o(U9,$,"caliper envelope"),S.debug("Sending Caliper envelope",{sensor:$.sensor,eventCount:$.data.length});let J=this.eventTransformer?this.eventTransformer.transformEnvelope($):$,H=(await this.transport.request(this.transport.paths.send,{method:"POST",body:J}))?.jobId;return S.debug("Events sent",{jobId:H??"(none)"}),{jobId:H}}async validate($){let J=this.transport.paths.validate;if(!J)throw Error("validate() is not supported on this platform");o(U9,$,"caliper envelope"),S.debug("Validating Caliper envelope",{sensor:$.sensor,eventCount:$.data.length});let Z=await this.transport.request(J,{method:"POST",body:$});return S.debug("Validation complete",{status:Z.status}),Z}async list($={}){let J=this.transport.paths.list;if(!J)throw Error("list() is not supported on this platform");o(M9,$,"list events params"),S.debug("Listing events",{params:$});let Z={limit:$.limit??100,offset:$.offset??0};if($.sensor)Z.sensor=$.sensor;if($.startDate)Z.startDate=$.startDate;if($.endDate)Z.endDate=$.endDate;if($.actorId)Z.actorId=$.actorId;if($.actorEmail)Z.actorEmail=$.actorEmail;let H=await this.transport.request(J,{params:Z});return{events:H.events??[],pagination:H.pagination}}stream($={}){let J=this.transport.paths.list;if(!J)throw Error("stream() is not supported on this platform");let{max:Z,...H}=$;o(M9,H,"list events params"),z8($),S.debug("Streaming events",{params:$});let K={};if(H.limit!==void 0)K.limit=H.limit;if(H.offset!==void 0)K.offset=H.offset;if(H.sensor)K.sensor=H.sensor;if(H.startDate)K.startDate=H.startDate;if(H.endDate)K.endDate=H.endDate;if(H.actorId)K.actorId=H.actorId;if(H.actorEmail)K.actorEmail=H.actorEmail;return new C9(this.transport,J,{...K,max:Z})}async get($){let J=this.transport.paths.get;if(!J)throw Error("get() is not supported on this platform");u2($,"externalId"),S.debug("Getting event",{externalId:$});let Z=J.replace("{id}",encodeURIComponent($)),H=await this.transport.request(Z);if(!H.event)throw Error(`Event not found: ${$}`);return H.event}sendActivity($,J){o(s5,J,"activity event");let Z=P8(J);return S.debug("Sending ActivityCompletedEvent",{eventId:Z.id,actor:J.actor.email,subject:J.object.subject,metricsCount:J.metrics.length}),this.send($,[Z])}sendTimeSpent($,J){o(o5,J,"time spent event");let Z=T8(J);return S.debug("Sending TimeSpentEvent",{eventId:Z.id,actor:J.actor.email,subject:J.object.subject,metricsCount:J.metrics.length}),this.send($,[Z])}sendQuestionSeen($,J){o(JZ,J,"question seen event");let Z=j5(J);return S.debug("Sending AssessmentItemEvent.Started",{eventId:Z.id,actor:J.actor,object:J.object.id}),this.send($,[Z])}sendQuestionAnswered($,J){o(ZZ,J,"question answered event");let Z=L5(J);return S.debug("Sending AssessmentItemEvent.Completed",{eventId:Z.id,actor:J.actor,object:J.object.id}),this.send($,[Z])}sendQuestionGraded($,J){o(HZ,J,"question graded event");let Z=V5(J);return S.debug("Sending GradeEvent.Graded",{eventId:Z.id,actor:J.actor,object:J.object,scoreGiven:J.generated.scoreGiven}),this.send($,[Z])}}class K${transport;constructor($){this.transport=$}async getStatus($){let J=this.transport.paths.jobStatus;if(!J)throw Error("getStatus() is not supported on this platform");u2($,"jobId"),S.debug("Getting job status",{jobId:$});let Z=J.replace("{id}",encodeURIComponent($));return(await this.transport.request(Z)).job}async waitForCompletion($,J={}){u2($,"jobId"),W0(J);let{timeoutMs:Z=30000,pollIntervalMs:H=1000}=J,K=Date.now();S.debug("Waiting for job completion",{jobId:$,timeoutMs:Z,pollIntervalMs:H});while(Date.now()-K<Z){let W=await this.getStatus($);if(W.state==="completed")return S.info("Job completed",{jobId:$}),W;if(W.state==="failed")throw S.error("Job failed",{jobId:$}),Error(`Job ${$} failed`);await new Promise((_)=>{setTimeout(_,H)})}throw Error(`Job ${$} timed out after ${Z}ms`)}}function W0($){if(!$)return;let J=[];if($.timeoutMs!==void 0){if(!Number.isInteger($.timeoutMs)||$.timeoutMs<=0)J.push({path:"timeoutMs",message:"Must be a positive integer"})}if($.pollIntervalMs!==void 0){if(!Number.isInteger($.pollIntervalMs)||$.pollIntervalMs<=0)J.push({path:"pollIntervalMs",message:"Must be a positive integer"})}if(J.length>0)throw N2("Invalid polling options",J)}function Y0($=l2){return class{transport;_provider;events;jobs;constructor(Z={}){let H=N5(Z,$),K;if(H.mode==="transport")this.transport=H.transport,S.info("Client initialized with custom transport");else{let{provider:W}=H,{baseUrl:_,paths:F}=W.getEndpointWithPaths("caliper"),O=W.getTokenProvider("caliper");if(!O)throw Error("Caliper API requires authentication");if(this._provider=W,this.transport=new q9({baseUrl:_,tokenProvider:O,timeout:W.timeout,paths:F}),W.platform===X9)K=new A9;S.info("Client initialized",{platform:W.platform,env:W.env,baseUrl:_})}this.events=new H$(this.transport,{eventTransformer:K}),this.jobs=new K$(this.transport)}getTransport(){return this.transport}checkAuth(){if(!this._provider)throw Error("Cannot check auth: client initialized with custom transport");return this._provider.checkAuth()}}}var B7=Y0();class W2 extends Error{course;env;constructor($,J){let Z=$.grade===void 0?$.courseCode??$.subject:`${$.subject} grade ${$.grade}`;super(`Course "${Z}" is missing a synced ID for ${J}. Run \`timeback resources push\` first.`);this.name="MissingSyncedCourseIdError",this.course=$,this.env=J}}class a2 extends Error{sensor;constructor($){super(`Invalid sensor URL "${$}". Sensor must be a valid absolute URL (e.g., "https://sensor.example.com") to support slug-based activity IDs.`);this.name="InvalidSensorUrlError",this.sensor=$}}var X$="/ims/oneroster/rostering/v1p2";function W$($,J){return`${$.replace(/\/+$/,"")}/${J.replace(/^\/+/,"")}`}function Q0($,J){return W$($,`${X$}/courses/${J}`)}function G0($,J){return W$($,`${X$}/users/${J}`)}function Y$($,J){let Z=$.ids?.[J];if(!Z)throw new W2($,J);return Z}function B0($,J,Z){let H=Y$(J,Z);return Q0($,H)}function _0($){if($.courseCode)return $.courseCode;if($.grade!==void 0)return`${$.subject} G${String($.grade)}`;return $.subject}function E8($,J,Z){let H;try{H=new URL($)}catch{throw new a2($)}let K="grade"in J?`${J.subject}/g${String(J.grade)}`:J.code,W=H.pathname.replace(/\/+$/,"");return H.pathname=`${W}/activities/${K}/${encodeURIComponent(Z)}`,H.toString()}function Q$($,J,Z,H,K,W,_){return{id:E8(K,$.course,$.id),type:"TimebackActivityContext",subject:J.subject,app:{name:Z},activity:{name:$.name},course:{id:B0(W,J,H),name:_0(J)},process:_??!0}}function F0($){let J=[];if($.totalQuestions!==void 0)J.push({type:"totalQuestions",value:$.totalQuestions});if($.correctQuestions!==void 0)J.push({type:"correctQuestions",value:$.correctQuestions});if($.xpEarned!==void 0)J.push({type:"xpEarned",value:$.xpEarned});if($.masteredUnits!==void 0)J.push({type:"masteredUnits",value:$.masteredUnits});return J}function O0($,J){let Z=[{type:"active",value:Math.max(0,$)/1000}];if(J>0)Z.push({type:"inactive",value:Math.max(0,J)/1000});return Z}function D0($){return $===void 0?void 0:{pctCompleteApp:$}}function G$($,J){return{courseId:Y$($,J)}}function B$($){if(!$)return;return`urn:uuid:${$}`}function _$($,J,Z){return{id:G0($,J),type:"TimebackUser",email:Z}}function F$($){let{sensor:J,timebackId:Z,email:H,payload:K,process:W,course:_,appName:F,apiEnv:O,onerosterBaseUrl:x,attempt:V,runId:A}=$,C=_$(x,Z,H),q=Q$(K,_,F,O,J,x,W??K.process),z=F0(K.metrics),N=D0(K.pctComplete),I=B$(A),r=G$(_,O),Y2=P8({actor:C,object:q,metrics:z,eventTime:K.endedAt,generatedExtensions:N,extensions:r,attempt:V,session:I});return{sensor:J,actor:C,object:q,event:Y2,payload:K,course:_,appName:F,apiEnv:O,email:H,timebackId:Z}}function i2($){let{sensor:J,timebackId:Z,email:H,payload:K,course:W,appName:_,apiEnv:F,onerosterBaseUrl:O,runId:x}=$,V=_$(O,Z,H),A=Q$(K,W,_,F,J,O),C=O0(K.elapsedMs,K.pausedMs),q=G$(W,F),z=B$(x),N=T8({actor:V,object:A,metrics:C,eventTime:K.endedAt,extensions:q,session:z});return{sensor:J,actor:V,object:A,event:N,payload:{id:K.id,name:K.name,course:K.course,startedAt:K.startedAt,endedAt:K.endedAt,elapsedMs:K.elapsedMs,pausedMs:K.pausedMs},course:W,appName:_,apiEnv:F,email:H,timebackId:Z,runId:x}}import*as h from"zod";import*as b2 from"zod";var w0=b2.object({subject:O$,grade:D$}),x0=b2.object({code:E}),M2=b2.union([w0,x0]);class B2 extends Error{code;selector;count;constructor($,J,Z){super($);this.code=$,this.selector=J,this.count=Z}get selectorDescription(){if("grade"in this.selector)return`${this.selector.subject} grade ${this.selector.grade}`;return`code "${this.selector.code}"`}}function j2($,J){let Z;if("grade"in J)Z=$.filter((H)=>H.subject===J.subject&&H.grade===J.grade);else Z=$.filter((H)=>H.courseCode===J.code);if(Z.length===0)throw new B2("unknown_course",J);if(Z.length>1)throw new B2("ambiguous_course",J,Z.length);return Z[0]}var z2=R("handlers:activity:schema"),U0=h.object({totalQuestions:h.number().int().nonnegative().optional(),correctQuestions:h.number().int().nonnegative().optional(),xpEarned:h.number(),masteredUnits:h.number().int().nonnegative().optional()}).superRefine(o2);function M0($){return Math.min(100,Math.max(0,$))}function s2($){if("grade"in $)return`${$.subject} grade ${$.grade}`;return`code "${$.code}"`}var j0=h.object({id:E,name:E,course:M2,runId:h.string().uuid(),startedAt:h.iso.datetime(),endedAt:h.iso.datetime(),elapsedMs:h.number().int().nonnegative(),pausedMs:h.number().int().nonnegative()});function w$($,J,Z){let H=j0.safeParse($);if(!H.success)return{ok:!1,response:M("INVALID_PAYLOAD","Invalid payload",400,{details:H.error.flatten()})};let K=H.data,W;try{W=j2(J.courses,K.course)}catch(F){if(F instanceof B2){let O=s2(K.course);if(F.code==="unknown_course")return z2.warn("Unknown course selector",{selector:K.course}),{ok:!1,response:M("UNKNOWN_COURSE",`Unknown course: ${O}`,400)};return z2.error("Ambiguous course selector",{selector:K.course}),{ok:!1,response:M("AMBIGUOUS_COURSE_SELECTOR","Ambiguous course selector in timeback.config.json",500)}}throw F}let _=h2(J,W,Z);if(!_){let F=s2(K.course);return z2.error("Missing sensor for course",{selector:K.course}),{ok:!1,response:M("MISSING_SENSOR",`Course "${F}" has no sensor configured.`,500)}}return{ok:!0,payload:K,course:W,sensor:_}}var L0=h.object({id:E,name:E,course:M2,process:h.boolean().optional(),runId:h.string().uuid(),endedAt:h.iso.datetime(),metrics:U0,pctComplete:h.number().optional().transform(($)=>$===void 0?void 0:M0($))});function x$($,J,Z){let H=L0.safeParse($);if(!H.success)return{ok:!1,response:M("INVALID_PAYLOAD","Invalid payload",400,{details:H.error.flatten()})};let K=H.data,W;try{W=j2(J.courses,K.course)}catch(F){if(F instanceof B2){let O=s2(K.course);if(F.code==="unknown_course")return z2.warn("Unknown course selector",{selector:K.course}),{ok:!1,response:M("UNKNOWN_COURSE",`Unknown course: ${O}`,400)};return z2.error("Ambiguous course selector",{selector:K.course}),{ok:!1,response:M("AMBIGUOUS_COURSE_SELECTOR","Ambiguous course selector in timeback.config.json",500)}}throw F}let _=h2(J,W,Z);if(!_){let F=s2(K.course);return z2.error("Missing sensor for course",{selector:K.course}),{ok:!1,response:M("MISSING_SENSOR",`Course "${F}" has no sensor configured.`,500)}}return{ok:!0,payload:K,course:W,sensor:_}}import{getServiceUrlsForEnv as q$}from"@timeback/core";var v8=R("handlers:activity:attempts");async function U$($,J){let Z=[$,J].join("_");return`caliper_${await S2(Z)}`}function V0($,J){return $.find((Z)=>Z.scoreDate===J)}function k0($){let J=0;for(let Z of $){let K=Z.metadata?.attempt;if(typeof K==="number"&&K>J)J=K}return J}function q0($){let J=$.metadata;return typeof J?.attempt==="number"&&J.attempt>=1?J.attempt:1}async function M$($,J,Z,H){let K;try{K=await $.oneroster.assessmentResults.listAll({where:{status:"active","assessmentLineItem.sourcedId":J,"student.sourcedId":Z}})}catch{return v8.debug("No existing results found (line item may not exist yet)",{lineItemId:J}),1}if(K.length===0)return 1;let W=V0(K,H);if(W){let O=q0(W);return v8.debug("Retry detected, reusing attempt number",{lineItemId:J,timebackId:Z,endedAt:H,attempt:O}),O}let _=k0(K),F=_+1;return v8.debug("New attempt computed",{lineItemId:J,timebackId:Z,endedAt:H,maxAttempt:_,nextAttempt:F}),F}var j$=R("handlers:activity:completion");async function V$($){let{client:J,courseId:Z,timebackId:H,pctComplete:K,appName:W}=$;if(K!==100)return;let _=L$(Z),F=`timeback_sdk_${await S2(`mastery-completion_${Z}`)}`,O=`timeback_sdk_${await S2(`mastery-completion_${Z}_${H}`)}`;try{let x=!1;try{await J.oneroster.assessmentLineItems(F).get(),x=!0}catch{}if(!x)await J.oneroster.assessmentLineItems.create({sourcedId:F,title:`${W}: Complete`,status:"active",course:{sourcedId:_.course},componentResource:{sourcedId:_.componentResource},resultValueMin:0,resultValueMax:100,metadata:{appName:W}});let V=new Date().toISOString();await J.oneroster.assessmentResults.upsert(O,{status:"active",assessmentLineItem:{sourcedId:F},student:{sourcedId:H},score:100,scoreDate:V,scoreStatus:"fully graded",metadata:{isMasteryCompletion:!0,completedAt:V,appName:W}}),j$.debug("Created mastery completion entry",{courseId:Z,timebackId:H,lineItemId:F,resultId:O})}catch(x){let V=x instanceof Error?x.message:"Unknown error";j$.error("Failed to create mastery completion entry",{courseId:Z,timebackId:H,lineItemId:F,error:V})}}import{aggregateActivityMetrics as C0}from"@timeback/core/utils";var P2=R("handlers:activity:progress");function A0($,J){let Z=u(J),H=$.overrides?.[Z]?.metadata?.metrics,K=$.metadata?.metrics;return H?.totalLessons??K?.totalLessons}function z0($,J){let Z=$/J*100;return Math.min(100,Math.max(0,Math.round(Z)))}async function k$($){let{client:J,courseId:Z,timebackId:H,payload:K,course:W,env:_}=$;if(K.pctComplete!==void 0)return;let F=K.metrics.masteredUnits;if(typeof F!=="number"||F<=0)return;let O=A0(W,_);if(!O||O<=0){P2.debug("Skipping progress computation: totalLessons not configured",{courseId:Z});return}let x;try{x=(await J.edubridge.enrollments.list({userId:H})).find((N)=>N.course.id===Z)?.id}catch(z){let N=z instanceof Error?z.message:"Unknown error";P2.warn("Failed to fetch enrollments for progress computation",{courseId:Z,timebackId:H,error:N});return}if(!x){P2.warn("Skipping progress computation: enrollment not found for student/course",{courseId:Z,timebackId:H});return}let V=0;try{let z=await J.edubridge.analytics.getEnrollmentFacts({enrollmentId:x});V=C0(z.facts).masteredUnits}catch(z){let N=z instanceof Error?z.message:"Unknown error";P2.warn("Failed to fetch enrollment facts for progress computation",{courseId:Z,timebackId:H,enrollmentId:x,error:N});return}let A=!0;try{if((await J.edubridge.analytics.getWeeklyFacts({studentId:H,weekDate:K.endedAt})).some((I)=>{if(I.activityId!==K.id)return!1;if(I.enrollmentId&&I.enrollmentId===x)return!0;if(I.courseId&&I.courseId===Z)return!0;return!1}))A=!1}catch(z){let N=z instanceof Error?z.message:"Unknown error";P2.warn("Failed to fetch weekly facts for retry-safe progress computation",{courseId:Z,timebackId:H,enrollmentId:x,activityId:K.id,error:N}),A=!1}let C=V+(A?F:0),q=z0(C,O);return P2.debug("Computed pctComplete",{courseId:Z,timebackId:H,enrollmentId:x,historicalMasteredUnits:V,currentMasteredUnits:F,shouldIncludeCurrentMasteredUnits:A,totalMastered:C,totalLessons:O,pctComplete:q}),{pctComplete:q}}var y8=R("handlers:activity:submit"),P0={computeProgress:k$,maybeWriteCompletionEntry:V$};function C$($,J){return $.timebackId??_2({email:$.email,client:J})}async function n2($,J,Z=P0){let H=u($.env),{userInfo:K,payload:W,course:_,sensor:F,preview:O=!1,runId:x}=J,V=_.ids?.[H];if(!V)throw new W2(_,H);let A=$.getClient(),C=await C$(K,A),q=W;if(W.pctComplete===void 0){let y2=await Z.computeProgress({client:A,courseId:V,timebackId:C,payload:W,course:_,env:$.env});if(y2)q={...W,pctComplete:y2.pctComplete}}let z;if(!O){let y2=E8(F,q.course,q.id),UJ=await U$(y2,V);z=await M$(A,UJ,C,q.endedAt)}let I=q$(H).oneroster,r=F$({sensor:F,timebackId:C,email:K.email,payload:q,process:q.process,course:_,appName:$.appConfig.name,apiEnv:H,onerosterBaseUrl:I,attempt:z,runId:x}),Y2=$.hooks?.beforeActivitySend,v2=Y2?await Y2(r):r,p=v2??r;if(O||v2===null)return{success:!0,preview:!0,sensor:p.sensor,actor:p.actor,object:p.object,event:p.event};return await A.caliper.events.send(p.sensor,[p.event]),await Z.maybeWriteCompletionEntry({client:A,courseId:V,timebackId:p.timebackId,pctComplete:p.payload.pctComplete,appName:p.appName}),y8.debug("Recorded completion",{courseSelector:W.course,activityId:W.id}),{success:!0}}async function A$($,J){let Z=u($.env),{userInfo:H,payload:K,course:W,sensor:_,runId:F}=J;if(!W.ids?.[Z])throw new W2(W,Z);let x=$.getClient(),V=await C$(H,x),C=q$(Z).oneroster,q=i2({sensor:_,timebackId:V,email:H.email,payload:K,course:W,appName:$.appConfig.name,apiEnv:Z,onerosterBaseUrl:C,runId:F}),z=$.hooks?.beforeTimeSpentSend,N=z?await z(q):q,I=N??q;if(N===null){y8.debug("Hook skipped time-spent send",{activityId:K.id});return}await x.caliper.events.send(I.sensor,[I.event]),y8.debug("Sent time-spent event",{activityId:K.id,elapsedMs:K.elapsedMs})}var E2=R("handlers:activity:submit");async function T2($,J){if($.mode==="custom"){let H=await $.getEmail(J);return H?{email:H}:void 0}let Z=await $.getUser(J);return Z?{email:Z.email,timebackId:Z.id}:void 0}function r2($){return async(J)=>{let Z=await T2($.identity,J);if(!Z)return M("UNAUTHORIZED","Unauthorized",401);let H=x$(await J.json(),$.appConfig,$.env);if(!H.ok)return H.response;let{payload:K,course:W,sensor:_}=H,F={id:K.id,name:K.name,course:K.course,process:K.process,endedAt:K.endedAt,metrics:K.metrics,pctComplete:K.pctComplete};try{if((await n2({env:$.env,api:$.api,appConfig:$.appConfig,getClient:$.getClient,hooks:$.hooks},{userInfo:Z,payload:F,course:W,sensor:_,preview:!1,runId:K.runId})).preview)return P({preview:!0});return E2.debug("Submitted activity",{runId:K.runId,activityId:K.id}),new Response(null,{status:204})}catch(O){if(O instanceof d)return E2.warn("Failed to resolve Timeback user",{code:O.code}),M("USER_RESOLUTION_FAILED","Unable to resolve Timeback identity",F2(O));if(O instanceof W2)return E2.warn("Course not synced",{course:O.course,env:O.env}),M("MISSING_SYNCED_COURSE_ID",O.message,503);if(O instanceof a2)return E2.error("Invalid sensor URL",{sensor:O.sensor}),M("INVALID_SENSOR_URL",O.message,500);let x=O instanceof Error?O.message:"Unknown error";return E2.error("Failed to submit activity",{error:x}),M("INTERNAL_ERROR",x,502)}}}var R2=R("handlers:activity:heartbeat"),t2=new Map,R0=300000;function N0(){let $=Date.now();for(let[J,Z]of t2)if($-Z>R0)t2.delete(J)}function I0($){return N0(),t2.has($)}function z$($){t2.set($,Date.now())}function e2($){return async(J)=>{let Z=await T2($.identity,J);if(!Z)return M("UNAUTHORIZED","Unauthorized",401);let H=w$(await J.json(),$.appConfig,$.env);if(!H.ok)return H.response;let{payload:K,course:W,sensor:_}=H,F=new Date(K.startedAt).getTime(),O=`${K.runId}:${F}`;if(I0(O))return R2.debug("Duplicate heartbeat, skipping",{runId:K.runId,windowKey:O}),P({duplicate:!0});let x=u($.env);if(!W.ids?.[x]){let C=new W2(W,x);return R2.warn("Course not synced",{course:K.course,env:x}),M("MISSING_SYNCED_COURSE_ID",C.message,503)}let A=$.getClient();try{let C=Z.timebackId??await _2({email:Z.email,client:A}),z=T0(x).oneroster,N=i2({sensor:_,timebackId:C,email:Z.email,payload:K,course:W,appName:$.appConfig.name,apiEnv:x,onerosterBaseUrl:z,runId:K.runId}),I=$.hooks?.beforeTimeSpentSend,r=I?await I(N):N,Y2=r??N;if(r===null)return z$(O),R2.debug("Hook skipped heartbeat send",{runId:K.runId}),new Response(null,{status:204});return await A.caliper.events.send(Y2.sensor,[Y2.event]),z$(O),R2.debug("Sent heartbeat",{runId:K.runId,activityId:K.id,elapsedMs:K.elapsedMs}),new Response(null,{status:204})}catch(C){if(C instanceof d)return R2.warn("Failed to resolve Timeback user",{code:C.code}),M("USER_RESOLUTION_FAILED","Unable to resolve Timeback identity",F2(C));let q=C instanceof Error?C.message:"Unknown error";return R2.error("Failed to send heartbeat",{error:q}),M("INTERNAL_ERROR",q,502)}}}async function v$($,J,Z){if(Z.mode!=="sso")return L2.warn("SSO not configured"),P({error:"SSO not configured"},400);return await h$({req:$,env:J,clientId:Z.clientId,issuer:Z.issuer,redirectUri:Z.redirectUri,buildState:Z.buildState})}async function b0($,J,Z,H,K,W,_){try{let F=W.issuer??P$(K),O=E$(J,W.redirectUri);L2.debug("Exchanging auth code for tokens",{issuer:F,clientId:W.clientId});let x=await T$({issuer:F,clientId:W.clientId,clientSecret:W.clientSecret,code:$,redirectUri:O}),V=await R$({issuer:F,accessToken:x.access_token}),A=typeof V.identities==="string"?JSON.parse(V.identities):V.identities;L2.debug("SSO completed, resolving Timeback user",{user:{...V,identities:A}});let C=await O2({env:K,apiCredentials:_.credentials,userInfo:V,client:_.getClient()});L2.debug("Timeback user resolved",{timebackId:C.id});let q={user:C,idp:{tokens:x,userInfo:V},state:Z,req:H,redirect:$8,json:P};return W.onCallbackSuccess(q)}catch(F){let O=F instanceof Error?F:Error("Unknown error"),x=F instanceof d?F.code:"token_exchange_failed";if(L2.error("SSO callback failed",{error:O.message,errorCode:x}),W.onCallbackError)return W.onCallbackError(N$(O,x,Z,H));if(F instanceof d)return P({error:O.message},F2(F));return P({error:O.message},500)}}async function y$($,J,Z,H){if(Z.mode!=="sso")return L2.warn("SSO not configured"),P({error:"SSO not configured"},400);let{url:K,code:W,errorParam:_,state:F}=S$($);if(_)return I$(_,K,F,$,Z.onCallbackError);if(!W)return b$(F,$,Z.onCallbackError);return await b0(W,K,F,$,J,Z,H)}function J8($){let{env:J,identity:Z}=$;return(H)=>v$(H,J,Z)}function Z8($){let{env:J,identity:Z,api:H}=$;return(K)=>y$(K,J,Z,H)}function H8(){return()=>$8("/")}var f$=($)=>{return async(J)=>{return await $.getClient().powerpath.assessments.getAssessmentProgress({student:J.student,lesson:J.lesson,attempt:J.attempt})}};var g$=($)=>{return async(J)=>{return(await $.getClient().powerpath.assessments.getAttempts({student:J.student,lesson:J.lesson})).attempts.map((H)=>({attempt:H.attempt??void 0,score:H.score,startedAt:H.startedAt??void 0,completedAt:H.completedAt??void 0,scoreStatus:H.scoreStatus}))}};var d$=($)=>{return async(J)=>{let Z=$.getClient().powerpath.assessments,H=await Z.getAssessmentProgress({student:J.student,lesson:J.lesson}),K;if(H.lessonType!=="powerpath-100"&&H.finalized!==!0){try{K=await Z.finalStudentAssessmentResponse({student:J.student,lesson:J.lesson})}catch{}H=await Z.getAssessmentProgress({student:J.student,lesson:J.lesson})}let W=H.lessonType==="powerpath-100"?!0:H.finalized===!0;return{...K??{},score:H.score??0,totalQuestions:H.totalQuestions,correctQuestions:H.correctQuestions,accuracy:H.accuracy,finalized:W}}};function m$($){let J=$.metadata?.questionCount;return typeof J==="number"?J:void 0}function K8($){return{id:$.id,title:$.title,difficulty:$.difficulty,content:$.content?{rawXml:$.content.rawXml}:void 0,index:$.index,url:$.url,humanApproved:$.humanApproved,response:$.response,responses:$.responses,correct:$.correct,result:$.result,resultId:$.resultId,learningObjectives:$.learningObjectives}}function l$($,J){if(!J)return{lessonId:$,lessonType:"quiz",score:0,seenQuestions:0,finalized:!1};return{lessonId:$,lessonType:J.lessonType,attempt:J.attempt,score:J.score??0,questionCount:J.totalQuestions,seenQuestions:J.lessonType==="powerpath-100"?J.seenQuestions.length:0,finalized:J.lessonType==="powerpath-100"?!1:J.finalized}}function u$($){let J=$.questions,Z=J.filter((H)=>H.response!==void 0).map((H)=>H.id);return{questions:J.map(K8),answeredIds:Z,score:$.score??0,finalized:$.finalized,complete:$.finalized}}function h0($){if($.lessonType==="powerpath-100")return $.responseResult.isCorrect;return!1}function S0($){if($.lessonType==="powerpath-100")return $.powerpathScore;return 0}function c$($){let J=S0($);return{correct:h0($),score:J,complete:$.lessonType==="powerpath-100"&&J>=100,questionResult:$.questionResult}}function p$($,J){return Array.from(new Set($.map((Z)=>Z.ids?.[J]).filter((Z)=>Boolean(Z))))}function a$($){return String($.sourcedId??"")}var i$=($)=>{return async(J={})=>{let Z=$.getClient(),H=u($.env),K;if(J.course){let F=j2($.appConfig.courses,J.course).ids?.[H];K=F?[F]:[]}else K=p$($.appConfig.courses,H);let W=[];for(let _ of K){let F=await Z.oneroster.courses(_).components({where:{status:"active"}}),O=f8(F);for(let x of O){let V=a$(x);if(!V)continue;let A=await Z.oneroster.courses.componentResources({where:{"courseComponent.sourcedId":V,status:"active"}}),C=f8(A);for(let q of C){if(!q.sourcedId)continue;let z=q.metadata??{},N=m$(q);W.push({id:q.sourcedId,name:q.title??q.sourcedId,type:z.lessonType??"quiz",courseId:_,questionCount:N,metadata:z})}}}return W}};class X8 extends Error{name="LessonTypeMismatchError"}var s$=($)=>{return async(J)=>{let Z=$.getClient().powerpath.assessments;if(J.lessonType==="powerpath-100"){let K=await Z.getNextQuestion({student:J.student,lesson:J.lesson});return K8(K.question)}let H=await Z.getAssessmentProgress({student:J.student,lesson:J.lesson});if(H.lessonType==="powerpath-100"){if(J.lessonType!==void 0)throw new X8(`Expected quiz progress but got powerpath-100 for lesson ${J.lesson}`);let K=await Z.getNextQuestion({student:J.student,lesson:J.lesson});return K8(K.question)}return u$(H)}};var E0=R("lessons:start"),o$=($)=>{return async(J)=>{let Z=$.getClient().powerpath.assessments,H=J.lesson,K=J.student,W=await Z.getAssessmentProgress({student:K,lesson:H});if(J.forceNew){if(W.lessonType!=="powerpath-100"&&W.finalized!==!0)try{await Z.finalStudentAssessmentResponse({student:K,lesson:H})}catch{}try{await Z.createNewAttempt({student:K,lesson:H}),W=await Z.getAssessmentProgress({student:K,lesson:H})}catch(_){E0.warn("Failed to create new lesson attempt",{lessonId:H,error:_})}}else if(W.lessonType!=="powerpath-100"&&W.finalized!==!0&&(W.questions?.length??0)===0)try{await Z.createNewAttempt({student:K,lesson:H}),W=await Z.getAssessmentProgress({student:K,lesson:H})}catch{}return l$(H,W)}};var n$=($)=>{return async(J)=>{let H=await $.getClient().powerpath.assessments.updateStudentQuestionResponse({student:J.student,lesson:J.lesson,question:J.question,responses:{RESPONSE:J.response}});return c$(H)}};function m($){return{list:i$($),start:o$($),next:s$($),submit:n$($),complete:d$($),attempts:g$($),attemptDetails:f$($)}}async function a($,J){let Z=await T2($.identity,J);if(!Z)return null;if(Z.timebackId)return Z.timebackId;return await _2({email:Z.email,client:$.getClient()})}async function r$($,J){let Z=await T2($.identity,J);return Boolean(Z)}var v0=R("handlers:lessons");function c($,J){if($ instanceof d)return M("USER_RESOLUTION_FAILED","Unable to resolve Timeback identity",F2($));if($ instanceof X8)return M("LESSON_TYPE_MISMATCH",$.message,400);let Z=$ instanceof Error?$.message:"Unknown error";return v0.error(J,{error:Z}),M("INTERNAL_ERROR",Z,500)}import*as i from"zod";var y0=i.object({course:M2.optional()}).partial(),f0=i.object({lessonId:E,forceNew:i.boolean().optional()}),g0=i.object({lessonId:E,lessonType:E.optional()}),d0=i.object({lessonId:E,questionId:E,response:E}),m0=i.object({lessonId:E}),l0=i.object({lessonId:E}),u0=i.object({lessonId:E,attempt:i.number().int().positive()});async function c0($){try{let J=await $.json();if(!J||typeof J!=="object"||Array.isArray(J))return null;return J}catch{return null}}async function V2($,J){let Z=await c0($);if(!Z)return{ok:!1,response:M("INVALID_PAYLOAD","Invalid JSON body",400)};let H=J.safeParse(Z);if(!H.success)return{ok:!1,response:M("INVALID_PAYLOAD","Invalid payload",400,{details:H.error.flatten()})};return{ok:!0,payload:H.data}}async function t$($){return await V2($,y0)}async function e$($){return await V2($,f0)}async function $J($){return await V2($,g0)}async function JJ($){return await V2($,d0)}async function ZJ($){return await V2($,m0)}async function HJ($){return await V2($,l0)}async function KJ($){return await V2($,u0)}function W8($){let J=m($);return async(Z)=>{try{let H=await KJ(Z);if(!H.ok)return H.response;let K=await a($,Z);if(!K)return M("UNAUTHORIZED","Unauthorized",401);let W=await J.attemptDetails({lesson:H.payload.lessonId,attempt:H.payload.attempt,student:K});return P(W)}catch(H){return c(H,"Failed to fetch lesson attempt details")}}}function Y8($){let J=m($);return async(Z)=>{try{let H=await HJ(Z);if(!H.ok)return H.response;let K=await a($,Z);if(!K)return M("UNAUTHORIZED","Unauthorized",401);let W=await J.attempts({lesson:H.payload.lessonId,student:K});return P({attempts:W})}catch(H){return c(H,"Failed to list lesson attempts")}}}function Q8($){let J=m($);return async(Z)=>{try{let H=await ZJ(Z);if(!H.ok)return H.response;let K=await a($,Z);if(!K)return M("UNAUTHORIZED","Unauthorized",401);let W=await J.complete({lesson:H.payload.lessonId,student:K});return P(W)}catch(H){return c(H,"Failed to complete lesson")}}}function G8($){let J=m($);return async(Z)=>{try{if(!await r$($,Z))return M("UNAUTHORIZED","Unauthorized",401);let H=await t$(Z);if(!H.ok)return H.response;let K=await J.list({course:H.payload.course});return P({lessons:K})}catch(H){return c(H,"Failed to list lessons")}}}function B8($){let J=m($);return async(Z)=>{try{let H=await $J(Z);if(!H.ok)return H.response;let K=await a($,Z);if(!K)return M("UNAUTHORIZED","Unauthorized",401);let W=await J.next({lesson:H.payload.lessonId,lessonType:H.payload.lessonType,student:K});return P(W)}catch(H){return c(H,"Failed to fetch next lesson question")}}}function _8($){let J=m($);return async(Z)=>{try{let H=await e$(Z);if(!H.ok)return H.response;let K=await a($,Z);if(!K)return M("UNAUTHORIZED","Unauthorized",401);let W=await J.start({lesson:H.payload.lessonId,student:K,forceNew:H.payload.forceNew});return P(W)}catch(H){return c(H,"Failed to start lesson")}}}function F8($){let J=m($);return async(Z)=>{try{let H=await JJ(Z);if(!H.ok)return H.response;let K=await a($,Z);if(!K)return M("UNAUTHORIZED","Unauthorized",401);let W=await J.submit({lesson:H.payload.lessonId,question:H.payload.questionId,response:H.payload.response,student:K});return P(W)}catch(H){return c(H,"Failed to submit lesson answer")}}}function XJ($,J){let Z=new Map;for(let H of $){let K=H.ids?.[J];if(K)Z.set(K,H)}return Z}function WJ($,J){return $.map((Z)=>{let H=J.get(Z.course.id);return{id:Z.course.id,code:H?.courseCode??Z.course.id,name:Z.course.title}})}function YJ($){return $.map((J)=>J.metadata?.goals).find(Boolean)}function QJ($){let J=new Date(Date.UTC($.getUTCFullYear(),$.getUTCMonth(),$.getUTCDate())),Z=new Date(Date.UTC($.getUTCFullYear(),$.getUTCMonth(),$.getUTCDate(),23,59,59,999));return{start:J,end:Z}}function g8($){return Object.values($).reduce((J,Z)=>{return J+Object.values(Z).reduce((H,K)=>{return H+(K.activityMetrics?.xpEarned??0)},0)},0)}async function O8($,J,Z,H){let K=await $.edubridge.enrollments.list({userId:J.id}),W=XJ(Z.courses,H),_=WJ(K,W),F=YJ(K),{start:O,end:x}=QJ(new Date),[V,A]=await Promise.all([$.edubridge.analytics.getActivity({studentId:J.id,startDate:O.toISOString(),endDate:x.toISOString()}),$.edubridge.analytics.getActivity({studentId:J.id,startDate:"2000-01-01",endDate:x.toISOString()})]);return{id:J.id,email:J.email,name:J.name,school:J.school,grade:J.grade,courses:_.length?_:void 0,goals:F,xp:{today:g8(V.facts),all:g8(A.facts)}}}var d8=R("handlers:user");async function p0($,J){if($.mode==="custom"){let H=await $.getEmail(J);if(!H)return;return{sub:H,email:H}}let Z=await $.getUser(J);if(!Z)return;return{sub:Z.id,email:Z.email}}function a0($){if(d8.warn("Timeback user resolution failed",{code:$.code}),$.code==="timeback_user_ambiguous")return M("USER_AMBIGUOUS","Timeback user resolution ambiguous",409);if($.code==="timeback_user_not_found")return M("USER_NOT_FOUND","Timeback user not found",404);return M("USER_RESOLUTION_FAILED",$.message,502)}function D8($){return async(J)=>{try{let Z=await p0($.identity,J);if(!Z)return M("UNAUTHORIZED","Unauthorized",401);let H=u($.env),K=$.getClient();try{let W=await O2({env:$.env,apiCredentials:$.api,userInfo:Z,client:K}),_=await O8(K,W,$.appConfig,H);return P(_)}catch(W){if(W instanceof d)return a0(W);let _=W instanceof Error?W.message:"Unknown error";return d8.error("Failed to build user profile",{error:_}),M("INTERNAL_ERROR",_,502)}}catch(Z){let H=Z instanceof Error?Z.message:"Unknown error";return d8.error("Unhandled error in user handler",{error:H}),M("INTERNAL_ERROR",H,500)}}}var m8=R("handlers:user:verify");async function i0($,J){if($.mode==="custom"){let H=await $.getEmail(J);if(!H)return;return{sub:H,email:H}}let Z=await $.getUser(J);if(!Z)return;return{sub:Z.id,email:Z.email}}function w8($){return async(J)=>{try{let Z=await i0($.identity,J);if(!Z)return M("UNAUTHORIZED","Unauthorized",401);let H=$.getClient();try{let K=await O2({env:$.env,apiCredentials:$.api,userInfo:Z,client:H});return P({verified:!0,timebackId:K.id})}catch(K){if(K instanceof d){if(m8.warn("Timeback user resolution failed",{code:K.code}),K.code==="timeback_user_ambiguous")return M("USER_AMBIGUOUS","Timeback user resolution ambiguous",409);if(K.code==="timeback_user_not_found")return P({verified:!1});return M("USER_RESOLUTION_FAILED",K.message,502)}let W=K instanceof Error?K.message:"Unknown error";return m8.error("Failed to verify user",{error:W}),M("INTERNAL_ERROR",W,502)}}catch(Z){let H=Z instanceof Error?Z.message:"Unknown error";return m8.error("Unhandled error in verify handler",{error:H}),M("INTERNAL_ERROR",H,500)}}}import*as T from"zod";var s0=T.object({email:T.email(),timebackId:T.string().optional()}),o0=T.object({id:E,name:E,course:M2}),n0=T.object({totalQuestions:T.number().int().nonnegative().optional(),correctQuestions:T.number().int().nonnegative().optional(),xpEarned:T.number(),masteredUnits:T.number().int().nonnegative().optional(),pctComplete:T.number().min(0).max(100).optional()}).superRefine(o2),r0=T.object({startedAt:T.union([T.iso.datetime(),T.date()]).optional(),endedAt:T.union([T.iso.datetime(),T.date()]).optional(),activeMs:T.number().int().nonnegative().optional(),inactiveMs:T.number().int().nonnegative().optional()}),t0=T.uuid().optional(),GJ=T.object({user:s0,activity:o0,metrics:n0,time:r0.optional(),runId:t0});var BJ=R("activity:record");class _J extends Error{code="VALIDATION_ERROR";details;constructor($,J){super($);this.name="ActivityRecordValidationError",this.details=J}}class l8 extends Error{code="COURSE_ERROR";constructor($){super($);this.name="ActivityRecordCourseError"}}function e0($){let J=$.time?.endedAt?typeof $.time.endedAt==="string"?$.time.endedAt:$.time.endedAt.toISOString():new Date().toISOString();return{id:$.activity.id,name:$.activity.name,course:$.activity.course,endedAt:J,metrics:{totalQuestions:$.metrics.totalQuestions,correctQuestions:$.metrics.correctQuestions,xpEarned:$.metrics.xpEarned,masteredUnits:$.metrics.masteredUnits},pctComplete:$.metrics.pctComplete}}function $1($,J){let Z=$.time,H=Z.activeMs??0,K=Z.inactiveMs??0,W;if(Z.startedAt)W=typeof Z.startedAt==="string"?Z.startedAt:Z.startedAt.toISOString();else if(Z.activeMs!==void 0||Z.inactiveMs!==void 0){let _=new Date(J),F=H+K;W=new Date(_.getTime()-F).toISOString()}else W=J;return{id:$.activity.id,name:$.activity.name,course:$.activity.course,startedAt:W,endedAt:J,elapsedMs:H,pausedMs:K}}function J1($,J,Z){let H;try{H=j2($.courses,J)}catch(W){if(W instanceof B2)throw new l8(W.code==="unknown_course"?`Unknown course: ${JSON.stringify(J)}`:"Ambiguous course selector in timeback.config.json");throw W}let K=h2($,H,Z);if(!K)throw new l8(`Course "${JSON.stringify(J)}" has no sensor configured.`);return{course:H,sensor:K}}var Z1={recordCompletion:n2,sendTimeSpent:A$};function u8($,J=Z1){return async(Z)=>{let H=GJ.safeParse(Z);if(!H.success)throw BJ.warn("Invalid record input",{error:H.error.flatten()}),new _J("Invalid activity record input",H.error.flatten());let K=H.data,{course:W,sensor:_}=J1($.appConfig,K.activity.course,$.env),F=e0(K),O={env:$.env,api:$.api,appConfig:$.appConfig,getClient:$.getClient,hooks:$.hooks};if(await J.recordCompletion(O,{userInfo:{email:K.user.email,timebackId:K.user.timebackId},payload:F,course:W,sensor:_,preview:!1,runId:K.runId}),K.time){let x=$1(K,F.endedAt);await J.sendTimeSpent(O,{userInfo:{email:K.user.email,timebackId:K.user.timebackId},payload:x,course:W,sensor:_,runId:K.runId})}BJ.debug("Recorded activity",{activityId:K.activity.id,hasTime:!!K.time})}}var x8=R("user:verify");function c8($){return async(J)=>{x8.debug("Verifying user by email");let Z=$.getClient();try{let H=await _2({email:J,client:Z});return x8.debug("User verified",{timebackId:H}),{verified:!0,timebackId:H}}catch(H){if(H instanceof d){if(H.code==="timeback_user_not_found")return x8.debug("User not found in Timeback"),{verified:!1};throw H}let K=H instanceof Error?H.message:"Unknown error";throw x8.error("Failed to verify user",{error:K}),H}}}var p8=R("user:getProfile");function a8($){return async(J)=>{p8.debug("Building user profile by email");let Z=$.getClient(),H=u($.env);try{let K=await O2({env:$.env,apiCredentials:$.api,userInfo:{sub:J,email:J},client:Z}),W=await O8(Z,K,$.appConfig,H);return p8.debug("User profile built",{userId:W.id}),W}catch(K){if(K instanceof d)throw K;let W=K instanceof Error?K.message:"Unknown error";throw p8.error("Failed to build user profile",{error:W}),K}}}async function K1($){let{loadConfig:J}=await import("./chunk-2kfgswby.js");return await J($)}function X1($){return $.map((J)=>{if(J.grade!==void 0)return J;if(J.courseCode)return J;throw Error(`Invalid course config: missing both grade and courseCode for subject "${J.subject}"`)})}async function wJ($){if(!globalThis.process?.versions?.node&&!globalThis.Bun)throw Error("createTimeback() requires Node.js or Bun — it reads timeback.config.json from the filesystem. "+"For edge runtimes (Cloudflare Workers, Vercel Edge, etc.), use createTimebackIdentity() from '@timeback/sdk' instead.");FJ({logger:$.logger,logLevel:$.logLevel});let J=OJ($.env),Z=await K1({configPath:$.configPath});if(!Z.success)throw Error(`Failed to load timeback config: ${Z.error}`);let H=Z.config,K,W=()=>{if(!K)K=new H1({env:u(J),auth:{clientId:$.api.clientId,clientSecret:$.api.clientSecret}});return K},_=$.hooks,F=(V,A)=>DJ(V,_,A),O={env:J,identity:$.identity,appConfig:{name:H.name,sensor:H.sensor,launchUrl:H.launchUrl,courses:X1(H.courses)},api:$.api,getClient:W,hooks:_},x={env:J,identity:$.identity,api:{credentials:$.api,getClient:W}};return{config:$,handle:{activity:{heartbeat:F("activity.heartbeat",e2(O)),submit:F("activity.submit",r2(O))},identity:{signIn:F("identity.signIn",J8(x)),callback:F("identity.callback",Z8(x)),signOut:H8()},lessons:{list:F("lessons.list",G8(O)),start:F("lessons.start",_8(O)),next:F("lessons.next",B8(O)),submit:F("lessons.submit",F8(O)),complete:F("lessons.complete",Q8(O)),attempts:F("lessons.attempts",Y8(O)),attemptDetails:F("lessons.attemptDetails",W8(O))},user:{me:F("user.me",D8(O)),verify:F("user.verify",w8(O))}},activity:{record:u8({...O})},lessons:m({...O}),user:{verify:c8({...O}),getProfile:a8({...O})},get api(){return W()},close(){if(K)K.close(),K=void 0}}}import{TimebackClient as EK}from"@timeback/core";import{ApiError as yK,ForbiddenError as fK,isApiError as gK,NotFoundError as dK,UnauthorizedError as mK,ValidationError as lK}from"@timeback/core";export{Y1 as toNativeHandler,gK as isApiError,xJ as createTimebackIdentity,wJ as createTimeback,lK as ValidationError,mK as UnauthorizedError,EK as TimebackClient,W1 as ROUTES,dK as NotFoundError,fK as ForbiddenError,yK as ApiError};
1
+ import"./chunk-ae6bkfs5.js";import{a as E,b as x$,c as U$}from"./chunk-x7eeh8m2.js";import{e as h$,f as S$,g as E$,h as v$,i as y$,j as f$,k as jJ}from"./chunk-qpzke7wy.js";import{l as O1}from"./server/adapters/native.js";import{m as d,n as F2,o as O2,p as _2,q as o2,r as h2,s as UJ}from"./chunk-k1awna2q.js";import{t as wJ,u as R,v as L2,w as N$,y as I$,z as b$}from"./chunk-b49f5qfw.js";import"./chunk-3pf3cpfk.js";import{G as g8,H as q$,I as S2,J as u,K as xJ,L as P,M,N as $8,Q as F1}from"./chunk-dbcsf5tk.js";import{R as M8,U as j8}from"./chunk-1s709w5e.js";import{TimebackClient as G1}from"@timeback/core";import{getServiceUrlsForEnv as S0}from"@timeback/core";class s extends Error{statusCode;response;name="ApiError";constructor($,J,Z){super($);this.statusCode=J,this.response=Z}get minorCodes(){let $=this.response;if(!$?.imsx_CodeMinor?.imsx_codeMinorField)return[];return $.imsx_CodeMinor.imsx_codeMinorField.map((J)=>({field:J.imsx_codeMinorFieldName,value:J.imsx_codeMinorFieldValue}))}get details(){return this.response?.imsx_error_details??[]}}class J9 extends s{name="UnauthorizedError";constructor($="Unauthorized",J){super($,401,J)}}class Z9 extends s{name="ForbiddenError";constructor($="Forbidden",J){super($,403,J)}}class H9 extends s{name="NotFoundError";constructor($="Not Found",J){super($,404,J)}}class K9 extends s{name="ValidationError";constructor($="Validation Error",J){super($,422,J)}}class X9 extends s{name="InputValidationError";issues;constructor($,J){let Z={imsx_codeMajor:"failure",imsx_severity:"error",imsx_description:$,imsx_error_details:J.map((H)=>({path:H.path,message:H.message}))};super($,400,Z);this.issues=J}}function N2($,J){return new X9($,J)}function VJ($){if(!($ instanceof Error))return!1;return"statusCode"in $&&"response"in $}var kJ="BEYOND_AI",W9="LEARNWITH_AI",Y9=kJ,qJ={staging:"https://staging-beyond-timeback-api-2-idp.auth.us-east-1.amazoncognito.com/oauth2/token",production:"https://prod-beyond-timeback-api-2-idp.auth.us-east-1.amazoncognito.com/oauth2/token"},CJ={staging:"https://api.staging.alpha-1edtech.ai",production:"https://api.alpha-1edtech.ai"},AJ={staging:"https://caliper.staging.alpha-1edtech.ai",production:"https://caliper.alpha-1edtech.ai"},zJ={staging:"https://qti.alpha-1edtech.ai/api",production:"https://qti.alpha-1edtech.ai/api"},PJ={staging:"https://platform.dev.timeback.com/auth/1.0/token",production:"https://platform.timeback.com/auth/1.0/token"},TJ={staging:"https://platform.dev.timeback.com",production:"https://platform.timeback.com"},RJ={staging:"https://platform.dev.timeback.com",production:"https://platform.timeback.com"},NJ={staging:"https://platform.dev.timeback.com",production:"https://platform.timeback.com"},IJ={BEYOND_AI:{token:qJ,tokenScope:void 0,api:CJ,caliper:AJ,qti:zJ},LEARNWITH_AI:{token:PJ,tokenScope:"https://purl.imsglobal.org/spec/caliper/v1p2/scope/events.write",api:TJ,caliper:RJ,qti:NJ}},bJ={tsc:"tsc",nativePreview:"@typescript/native-preview"},U1={package:bJ.nativePreview,bin:"tsgo"},e=null,L8=!1,V8=!1;function Q9(){try{let $=process.env.DEBUG?.trim();if(!$)return!1;return $.split(",").some((J)=>J.trim().length>0)}catch{return!1}}function o8($){let Z=$.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${Z}$`)}function hJ(){if(e!==null)return;if(e=[],!Q9()){V8=!1;return}V8=!0;let $=process.env.DEBUG.trim();if($==="1"||$==="true"||$==="*"){L8=!0;return}let J=$.split(",").map((H)=>H.trim()).filter(Boolean);for(let H of J)if(H.startsWith("-"))e.push({regex:o8(H.slice(1)),exclude:!0});else e.push({regex:o8(H),exclude:!1});if(!e.some((H)=>!H.exclude)&&e.length>0)L8=!0}function SJ($){if(hJ(),!V8)return!0;if(L8){if($){for(let J of e)if(J.exclude&&J.regex.test($))return!1}return!0}if(!$)return!1;for(let J of e)if(J.exclude&&J.regex.test($))return!1;for(let J of e)if(!J.exclude&&J.regex.test($))return!0;return!1}function G9(){return typeof globalThis<"u"&&"window"in globalThis}function EJ(){if(G9())return"browser";if(typeof process<"u"&&process.env){if(process.env.CI||process.env.GITHUB_ACTIONS||process.env.GITLAB_CI||process.env.CIRCLECI||process.env.JENKINS_URL||process.env.BUILDKITE)return"ci"}return"terminal"}var k8;if(!G9())try{k8=(await import("./chunk-kkajswjx.js")).inspect}catch{}var $2={reset:"\x1B[0m",bold:"\x1B[1m",dim:"\x1B[2m",red:"\x1B[31m",yellow:"\x1B[33m",blue:"\x1B[34m",cyan:"\x1B[36m"};function vJ($){switch($){case"debug":return $2.blue;case"info":return $2.cyan;case"warn":return $2.yellow;case"error":return $2.red}}function yJ($){switch($){case"debug":return console.debug;case"info":return console.info;case"warn":return console.warn;case"error":return console.error}}function fJ($){if(k8)return k8($,{depth:null,colors:!0,breakLength:80,compact:!1});return JSON.stringify($,null,2)}var gJ=($)=>{let J=vJ($.level),Z=yJ($.level),H=$.level.toUpperCase().padEnd(5),K=$.timestamp.toISOString().replace(/\.\d{3}Z$/,""),W=`${$2.dim}[${K}]${$2.reset}`,_=`${J}${H}${$2.reset}`,F=$.scope?`${$2.bold}[${$.scope}]${$2.reset} `:"",O=`${W} ${_} ${F}${$.message}`;if($.context&&Object.keys($.context).length>0)Z(O,fJ($.context));else Z(O)},dJ={debug:"[DEBUG]",info:"[INFO]",warn:"[WARN]",error:"[ERROR]"};function mJ($){return Object.entries($).map(([J,Z])=>`${J}=${lJ(Z)}`).join(" ")}function lJ($){if(typeof $==="string")return $;if(typeof $==="number")return String($);if(typeof $==="boolean")return String($);if($===null)return"null";if($===void 0)return"undefined";return JSON.stringify($)}var uJ=($)=>{let J=[];if(J.push($.timestamp.toISOString()),J.push(dJ[$.level]),$.scope)J.push(`[${$.scope}]`);if(J.push($.message),$.context&&Object.keys($.context).length>0)J.push(mJ($.context));console.log(J.join(" "))},cJ=($)=>{let J={timestamp:$.timestamp.toISOString(),level:$.level,...$.scope&&{scope:$.scope},msg:$.message};if($.context&&Object.keys($.context).length>0)Object.assign(J,$.context);console.log(JSON.stringify(J))},pJ={debug:"color: gray",info:"color: #0ea5e9",warn:"color: #f59e0b",error:"color: #ef4444; font-weight: bold"},aJ={debug:"log",info:"info",warn:"warn",error:"error"},iJ=($)=>{let J=aJ[$.level],Z=pJ[$.level],K=`%c${$.scope?`[${$.scope}]`:""} ${$.message}`;if($.context&&Object.keys($.context).length>0)console[J](K,Z,$.context);else console[J](K,Z)},n8=["debug","info","warn","error"],r8=Symbol.for("@timeback/internal-logger/config");function sJ(){try{return process.env.TIMEBACK_INTERNAL_LOGGER==="silent"}catch{return!1}}function oJ(){let $=globalThis;return $[r8]??={},$[r8]}function nJ($){switch($){case"terminal":return gJ;case"ci":return uJ;case"production":return cJ;case"browser":return iJ;case"test":return()=>{}}}function rJ(){if(Q9())return"debug";return"info"}function tJ($,J){return J??oJ().formatter??(sJ()?()=>{}:nJ($))}function eJ($,J){return n8.indexOf($)>=n8.indexOf(J)}class g2{scope;minLevel;environment;explicitFormatter;defaultContext;constructor($={}){this.scope=$.scope,this.minLevel=$.minLevel??rJ(),this.defaultContext=$.defaultContext??{},this.environment=$.environment??EJ(),this.explicitFormatter=$.formatter}child($){let J=this.scope?`${this.scope}:${$}`:$;return new g2({scope:J,minLevel:this.minLevel,environment:this.environment,defaultContext:{...this.defaultContext},formatter:this.explicitFormatter})}withContext($){return new g2({scope:this.scope,minLevel:this.minLevel,environment:this.environment,defaultContext:{...this.defaultContext,...$},formatter:this.explicitFormatter})}debug($,J){this.log("debug",$,J)}info($,J){this.log("info",$,J)}warn($,J){this.log("warn",$,J)}error($,J){this.log("error",$,J)}log($,J,Z){if($==="debug"&&!SJ(this.scope))return;if(!eJ($,this.minLevel))return;let H={level:$,message:J,scope:this.scope,context:Z||Object.keys(this.defaultContext).length>0?{...this.defaultContext,...Z}:void 0,timestamp:new Date};tJ(this.environment,this.explicitFormatter)(H)}}function B9($={}){return new g2($)}function $5(){try{let $=typeof process>"u"?void 0:process.env.DEBUG;return $==="1"||$==="true"}catch{return!1}}class d2{config;accessToken=null;tokenExpiry=0;pendingRequest=null;fetchFn;log;constructor($){this.config=$,this.fetchFn=$.fetch??globalThis.fetch.bind(globalThis),this.log=$.logger??B9({scope:"auth",minLevel:$5()?"debug":"warn"})}async getToken(){if(this.accessToken&&Date.now()<this.tokenExpiry)return this.log.debug("Using cached token"),this.accessToken;if(this.pendingRequest)return this.log.debug("Waiting for in-flight token request"),this.pendingRequest;this.pendingRequest=this.fetchToken();try{return await this.pendingRequest}finally{this.pendingRequest=null}}async fetchToken(){this.log.debug("Fetching new access token...");let{clientId:$,clientSecret:J}=this.config.credentials,Z=btoa(`${$}:${J}`),H=performance.now(),K=await this.fetchFn(this.config.tokenUrl,{method:"POST",headers:{Authorization:`Basic ${Z}`,"Content-Type":"application/x-www-form-urlencoded"},body:this.config.scope?`grant_type=client_credentials&scope=${encodeURIComponent(this.config.scope)}`:"grant_type=client_credentials"}),W=Math.round(performance.now()-H);if(!K.ok)throw this.log.error(`Token request failed: ${K.status} ${K.statusText}`),Error(`Failed to obtain access token: ${K.status} ${K.statusText}`);let _=await K.json();return this.accessToken=_.access_token,this.tokenExpiry=Date.now()+(_.expires_in-60)*1000,this.log.debug(`Token acquired (${W}ms, expires in ${_.expires_in}s)`),this.accessToken}invalidate(){this.log.debug("Token invalidated"),this.accessToken=null,this.tokenExpiry=0}}var m2={caliper:{send:"/caliper/event",validate:"/caliper/event/validate",list:"/caliper/events",get:"/caliper/events/{id}",jobStatus:"/jobs/{id}/status"},oneroster:{rostering:"/ims/oneroster/rostering/v1p2",gradebook:"/ims/oneroster/gradebook/v1p2",resources:"/ims/oneroster/resources/v1p2"},edubridge:{base:"/edubridge"},powerpath:{base:"/powerpath"},clr:{credentials:"/ims/clr/v2p0/credentials",discovery:"/ims/clr/v2p0/discovery"},case:{base:"/ims/case/v1p1"},webhooks:{webhookList:"/webhooks/",webhookGet:"/webhooks/{id}",webhookCreate:"/webhooks/",webhookUpdate:"/webhooks/{id}",webhookDelete:"/webhooks/{id}",webhookActivate:"/webhooks/{id}/activate",webhookDeactivate:"/webhooks/{id}/deactivate",webhookFilterList:"/webhook-filters/",webhookFilterGet:"/webhook-filters/{id}",webhookFilterCreate:"/webhook-filters/",webhookFilterUpdate:"/webhook-filters/{id}",webhookFilterDelete:"/webhook-filters/{id}",webhookFiltersByWebhook:"/webhook-filters/webhook/{webhookId}"},reporting:{mcp:"/mcp/reporting",savedQueryExecute:"/reporting/saved-queries/{id}",adminGroupCheck:"/mcp/admin/users/{email}/group",adminGroupAdd:"/mcp/admin/users/{email}/group",adminGroupRemove:"/mcp/admin/users/{email}/group"}},J5={caliper:{send:"/caliper/v1p2",validate:null,list:null,get:null,jobStatus:null},oneroster:{rostering:"/rostering/1.0",gradebook:"/gradebook/1.0",resources:"/resources/1.0"},webhooks:null,reporting:null,edubridge:null,powerpath:null,clr:null,case:{base:"/case/1.1"}},_9={BEYOND_AI:m2,LEARNWITH_AI:J5};function Z5($){return"env"in $&&!("baseUrl"in $)&&!("services"in $)}function H5($){return"baseUrl"in $&&!("services"in $)}function K5($){return"services"in $}function t8($,J){let Z=$?_9[$]??m2:m2;return{caliper:J?.caliper??Z.caliper,oneroster:J?.oneroster??Z.oneroster,webhooks:J?.webhooks??Z.webhooks,reporting:J?.reporting??Z.reporting,edubridge:J?.edubridge??Z.edubridge,powerpath:J?.powerpath??Z.powerpath,clr:J?.clr??Z.clr,case:J?.case??Z.case}}class I2{platform;env;auth;timeout;_endpoints;_authUrl;_tokenScope;_pathProfiles;_tokenManagers=new Map;constructor($){if(this.timeout=$.timeout??30000,Z5($)){this.auth=$.auth;let J=$.platform??Y9,Z=$.env;this.platform=J,this.env=Z;let H=IJ[J];if(!H)throw Error(`Unknown platform: ${J}`);this._authUrl=H.token[Z],this._tokenScope=H.tokenScope??void 0,this._pathProfiles=_9[J]??m2,this._endpoints={oneroster:{baseUrl:H.api[Z],authUrl:this._authUrl},edubridge:{baseUrl:H.api[Z],authUrl:this._authUrl},powerpath:{baseUrl:H.api[Z],authUrl:this._authUrl},clr:{baseUrl:H.api[Z],authUrl:this._authUrl},case:{baseUrl:H.api[Z],authUrl:this._authUrl},caliper:{baseUrl:H.caliper[Z],authUrl:this._authUrl},webhooks:{baseUrl:H.caliper[Z],authUrl:this._authUrl},reporting:{baseUrl:H.api[Z],authUrl:this._authUrl},qti:{baseUrl:H.qti[Z],authUrl:this._authUrl}}}else if(H5($))this.auth=$.auth,this._authUrl=$.authUrl,this._pathProfiles=t8($.pathProfile,$.paths),this._endpoints={oneroster:{baseUrl:$.baseUrl,authUrl:this._authUrl},edubridge:{baseUrl:$.baseUrl,authUrl:this._authUrl},powerpath:{baseUrl:$.baseUrl,authUrl:this._authUrl},clr:{baseUrl:$.baseUrl,authUrl:this._authUrl},case:{baseUrl:$.baseUrl,authUrl:this._authUrl},caliper:{baseUrl:$.baseUrl,authUrl:this._authUrl},webhooks:{baseUrl:$.baseUrl,authUrl:this._authUrl},reporting:{baseUrl:$.baseUrl,authUrl:this._authUrl},qti:{baseUrl:$.baseUrl,authUrl:this._authUrl}};else if(K5($)){this.auth=$.auth,this._authUrl=$.authUrl,this._pathProfiles=t8($.pathProfile,$.paths),this._endpoints={};for(let[J,Z]of Object.entries($.services))if(Z)this._endpoints[J]={baseUrl:Z,authUrl:this._authUrl}}else throw Error("Invalid provider configuration");for(let J of Object.keys(this._pathProfiles))if(this._pathProfiles[J]===null)delete this._endpoints[J]}getEndpoint($){let J=this._endpoints[$];if(!J){let Z=$;if(Z in this._pathProfiles&&this._pathProfiles[Z]===null)throw Error(`Service "${$}" is not supported on ${this.platform??"this"} platform.`);throw Error(`Service "${$}" is not configured in this provider`)}return J}hasService($){return $ in this._endpoints}getAvailableServices(){return Object.keys(this._endpoints)}getTokenUrl(){return this._authUrl}getEndpointWithPaths($){let J=this.getEndpoint($),Z=this.getServicePaths($);return{...J,paths:Z}}getPaths(){return this._pathProfiles}getServicePaths($){let J=this._pathProfiles[$];if(!J)throw Error(`Service "${$}" is not supported on ${this.platform??"this"} platform.`);return J}hasServiceSupport($){return this._pathProfiles[$]!==null}getTokenProvider($){let J=this.getEndpoint($),{authUrl:Z}=J;if(!Z)return;if(!this.auth)throw Error(`Service "${$}" requires authentication but no credentials were provided`);let H=this._tokenManagers.get(Z);if(!H)H=new d2({tokenUrl:Z,credentials:{clientId:this.auth.clientId,clientSecret:this.auth.clientSecret},scope:this._tokenScope}),this._tokenManagers.set(Z,H);return H}async checkAuth(){if(!this._authUrl||!this.auth)throw Error("No auth configured on this provider");let $=Date.now(),J=this._tokenManagers.get(this._authUrl);if(!J)J=new d2({tokenUrl:this._authUrl,credentials:{clientId:this.auth.clientId,clientSecret:this.auth.clientSecret},scope:this._tokenScope}),this._tokenManagers.set(this._authUrl,J);try{return await J.getToken(),{ok:!0,latencyMs:Date.now()-$,checks:{tokenAcquisition:!0}}}catch(Z){return{ok:!1,latencyMs:Date.now()-$,error:Z instanceof Error?Z.message:String(Z),checks:{tokenAcquisition:!1}}}}invalidateTokens(){for(let $ of this._tokenManagers.values())$.invalidate?.();this._tokenManagers.clear()}}function b($){try{if(typeof process>"u")return;if(typeof $==="string")return process.env[$];for(let J of $){let Z=process.env[J];if(Z!==void 0)return Z}return}catch{return}}function D2(){let $=b("DEBUG");return $==="1"||$==="true"}function X5(){return Math.random().toString(16).slice(2,10)}function q8($){return B9({scope:$,minLevel:D2()?"debug":"warn"})}var l2={defaultPlatform:Y9,templates:{BEYOND_AI:{staging:{platform:"BEYOND_AI",env:"staging"},production:{platform:"BEYOND_AI",env:"production"}},LEARNWITH_AI:{staging:{platform:"LEARNWITH_AI",env:"staging"},production:{platform:"LEARNWITH_AI",env:"production"}}}};function W5($){if(typeof $==="string")return $;if($.length===0)throw Error(`Missing env var key: ${$}`);return $[0]}function w2($){return W5($)}function F9($){if($!=="staging"&&$!=="production")throw Error(`Invalid env "${$}": must be "staging" or "production"`);return $}function O9($,J){let Z=$?.clientId??b(J.clientId),H=$?.clientSecret??b(J.clientSecret);if(!Z)throw Error(`Missing clientId: provide in config or set ${w2(J.clientId)}`);if(!H)throw Error(`Missing clientSecret: provide in config or set ${w2(J.clientSecret)}`);return{clientId:Z,clientSecret:H}}function Y5($,J,Z){if(!Z)return;return O9($,J)}function Q5($){let J=b($.baseUrl),Z=b($.authUrl),H=b($.clientId),K=b($.clientSecret);if(J===void 0&&H===void 0)return`Missing env: provide in config or set ${w2($.env??$.baseUrl)}`;let W=[];if(J===void 0)W.push(w2($.env??$.baseUrl));if(J!==void 0&&Z===void 0)W.push(w2($.authUrl));if(H===void 0)W.push(w2($.clientId));if(K===void 0)W.push(w2($.clientSecret));return`Missing environment variables: ${W.join(", ")}`}var G5={name:"transport",matches($){return"transport"in $&&!!$.transport},resolve($){return{mode:"transport",transport:$.transport}}},B5={name:"provider",matches($){return"provider"in $&&!!$.provider},resolve($){return{mode:"provider",provider:$.provider}}},_5={name:"env-config",matches($){return"env"in $},resolve($,J,Z){let H=$,K=F9(H.env),W=O9(H.auth,J),_=H.platform??Z.defaultPlatform,F=Z.templates[_];if(!F){let x=Object.keys(Z.templates).join(", ");throw Error(`Unknown platform "${_}": available platforms are ${x}`)}let O=F[K];if(!O){let x=Object.keys(F).join(", ");throw Error(`Unknown env "${K}" for platform "${_}": available environments are ${x}`)}return{mode:"provider",provider:new I2({platform:O.platform,env:O.env,auth:W,timeout:H.timeout})}}},F5={name:"explicit-config",matches($){return"baseUrl"in $},resolve($,J){let Z=$,H=Z.authUrl??Z.auth?.authUrl,K=!!H,W=Y5(Z.auth,J,K);return{mode:"provider",provider:new I2({baseUrl:Z.baseUrl,authUrl:H,auth:W,timeout:Z.timeout,pathProfile:Z.pathProfile,paths:Z.paths})}}},O5={name:"env-fallback-platform",matches($,J){if(Object.keys($).length>0)return!1;let Z=J.env?b(J.env):void 0,H=b(J.clientId),K=b(J.clientSecret);return Z!==void 0&&H!==void 0&&K!==void 0},resolve($,J,Z){let H=F9(b(J.env)),K=b(J.clientId),W=b(J.clientSecret),_=Z.defaultPlatform,F=Z.templates[_]?.[H];if(!F)throw Error(`Unknown env "${H}" for platform "${_}"`);return{mode:"provider",provider:new I2({platform:F.platform,env:F.env,auth:{clientId:K,clientSecret:W}})}}},D5={name:"env-fallback-explicit",matches($,J){if(Object.keys($).length>0)return!1;let Z=b(J.baseUrl),H=b(J.authUrl),K=b(J.clientId),W=b(J.clientSecret);return Z!==void 0&&H!==void 0&&K!==void 0&&W!==void 0},resolve($,J){let Z=b(J.baseUrl),H=b(J.authUrl),K=b(J.clientId),W=b(J.clientSecret);return{mode:"provider",provider:new I2({baseUrl:Z,authUrl:H,auth:{clientId:K,clientSecret:W}})}}},w5={name:"token-provider",matches($){return"tokenProvider"in $},resolve(){throw Error("TokenProvider mode is not supported with provider pattern. Use { provider: TimebackProvider } or { env, auth } instead.")}},x5=[G5,B5,_5,w5,F5,O5,D5];function D9($,J,Z=l2){for(let H of x5)if(H.matches($,J))return H.resolve($,J,Z);throw Error(Q5(J))}var U8=3,U5=[429,503],e8=1000;class C8{config;log;constructor($){let{config:J,logger:Z}=$,H=J.fetch??globalThis.fetch.bind(globalThis),K;if("tokenProvider"in J&&J.tokenProvider)K=J.tokenProvider;else if("auth"in J&&J.auth)K=new d2({tokenUrl:J.auth.authUrl,credentials:{clientId:J.auth.clientId,clientSecret:J.auth.clientSecret},fetch:H});let W=J.baseUrl.endsWith("/")?J.baseUrl:`${J.baseUrl}/`;this.config={baseUrl:W,timeout:J.timeout??30000,fetch:H,tokenProvider:K},this.log=Z.child("http")}get baseUrl(){return this.config.baseUrl}async request($,J={}){let Z=await this.requestRaw($,J);return this.handleResponse(Z)}async exists($,J={}){try{return await this.requestRaw($,J),!0}catch(Z){if(VJ(Z)&&Z.statusCode===404)return!1;throw Z}}async requestRaw($,J={}){let{method:Z="GET",params:H,body:K,headers:W={}}=J,_=this.buildUrl($,H),F=J.requestId??X5(),x=Date.now()+this.config.timeout;for(let V=0;V<U8;V++){let A=x-Date.now();if(A<=0)throw this.log.error("Request timeout before attempt",D2()?{requestId:F,path:$}:{path:$}),new s("Request timeout",408);let C=await this.getAccessToken(),q=V===U8-1,z=performance.now();this.log.debug(`→ ${Z} ${_}`,{requestId:F,attempt:V>0?V+1:void 0});let N={"Content-Type":"application/json",Accept:"application/json","X-Request-ID":F,...W};if(C)N.Authorization=`Bearer ${C}`;let I=await this.config.fetch(_,{method:Z,headers:N,body:K?JSON.stringify(K):void 0,signal:AbortSignal.timeout(Math.min(A,this.config.timeout))}),r=Math.round(performance.now()-z);if(this.log.debug(`← ${I.status} ${I.statusText} (${r}ms)`,{requestId:F}),U5.includes(I.status)&&!q){let v2=I.headers.get("Retry-After"),p=this.parseRetryAfter(v2,V),s8=x-Date.now();if(p>=s8)throw this.log.error("Request timeout during retry backoff",D2()?{requestId:F,path:$}:{path:$}),new s("Request timeout",408);this.log.warn(`Retrying in ${p}ms (attempt ${V+1}/${U8})`,{...D2()&&{requestId:F},status:I.status}),await this.sleep(p);continue}if(!I.ok)return this.handleErrorResponse(I,F);return I}throw this.log.error("Max retries exceeded",D2()?{requestId:F,path:$}:{path:$}),new s("Max retries exceeded")}getAccessToken(){if(!this.config.tokenProvider)return Promise.resolve(void 0);return this.config.tokenProvider.getToken()}buildUrl($,J){if(/^[a-z][a-z0-9+.-]*:/i.test($))throw Error(`Absolute URLs are not allowed in path: ${$}. Use relative paths only.`);let Z=$.startsWith("/")?$.slice(1):$,H=new URL(Z,this.config.baseUrl);if(J){for(let[K,W]of Object.entries(J))if(W!==void 0)H.searchParams.set(K,String(W))}return H.toString()}async handleResponse($){if(!$.ok)await this.handleErrorResponse($);if($.status===204)return;if($.headers.get("content-length")==="0")return;return this.parseJsonResponse($)}async parseJsonResponse($){let J=await $.text();if(!J||J.trim()==="")return;try{return JSON.parse(J)}catch(Z){let H=J.length>200?J.slice(0,200)+"...":J,K=Z instanceof Error?Z.message:String(Z),W=$.url||"unknown";throw this.log.error("Failed to parse JSON response",{url:W,status:$.status,contentType:$.headers.get("content-type"),bodyPreview:H,error:K}),new s(`Invalid JSON response from ${W}`,$.status,{parseError:K,body:H})}}async handleErrorResponse($,J){let Z,H=await $.text().catch(()=>"");if(H)try{Z=JSON.parse(H)}catch(W){let _=W instanceof Error?W.message:"Unknown parse error";Z={rawBody:H.slice(0,500),parseError:_},this.log.warn("Failed to parse error response as JSON",{...D2()&&{requestId:J},url:$.url,status:$.status,parseError:_,bodyPreview:H.slice(0,200)})}let K=this.extractErrorMessage(Z,$.statusText);if($.status!==404)this.log.error(`Request failed: ${$.status} ${K}`,D2()?{requestId:J}:void 0);switch($.status){case 401:throw this.config.tokenProvider?.invalidate?.(),new J9(K,Z);case 403:throw new Z9(K,Z);case 404:throw new H9(K,Z);case 422:throw new K9(K,Z);default:throw new s(K,$.status,Z)}}extractErrorMessage($,J){if(typeof $==="object"&&$!==null){let Z=$;if(typeof Z.message==="string")return Z.message;if(typeof Z.error==="string")return Z.error;if(typeof Z.imsx_description==="string")return Z.imsx_description}return J}sleep($){return new Promise((J)=>{setTimeout(J,$)})}parseRetryAfter($,J){if(!$)return e8*Math.pow(2,J);let Z=parseInt($,10);if(!isNaN(Z))return Z*1000;let H=Date.parse($);if(!isNaN(H)){let K=H-Date.now();return Math.max(0,K)}return e8*Math.pow(2,J)}}function M5($){if($ instanceof Date)return $.toISOString();if(typeof $==="boolean")return $?"true":"false";if(typeof $==="number")return String($);return $.replaceAll("'","''")}function t($){let J=M5($);return typeof $==="string"||$ instanceof Date?`'${J}'`:J}function j5($,J){if(typeof J==="string"||typeof J==="number"||typeof J==="boolean"||J instanceof Date)return[`${$}=${t(J)}`];if(typeof J==="object"&&J!==null){let Z=J,H=[];if(Z.ne!==void 0)H.push(`${$}!=${t(Z.ne)}`);if(Z.gt!==void 0)H.push(`${$}>${t(Z.gt)}`);if(Z.gte!==void 0)H.push(`${$}>=${t(Z.gte)}`);if(Z.lt!==void 0)H.push(`${$}<${t(Z.lt)}`);if(Z.lte!==void 0)H.push(`${$}<=${t(Z.lte)}`);if(Z.contains!==void 0)H.push(`${$}~${t(Z.contains)}`);if(Z.in!==void 0&&Z.in.length>0){let K=Z.in.map((_)=>`${$}=${t(_)}`),W=K.join(" OR ");H.push(K.length>1?`(${W})`:W)}if(Z.notIn!==void 0&&Z.notIn.length>0){let K=Z.notIn.map((W)=>`${$}!=${t(W)}`);H.push(K.join(" AND "))}return H}return[]}function L5($){return"OR"in $&&Array.isArray($.OR)}function w9($){if(L5($)){let Z=$.OR.map((H)=>w9(H)).filter((H)=>H!==void 0);return Z.length>0?Z.join(" OR "):void 0}let J=[];for(let[Z,H]of Object.entries($))if(H!==void 0)J.push(...j5(Z,H));return J.length>0?J.join(" AND "):void 0}var $9=100,V5=1e4;class A8{fetcher;path;params;max;unwrapKey;log;transform;paginationStyle;constructor($){this.fetcher=$.fetcher,this.path=$.path,this.params=$.params??{},this.max=$.max,this.unwrapKey=$.unwrapKey,this.log=$.logger?.child("pagination")??q8("pagination"),this.transform=$.transform,this.paginationStyle=$.paginationStyle??"offset"}buildRequestParams($,J){let{where:Z,fields:H,offset:K,limit:W,..._}=this.params,F={..._,filter:Z?w9(Z):void 0,fields:H?.join(","),limit:$};if(this.paginationStyle==="page"){let O=Math.floor(J/$)+1;return{...F,page:O}}return{...F,offset:J}}extractItems($,J){let Z;if(this.unwrapKey)Z=$[this.unwrapKey]??[];else Z=$;return this.validateItems(Z,J)}validateItems($,J){if($===null||$===void 0)return this.log.warn(`Page ${J}: response data is ${$}, treating as empty`),[];if(!Array.isArray($))throw Error(`Expected array for page ${J}, got ${typeof $}. `+(this.unwrapKey?`Check unwrapKey '${this.unwrapKey}' is correct.`:""));return $}hasMorePages($,J,Z,H){if(J===0)return!1;let K=$.hasMore,W=$.total!==void 0&&Z+J<$.total;return K||W||J===H&&$.total===void 0}async*[Symbol.asyncIterator](){let $=this.params.offset??0,J=this.params.limit??$9,Z=!0,H=1,K=0;while(Z){this.log.debug(`Fetching page ${H} (offset: ${$}, limit: ${J})`);let W=await this.fetcher(this.path,{params:this.buildRequestParams(J,$)}),_=this.extractItems(W.data,H);this.log.debug(`Page ${H}: ${_.length} items`);for(let F of _)if(yield this.transform?this.transform(F):F,K++,this.max!==void 0&&K>=this.max){this.log.debug(`Pagination complete: reached max of ${this.max} items`);return}Z=this.hasMorePages(W,_.length,$,J),$+=_.length,H++}this.log.debug(`Pagination complete: ${K} total items`)}async toArray($={}){let J=$.maxItems??V5,Z=[];for await(let H of this){if(Z.length>=J)throw Error(`toArray() exceeded maxItems limit of ${J}. Use 'for await...of' to stream large datasets, or increase maxItems.`);Z.push(H)}return Z}async firstPage(){let $=this.params.limit??$9,J=this.params.offset??0,Z=await this.fetcher(this.path,{params:this.buildRequestParams($,J)}),H=this.extractItems(Z.data,1),K=this.transform?H.map(this.transform):H,W=this.hasMorePages(Z,K.length,J,$);return this.log.debug(`First page: ${K.length} items, total: ${Z.total}, hasMore: ${W}`),{data:K,hasMore:W,total:Z.total,nextOffset:W?J+K.length:void 0}}}function f2($,J){return{path:$,message:J}}function o($,J,Z){let H=$.safeParse(J);if(H.success)return H.data;let K=H.error.issues.map((W)=>({path:W.path.join(".")||"(root)",message:W.message}));throw N2(`Invalid ${Z} data`,K)}function u2($,J){if(typeof $!=="string"||$.trim()==="")throw N2(`Invalid ${J}`,[f2(J,"Must be a non-empty string")])}function z8($){if(!$)return;let J=[];if($.limit!==void 0){if(!Number.isInteger($.limit)||$.limit<=0)J.push(f2("limit","Must be a positive integer"))}if($.offset!==void 0){if(!Number.isInteger($.offset)||$.offset<0)J.push(f2("offset","Must be a non-negative integer"))}if($.max!==void 0){if(!Number.isInteger($.max)||$.max<=0)J.push(f2("max","Must be a positive integer"))}if(J.length>0)throw N2("Invalid list parameters",J)}var x9={baseUrl:["TIMEBACK_API_BASE_URL","TIMEBACK_BASE_URL","CALIPER_BASE_URL"],authUrl:["TIMEBACK_API_AUTH_URL","TIMEBACK_AUTH_URL","CALIPER_TOKEN_URL"],clientId:["TIMEBACK_API_CLIENT_ID","TIMEBACK_CLIENT_ID","CALIPER_CLIENT_ID"],clientSecret:["TIMEBACK_API_CLIENT_SECRET","TIMEBACK_CLIENT_SECRET","CALIPER_CLIENT_SECRET"]},k2="http://purl.imsglobal.org/ctx/caliper/v1p2",U9="QUESTION_RESULT";import{z as j}from"zod/v4";import{z as Q}from"zod/v4";import{z as Z2}from"zod/v4";import{z as U}from"zod/v4";import{z as w}from"zod/v4";import{z as k}from"zod/v4";import{z as D}from"zod/v4";import{z as g}from"zod/v4";import{z as G}from"zod/v4";import{z as B}from"zod/v4";import{z as Y}from"zod/v4";import{z as A2}from"zod/v4";var S=q8("caliper");class C9 extends C8{paths;constructor($){super({config:$,logger:S});this.paths=$.paths}async requestPaginated($,J={}){let Z=await this.request($,J),{events:H,pagination:K}=Z,_=(J.params?.offset??0)+H.length<K.total;return{data:H,hasMore:_,total:K.total}}}class A9 extends A8{constructor($,J,Z={}){z8(Z);let{max:H,...K}=Z;super({fetcher:(W,_)=>$.requestPaginated(W,_),path:J,params:K,max:H,logger:S})}}function P8($){let J=$.id??`urn:uuid:${crypto.randomUUID()}`,Z=$.metricsId??`urn:uuid:${crypto.randomUUID()}`;return{"@context":k2,id:J,type:"ActivityEvent",action:"Completed",actor:$.actor,object:$.object,eventTime:$.eventTime??new Date().toISOString(),profile:"TimebackProfile",generated:{id:Z,type:"TimebackActivityMetricsCollection",items:$.metrics,...$.attempt===void 0?{}:{attempt:$.attempt},...$.generatedExtensions?{extensions:$.generatedExtensions}:{}},extensions:$.extensions,...$.edApp===void 0?{}:{edApp:$.edApp},...$.session===void 0?{}:{session:$.session}}}function T8($){let J=$.id??`urn:uuid:${crypto.randomUUID()}`,Z=$.metricsId??`urn:uuid:${crypto.randomUUID()}`;return{"@context":k2,id:J,type:"TimeSpentEvent",action:"SpentTime",actor:$.actor,object:$.object,eventTime:$.eventTime??new Date().toISOString(),profile:"TimebackProfile",generated:{id:Z,type:"TimebackTimeSpentMetricsCollection",items:$.metrics},extensions:$.extensions,...$.edApp===void 0?{}:{edApp:$.edApp},...$.session===void 0?{}:{session:$.session}}}function k5($){return{"@context":k2,id:$.id??`urn:uuid:${crypto.randomUUID()}`,type:"AssessmentItemEvent",action:"Started",profile:"AssessmentProfile",actor:$.actor,object:{...$.object,type:"AssessmentItem"},eventTime:$.eventTime??new Date().toISOString(),edApp:$.edApp,...$.session===void 0?{}:{session:$.session},...$.extensions===void 0?{}:{extensions:$.extensions}}}function q5($){return{"@context":k2,id:$.id??`urn:uuid:${crypto.randomUUID()}`,type:"AssessmentItemEvent",action:"Completed",profile:"AssessmentProfile",actor:$.actor,object:{...$.object,type:"AssessmentItem"},eventTime:$.eventTime??new Date().toISOString(),edApp:$.edApp,...$.generated===void 0?{}:{generated:{...$.generated,type:"Response"}},...$.session===void 0?{}:{session:$.session},...$.extensions===void 0?{}:{extensions:$.extensions}}}function C5($){let{id:J,...Z}=$.generated;return{"@context":k2,id:$.id??`urn:uuid:${crypto.randomUUID()}`,type:"GradeEvent",action:"Graded",profile:"GradingProfile",actor:$.actor,object:$.object,eventTime:$.eventTime??new Date().toISOString(),edApp:$.edApp,generated:{...Z,id:J??`urn:uuid:${crypto.randomUUID()}`,type:"Score",scoreType:U9},...$.session===void 0?{}:{session:$.session},...$.extensions===void 0?{}:{extensions:$.extensions}}}var A5="http://purl.imsglobal.org/ctx/caliper/v1p2",z5="urn:tag:auto-attach",Q2={PERSON:"Person",ASSIGNABLE_DIGITAL_RESOURCE:"AssignableDigitalResource",ACTIVITY_METRIC:"ActivityMetric",TIME_SPENT_METRIC:"TimeSpentMetric",ACTIVITY_METRICS_COLLECTION:"ActivityMetricsCollection",TIME_SPENT_METRICS_COLLECTION:"TimeSpentMetricsCollection",COURSE_OFFERING:"CourseOffering",SOFTWARE_APPLICATION:"SoftwareApplication"},P5=new Set(["ActivityEvent","TimeSpentEvent","AssignableEvent","ViewEvent"]);class z9{transformEnvelope($){let{data:J}=$;if(!Array.isArray(J))return $;let Z=J.map((H)=>x2(H)?T5(H):H);return{...$,data:Z}}}function T5($){let J={...$};if(!("@context"in J))J["@context"]=A5;if(J.profile==="TimebackProfile")J.profile="AggregationProfile";if(x2(J.actor)&&J.actor.type==="TimebackUser")J.actor=R5(J.actor);if(x2(J.object))J.object=N5(J.object,J.type);if(x2(J.generated)){let Z=J.type;if(Z==="ActivityEvent")J.generated=I5(J.generated);else if(Z==="TimeSpentEvent")J.generated=b5(J.generated)}if(!J.session)J.session=z5;return J}function R5($){return{type:Q2.PERSON,id:$.id}}function N5($,J){if(!($.type==="TimebackActivityContext"&&J!==void 0&&P5.has(J)))return{...$};let H={type:Q2.ASSIGNABLE_DIGITAL_RESOURCE,id:$.id};if($.name)H.name=$.name;if(x2($.course)){let K={type:Q2.COURSE_OFFERING,id:$.course.id};if($.course.name)K.name=$.course.name;H.isPartOf=K}if(x2($.app))H.extensions={app:{name:$.app.name,type:$.app.type??Q2.SOFTWARE_APPLICATION}};return H}function P9($,J,Z,H){let W={id:typeof $?.id==="string"?$.id:`urn:uuid:${crypto.randomUUID()}`,type:J};if(Array.isArray($.items))W.items=$.items.map((_)=>{if(!x2(_))return _;let F=typeof _.type==="string"?_.type:"",O=F?F[0].toUpperCase()+F.slice(1):H;return{id:`urn:uuid:${crypto.randomUUID()}`,type:Z,metricType:O,metricValue:_.value}});for(let[_,F]of Object.entries($))if(_!=="id"&&_!=="type"&&_!=="items")W[_]=F;return W}function I5($){return P9($,Q2.ACTIVITY_METRICS_COLLECTION,Q2.ACTIVITY_METRIC,"")}function b5($){return P9($,Q2.TIME_SPENT_METRICS_COLLECTION,Q2.TIME_SPENT_METRIC,"Active")}function x2($){return typeof $==="object"&&$!==null&&!Array.isArray($)}function h5($,J=l2){return D9($,x9,J)}var S5=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/,y=j.string().min(1).regex(S5,"must be a valid ISO 8601 datetime"),C2=j.string().min(1).regex(/^\d{4}-\d{2}-\d{2}$/,"must be a valid ISO 8601 date (YYYY-MM-DD)"),X=j.string().trim().min(1),X2=j.enum(["Reading","Language","Vocabulary","Social Studies","Writing","Science","FastMath","Math","None","Other"]).meta({id:"TimebackSubject",description:"Subject area"}),E5=j.union([j.literal(-1),j.literal(0),j.literal(1),j.literal(2),j.literal(3),j.literal(4),j.literal(5),j.literal(6),j.literal(7),j.literal(8),j.literal(9),j.literal(10),j.literal(11),j.literal(12),j.literal(13)]),v5=j.string().transform(($,J)=>{let Z=$.toLowerCase().trim().replaceAll("_"," ");if(Z==="")return J.addIssue({code:"custom",message:"must be a valid Timeback grade"}),j.NEVER;let H=Z.replace(/\bgrade\b/g,"").replace(/(\d+)(st|nd|rd|th)\b/g,"$1").trim();if(H==="")return J.addIssue({code:"custom",message:"must be a valid Timeback grade"}),j.NEVER;if(H==="pre-k"||H==="pk")return-1;if(H==="k")return 0;if(H==="middle school")return 7;let W=H.replace(/\s+/g,"").replace(/^0+/,"")||"0",_=Number(W);if(!Number.isInteger(_))return J.addIssue({code:"custom",message:"must be a valid Timeback grade"}),j.NEVER;return _}),n=j.union([j.number(),v5]).pipe(E5).meta({id:"TimebackGrade",description:"Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"}),y5=j.enum(["exempt","fully graded","not submitted","partially graded","submitted"]),f5=j.enum(["department","school","district","local","state","national"]),T9=j.enum(["administrator","aide","guardian","parent","proctor","relative","student","teacher"]),g5=j.enum(["administrator","proctor","student","teacher"]),d5=j.enum(["qti","text","audio","video","interactive","visual","course-material","assessment-bank"]),m5=j.enum(["qti-test","qti-question","qti-stimulus","qti-test-bank"]),l5=j.enum(["unit","course","resource-collection"]),u5=j.enum(["choice","order","associate","match","hotspot","hottext","select-point","graphic-order","graphic-associate","graphic-gap-match","text-entry","extended-text","inline-choice","upload","slider","drawing","media","custom"]),c5=j.enum(["easy","medium","hard"]),R9=j.array(j.object({source:j.string(),learningObjectiveIds:j.array(j.string())})),N9=j.object({consecutive_failures:j.number().int().min(1).optional(),stagnation_limit:j.number().int().min(1).optional()}).optional(),p5=j.enum(["powerpath-100","quiz","test-out","placement","unit-test","alpha-read-article"]).nullable(),E1=j.object({imsx_codeMajor:j.enum(["failure","success"]),imsx_severity:j.enum(["error","warning","status"]),imsx_description:j.string(),imsx_CodeMinor:j.object({imsx_codeMinorField:j.array(j.object({imsx_codeMinorFieldName:j.string(),imsx_codeMinorFieldValue:j.string()}))}).optional()}),a5=Q.union([Q.url(),Q.string().regex(/^urn:/,"Must be a URL or URN")]),U2=Q.object({id:Q.url(),type:Q.literal("TimebackUser"),email:Q.string()}),R8=Q.object({id:Q.url(),type:Q.literal("TimebackActivityContext"),subject:X2,app:Q.object({name:Q.string()}),activity:Q.object({id:Q.url().optional(),name:Q.string()}).strict().optional(),course:Q.object({id:Q.url().optional(),name:Q.string().optional()}).strict(),process:Q.boolean().optional()}),I9=Q.object({"@context":Q.literal("http://purl.imsglobal.org/ctx/caliper/v1p2"),id:Q.string().regex(/^urn:uuid:/,"Event id must start with urn:uuid:"),type:Q.string(),eventTime:y,profile:Q.literal("TimebackProfile"),actor:U2,action:Q.string(),object:R8,edApp:Q.object({id:Q.string(),name:Q.string().optional()}).optional()}),b9=Q.object({type:Q.enum(["totalQuestions","correctQuestions","xpEarned","masteredUnits"]),value:Q.number()}),i5=Q.object({id:Q.url(),type:Q.literal("TimebackActivityMetricsCollection"),attempt:Q.number().optional(),items:Q.array(b9),extensions:Q.record(Q.string(),Q.unknown()).optional()}),s5=I9.extend({type:Q.literal("ActivityEvent"),action:Q.literal("Completed"),generated:i5}),h9=Q.object({type:Q.enum(["active","inactive","waste","unknown","anti-pattern"]),value:Q.number(),subType:Q.string().optional()}),o5=Q.object({id:Q.url(),type:Q.literal("TimebackTimeSpentMetricsCollection"),items:Q.array(h9)}),n5=I9.extend({type:Q.literal("TimeSpentEvent"),action:Q.literal("SpentTime"),generated:o5}),r5=Q.object({actor:U2,object:R8,metrics:Q.array(b9).min(1,"metrics must contain at least one metric"),eventTime:y.optional(),metricsId:Q.string().optional(),id:Q.string().optional(),extensions:Q.record(Q.string(),Q.unknown()).optional(),edApp:Q.union([Q.string(),Q.record(Q.string(),Q.unknown())]).optional(),session:Q.union([Q.string(),Q.record(Q.string(),Q.unknown())]).optional(),attempt:Q.number().int().min(1).optional(),generatedExtensions:Q.object({pctCompleteApp:Q.number().optional()}).loose().optional()}).strict(),t5=Q.object({actor:U2,object:R8,metrics:Q.array(h9).min(1,"metrics must contain at least one metric"),eventTime:y.optional(),metricsId:Q.string().optional(),id:Q.string().optional(),extensions:Q.record(Q.string(),Q.unknown()).optional(),edApp:Q.union([Q.string(),Q.record(Q.string(),Q.unknown())]).optional(),session:Q.union([Q.string(),Q.record(Q.string(),Q.unknown())]).optional()}).strict(),e5=Q.union([s5,n5]),v1=Q.object({sensor:Q.string(),sendTime:y,dataVersion:Q.literal("http://purl.imsglobal.org/ctx/caliper/v1p2"),data:Q.array(e5)}),$Z=Q.enum(["AnnotationProfile","AssessmentProfile","ToolUseProfile","GeneralProfile","FeedbackProfile","MediaProfile","SurveyProfile","ResourceManagementProfile","ForumProfile","AssignableProfile","GradingProfile","ReadingProfile","SessionProfile","SearchProfile","ToolLaunchProfile","TimebackProfile"]),l=Q.union([Q.string(),Q.record(Q.string(),Q.unknown())]),c2=Q.object({id:a5,type:Q.string(),name:Q.string().optional(),extensions:Q.record(Q.string(),Q.unknown()).optional()}).strict(),S9=Q.object({"@context":Q.string().optional(),id:Q.string().regex(/^urn:uuid:/,"Event id must start with urn:uuid:"),type:Q.string(),actor:Q.union([Q.string(),c2,U2]),action:Q.string(),object:l,eventTime:y,profile:$Z,edApp:l.optional(),generated:l.optional(),target:l.optional(),referrer:l.optional(),group:l.optional(),membership:l.optional(),session:l.optional(),federatedSession:l.optional(),extensions:Q.record(Q.string(),Q.unknown()).optional()}).strict(),M9=Q.object({sensor:X,sendTime:y,dataVersion:Q.literal("http://purl.imsglobal.org/ctx/caliper/v1p2"),data:Q.array(S9).min(1,"data must contain at least one event")}),JZ=Q.object({sensor:X,events:Q.array(S9).min(1,"events must contain at least one event")}),j9=Q.object({limit:Q.number().int().positive().optional(),offset:Q.number().int().min(0).optional(),sensor:X.optional(),startDate:y.optional(),endDate:y.optional(),actorId:X.optional(),actorEmail:Q.email().optional()}).strict(),E9=Q.object({id:Q.string(),name:Q.string().optional(),isPartOf:l.optional(),extensions:Q.record(Q.string(),Q.unknown()).optional()}),ZZ=Q.object({id:Q.string(),attempt:Q.union([Q.string(),Q.record(Q.string(),Q.unknown())]).optional(),startedAtTime:y.optional(),endedAtTime:y.optional(),duration:Q.string().optional(),extensions:Q.record(Q.string(),Q.unknown()).optional()}),HZ=Q.object({id:Q.string().optional(),scoreGiven:Q.number(),maxScore:Q.number().optional(),attempt:Q.union([Q.string(),Q.record(Q.string(),Q.unknown())]).optional(),comment:Q.string().optional(),extensions:Q.record(Q.string(),Q.unknown()).optional()}),KZ=Q.object({actor:Q.union([Q.string(),c2,U2]),object:E9,edApp:l,id:Q.string().optional(),eventTime:y.optional(),session:l.optional(),extensions:Q.record(Q.string(),Q.unknown()).optional()}).strict(),XZ=Q.object({actor:Q.union([Q.string(),c2,U2]),object:E9,edApp:l,generated:ZZ.optional(),id:Q.string().optional(),eventTime:y.optional(),session:l.optional(),extensions:Q.record(Q.string(),Q.unknown()).optional()}).strict(),WZ=Q.object({actor:Q.union([Q.string(),c2,U2]),object:Q.string(),generated:HZ,edApp:l,id:Q.string().optional(),eventTime:y.optional(),session:l.optional(),extensions:Q.record(Q.string(),Q.unknown()).optional()}).strict(),y1=Z2.object({name:X,targetUrl:Z2.url("targetUrl must be a valid URL"),secret:X,active:Z2.boolean(),sensor:Z2.string().nullable().optional(),description:Z2.string().nullable().optional()}).strict(),YZ=Z2.enum(["string","number","boolean"]),QZ=Z2.enum(["eq","neq","gt","gte","lt","lte","contains","notContains","in","notIn","startsWith","endsWith","regexp"]),f1=Z2.object({webhookId:X,filterKey:X,filterValue:X,filterType:YZ,filterOperator:QZ,active:Z2.boolean()}).strict(),p2=U.string().uuid(),L9=U.object({title:X,identifier:p2,uri:X}),GZ=U.object({identifier:p2,uri:X,lastChangeDateTime:X,title:X,creator:X,officialSourceURL:U.string().optional(),publisher:U.string().optional(),description:U.string().optional(),language:U.string().optional(),version:U.string().optional(),caseVersion:U.string().optional(),adoptionStatus:U.string().optional(),statusStartDate:U.string().optional(),statusEndDate:U.string().optional(),licenseUri:U.string().optional(),notes:U.string().optional(),subject:U.array(U.string()).optional(),extensions:U.unknown().optional()}),BZ=U.object({identifier:p2,uri:X,lastChangeDateTime:X,fullStatement:X,alternativeLabel:U.string().optional(),CFItemType:U.string().optional(),cfItemType:U.string().optional(),humanCodingScheme:U.string().optional(),listEnumeration:U.string().optional(),abbreviatedStatement:U.string().optional(),conceptKeywords:U.array(U.string()).optional(),notes:U.string().optional(),subject:U.array(U.string()).optional(),language:U.string().optional(),educationLevel:U.array(U.string()).optional(),CFItemTypeURI:U.unknown().optional(),licenseURI:U.unknown().optional(),statusStartDate:U.string().optional(),statusEndDate:U.string().optional(),extensions:U.unknown().optional()}),_Z=U.object({identifier:p2,uri:X,lastChangeDateTime:X,associationType:X,originNodeURI:L9,destinationNodeURI:L9,sequenceNumber:U.number().optional(),extensions:U.unknown().optional()}),FZ=U.object({CFItemTypes:U.array(U.unknown()).optional(),CFSubjects:U.array(U.unknown()).optional(),CFConcepts:U.array(U.unknown()).optional(),CFLicenses:U.array(U.unknown()).optional(),CFAssociationGroupings:U.array(U.unknown()).optional(),extensions:U.unknown().optional()}),g1=U.object({CFDocument:GZ,CFItems:U.array(BZ),CFAssociations:U.array(_Z),CFDefinitions:FZ.optional(),extensions:U.unknown().optional()}),V9="https://www.w3.org/ns/credentials/v2",OZ=w.array(w.url()).min(3,"@context must include W3C, CLR, and OB context URLs").refine(($)=>$[0]===V9,`First @context entry must be "${V9}"`),v9=w.object({id:w.url(),type:w.literal("Image"),caption:w.string().optional()}),N8=w.object({id:w.url(),type:w.array(w.string()).min(1).refine(($)=>$.includes("Profile"),'type must include "Profile"'),name:w.string().optional(),url:w.string().url().optional(),phone:w.string().optional(),description:w.string().optional(),image:v9.optional(),email:w.string().email().optional()}),y9=w.object({type:X,proofPurpose:X,verificationMethod:X,created:w.iso.datetime(),proofValue:X,cryptosuite:w.string().optional()}),DZ=w.object({id:X,type:w.literal("1EdTechJsonSchemaValidator2019")}),wZ=w.object({id:w.string().url().optional(),narrative:w.string().optional()}),xZ=w.object({id:w.url(),type:w.array(w.string()).min(1).refine(($)=>$.includes("Achievement"),'type must include "Achievement"'),name:X,description:X,criteria:wZ,image:v9.optional(),achievementType:w.string().optional(),creator:N8.optional()}),UZ=w.object({type:w.literal("IdentityObject"),identityHash:X,identityType:X,hashed:w.boolean(),salt:w.string().optional()}),MZ=w.enum(["exactMatchOf","isChildOf","isParentOf","isPartOf","isPeerOf","isRelatedTo","precedes","replacedBy"]),jZ=w.object({type:w.literal("Association"),associationType:MZ,sourceId:w.url(),targetId:w.url()}),LZ=w.object({"@context":w.array(w.string()).min(1),id:w.url(),type:w.array(w.string()).min(1).refine(($)=>$.includes("VerifiableCredential"),'type must include "VerifiableCredential"'),issuer:N8,validFrom:w.iso.datetime(),validUntil:w.string().datetime().optional(),credentialSubject:w.object({id:w.string().optional()}),proof:w.array(y9).optional()}),VZ=w.object({id:w.string().url().optional(),type:w.array(w.string()).min(1).refine(($)=>$.includes("ClrSubject"),'type must include "ClrSubject"'),identifier:w.array(UZ).optional(),achievement:w.array(xZ).optional(),verifiableCredential:w.array(LZ).min(1),association:w.array(jZ).optional()}),d1=w.object({"@context":OZ,id:w.url(),type:w.array(w.string()).min(1).refine(($)=>$.includes("VerifiableCredential")&&$.includes("ClrCredential"),'type must include "VerifiableCredential" and "ClrCredential"'),issuer:N8,name:X,description:w.string().optional(),validFrom:w.iso.datetime(),validUntil:w.iso.datetime().optional(),credentialSubject:VZ,proof:w.array(y9).optional(),credentialSchema:w.array(DZ).optional()}),kZ=k.object({staging:k.string().meta({description:"Course ID in staging environment"}).optional(),production:k.string().meta({description:"Course ID in production environment"}).optional()}).meta({id:"CourseIds",description:"Environment-specific course IDs (populated by sync)"}),qZ=k.enum(["base","hole-filling","optional"]).meta({id:"CourseType",description:"Course classification type"}),CZ=k.enum(["draft","testing","published","deactivated"]).meta({id:"PublishStatus",description:"Course publication status"}),AZ=k.object({dailyXp:k.number().int().positive().meta({description:"Target XP to earn per day"}).optional(),dailyLessons:k.number().int().positive().meta({description:"Target lessons to complete per day"}).optional(),dailyActiveMinutes:k.number().int().positive().meta({description:"Target active learning minutes per day"}).optional(),dailyAccuracy:k.number().int().min(0).max(100).meta({description:"Target accuracy percentage (0-100)"}).optional(),dailyMasteredUnits:k.number().int().positive().meta({description:"Target units to master per day"}).optional()}).meta({id:"CourseGoals",description:"Daily learning goals for a course"}),zZ=k.object({totalXp:k.number().int().positive().meta({description:"Total XP available in the course"}).optional(),totalLessons:k.number().int().positive().meta({description:"Total number of lessons/activities"}).optional(),totalGrades:k.number().int().positive().meta({description:"Total grade levels covered"}).optional()}).meta({id:"CourseMetrics",description:"Aggregate metrics for a course"}),f9=k.object({courseType:qZ.optional(),isSupplemental:k.boolean().meta({description:"Whether this is supplemental to a base course"}).optional(),isCustom:k.boolean().meta({description:"Whether this is a custom course for an individual student"}).optional(),publishStatus:CZ.optional(),contactEmail:k.email().meta({description:"Contact email for course issues"}).optional(),primaryApp:k.string().meta({description:"Primary application identifier"}).optional(),goals:AZ.optional(),metrics:zZ.optional()}).meta({id:"CourseMetadata",description:"Course metadata (matches API metadata object)"}),g9=k.object({courseCode:k.string().meta({description:"Course code (e.g., 'MATH101')"}).optional(),level:k.string().meta({description:"Course level (e.g., 'AP', 'Honors')"}).optional(),metadata:f9.optional()}).meta({id:"CourseDefaults",description:"Default properties that apply to all courses unless overridden"}),k9=k.object({level:k.string().meta({description:"Course level for this environment"}).optional(),sensor:k.url().meta({description:"Caliper sensor endpoint URL for this environment"}).optional(),launchUrl:k.url().meta({description:"LTI launch URL for this environment"}).optional(),metadata:f9.optional()}).meta({id:"CourseEnvOverrides",description:"Environment-specific course overrides (non-identity fields)"}),PZ=k.object({staging:k9.meta({description:"Overrides for staging environment"}).optional(),production:k9.meta({description:"Overrides for production environment"}).optional()}).meta({id:"CourseOverrides",description:"Per-environment course overrides"}),TZ=g9.extend({subject:X2.meta({description:"Subject area for this course"}),grade:n.meta({description:"Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"}).optional(),ids:kZ.nullable().optional(),sensor:k.url().meta({description:"Caliper sensor endpoint URL for this course"}).optional(),launchUrl:k.url().meta({description:"LTI launch URL for this course"}).optional(),overrides:PZ.optional()}).meta({id:"CourseConfig",description:"Configuration for a single course. Must have either grade or courseCode (or both)."}),m1=k.object({$schema:k.string().meta({description:"JSON Schema reference for editor support"}).optional(),name:k.string().min(1,"App name is required").meta({description:"Display name for your app"}),defaults:g9.meta({description:"Default properties applied to all courses"}).optional(),courses:k.array(TZ).min(1,"At least one course is required").meta({description:"Courses available in this app"}),sensor:k.url().meta({description:"Default Caliper sensor endpoint URL for all courses"}).optional(),launchUrl:k.url().meta({description:"Default LTI launch URL for all courses"}).optional(),studio:k.object({telemetry:k.boolean().meta({description:"Enable anonymous usage telemetry for Studio (default: true)"}).optional().default(!0)}).meta({description:"Studio-specific configuration"}).optional()}).meta({id:"TimebackConfig",title:"Timeback Config",description:"Configuration schema for timeback.config.json files"}).refine(($)=>{return $.courses.every((J)=>J.grade!==void 0||J.courseCode!==void 0)},{message:"Each course must have either a grade or a courseCode",path:["courses"]}).refine(($)=>{let Z=$.courses.filter((H)=>H.grade!==void 0).map((H)=>`${H.subject}:${H.grade}`);return new Set(Z).size===Z.length},{message:"Duplicate (subject, grade) pair found; each must be unique",path:["courses"]}).refine(($)=>{let Z=$.courses.filter((H)=>H.courseCode!==void 0).map((H)=>H.courseCode);return new Set(Z).size===Z.length},{message:"Duplicate courseCode found; each must be unique",path:["courses"]}).refine(($)=>{return $.courses.every((J)=>{if(J.sensor!==void 0||$.sensor!==void 0)return!0;return[J.launchUrl,$.launchUrl,J.overrides?.staging?.launchUrl,J.overrides?.production?.launchUrl].filter(Boolean).length>0})},{message:"Each course must have an effective sensor. Either set `sensor` explicitly (top-level or per-course), or provide a `launchUrl` so sensor can be derived from its origin.",path:["courses"]}),H2=D.union([y,C2]),l1=D.object({id:D.string(),role:D.string(),beginDate:H2.nullable(),endDate:H2.nullable(),metadata:D.object({goals:D.object({dailyXp:D.number().optional()}).optional(),metrics:D.object({totalXp:D.number().optional(),totalLessons:D.number().optional()}).optional()}).optional(),course:D.object({id:D.string(),title:D.string(),subjects:D.array(D.string()).nullable(),grades:D.array(D.string()).nullable()}),school:D.object({id:D.string(),name:D.string()}),testOutSupported:D.boolean(),testOutEligible:D.boolean()}),RZ=D.object({activityMetrics:D.object({xpEarned:D.number(),totalQuestions:D.number(),correctQuestions:D.number(),masteredUnits:D.number()}),timeSpentMetrics:D.object({activeSeconds:D.number(),inactiveSeconds:D.number(),wasteSeconds:D.number()}),apps:D.array(D.string())}),NZ=D.record(D.string(),D.record(D.string(),RZ)),u1=D.object({message:D.string(),enrollmentId:D.string(),startDate:H2,endDate:H2,facts:NZ,factsByApp:D.unknown()}),d9=D.object({email:D.email().optional(),studentId:X.optional()}).superRefine(($,J)=>{if(!$.email&&!$.studentId)J.addIssue({code:D.ZodIssueCode.custom,message:"must provide either email or studentId",path:["email"]}),J.addIssue({code:D.ZodIssueCode.custom,message:"must provide either email or studentId",path:["studentId"]})}),c1=D.object({subject:X,grade:X,courseId:X,orgSourcedId:X.optional()}),p1=D.object({userId:X}),a1=D.object({sourcedId:X.optional(),role:g5.optional(),beginDate:y.optional(),metadata:D.record(D.string(),D.unknown()).optional()}),i1=D.object({fields:D.string().optional(),limit:D.number().int().positive().optional(),offset:D.number().int().nonnegative().optional(),sort:D.string().optional(),orderBy:D.enum(["asc","desc"]).optional(),filter:D.string().optional(),search:D.string().optional(),roles:D.array(T9).min(1),orgSourcedIds:D.array(X).optional()}),s1=d9.extend({startDate:H2,endDate:H2,timezone:D.string().optional()}),o1=d9.extend({weekDate:H2,timezone:D.string().optional()}),n1=D.object({enrollmentId:X,startDate:H2.optional(),endDate:H2.optional(),timezone:D.string().optional()}),r1=g.object({email:g.email()}),t1=g.object({name:X.optional(),timeback_id:X.optional(),grade:X.optional(),subject:X.optional(),all:g.boolean().optional()}),e1=g.object({student_email:g.email(),timeback_id:X.optional(),subject:X.optional(),grade_rank:g.number().int().min(0).max(12).optional(),assessment_line_item_sourced_id:X.optional(),assessment_result_sourced_id:X.optional()}).superRefine(($,J)=>{let Z=!!$.timeback_id,H=!!$.subject,K=$.grade_rank!==void 0;if(!Z&&!H)J.addIssue({code:g.ZodIssueCode.custom,message:"must provide either timeback_id or subject",path:["timeback_id"]}),J.addIssue({code:g.ZodIssueCode.custom,message:"must provide either timeback_id or subject",path:["subject"]});if(K&&!H)J.addIssue({code:g.ZodIssueCode.custom,message:"grade_rank requires subject",path:["grade_rank"]});let W=!!$.assessment_line_item_sourced_id,_=!!$.assessment_result_sourced_id;if(W!==_)J.addIssue({code:g.ZodIssueCode.custom,message:"assessment_line_item_sourced_id and assessment_result_sourced_id must be provided together",path:W?["assessment_result_sourced_id"]:["assessment_line_item_sourced_id"]})}),$6=g.object({student_email:g.email(),assignment_id:g.number().int().positive().optional(),timeback_id:X.optional(),subject:X.optional(),grade_rank:g.number().int().min(0).max(12).optional()}).superRefine(($,J)=>{let Z=$.assignment_id!==void 0,H=!!$.timeback_id,K=!!$.subject&&$.grade_rank!==void 0;if(!Z&&!H&&!K)J.addIssue({code:g.ZodIssueCode.custom,message:"Either assignment_id, timeback_id, or (subject and grade_rank) is required",path:["assignment_id"]});if($.grade_rank!==void 0&&!$.subject)J.addIssue({code:g.ZodIssueCode.custom,message:"grade_rank requires subject",path:["grade_rank"]})}),f=G.enum(["active","tobedeleted"]),v=G.record(G.string(),G.unknown()).nullable().optional(),L=G.object({sourcedId:X,type:G.string().optional(),href:G.string().optional()}).strict(),IZ=G.enum(["academicSession","assessmentLineItem","category","class","course","demographics","enrollment","gradingPeriod","lineItem","org","resource","result","scoreScale","student","teacher","term","user","componentResource","courseComponent"]),bZ=G.object({sourcedId:X,type:IZ,href:G.url()}).strict(),K2=G.union([C2,y]).transform(($)=>$.includes("T")?$:`${$}T00:00:00Z`),hZ=G.object({learningObjectiveId:G.string(),score:G.number().optional(),textScore:G.string().optional()}),m9=G.array(G.object({source:G.string(),learningObjectiveResults:G.array(hZ)})),SZ=G.object({roleType:G.enum(["primary","secondary"]),role:T9,org:L,userProfile:G.string().optional(),metadata:v,beginDate:K2.optional(),endDate:K2.optional()}).strict(),J6=G.object({sourcedId:X.describe("sourcedId must be a non-empty string"),status:f.optional(),enabledUser:G.union([G.boolean(),G.enum(["true","false"]).transform(($)=>$==="true")]),givenName:X.describe("givenName must be a non-empty string"),familyName:X.describe("familyName must be a non-empty string"),middleName:X.nullable().optional(),preferredFirstName:X.nullable().optional(),preferredMiddleName:X.nullable().optional(),preferredLastName:X.nullable().optional(),username:X.nullable().optional(),email:G.email(),userMasterIdentifier:G.string().nullable().optional(),roles:G.array(SZ).min(1,"roles must include at least one role"),userIds:G.array(G.object({type:X,identifier:X}).strict()).optional(),agents:G.array(L).optional(),primaryOrg:L.optional(),grades:G.array(n).optional(),sms:X.nullable().optional(),phone:X.nullable().optional(),pronouns:X.nullable().optional(),password:X.nullable().optional(),metadata:v}).strict(),Z6=G.object({sourcedId:X.describe("sourcedId must be a non-empty string").optional(),status:f,title:X.describe("title must be a non-empty string"),org:L,courseCode:X.nullable().optional(),subjects:G.array(X2).nullable().optional(),subjectCodes:G.array(G.string()).nullable().optional(),grades:G.array(n).nullable().optional(),level:X.nullable().optional(),academicSession:L.nullable().optional(),schoolYear:bZ.nullable().optional(),gradingScheme:X.nullable().optional(),metadata:v}).strict(),H6=G.object({sourcedId:X.describe("sourcedId must be a non-empty string").optional(),status:f.optional(),title:X.describe("title must be a non-empty string"),terms:G.array(L).min(1,"terms must have at least one item"),course:L,org:L,classCode:X.nullable().optional(),classType:G.enum(["homeroom","scheduled"]).optional(),location:X.nullable().optional(),grades:G.array(n).optional(),subjects:G.array(X2).optional(),subjectCodes:G.array(X).optional(),periods:G.array(X).optional(),metadata:v}).strict(),J2=G.enum(["true","false"]),K6=G.object({sourcedId:X.describe("sourcedId must be a non-empty string").optional(),status:f.optional(),user:L,class:L,school:L.optional(),role:G.enum(["administrator","proctor","student","teacher"]),primary:J2.optional(),beginDate:C2.optional(),endDate:C2.optional(),metadata:v}).strict(),X6=G.object({sourcedId:X.optional(),title:X.describe("title must be a non-empty string"),status:f,weight:G.number().nullable().optional(),metadata:v}).strict(),W6=G.object({sourcedId:X.optional(),title:X.describe("title must be a non-empty string"),class:L,school:L,category:L,assignDate:K2,dueDate:K2,status:f.optional(),description:G.string().nullable().optional(),resultValueMin:G.number().nullable().optional(),resultValueMax:G.number().nullable().optional(),gradingPeriod:L.nullable().optional(),academicSession:L.nullable().optional(),scoreScale:L.nullable().optional(),learningObjectiveSet:R9.nullable().optional(),metadata:v}).strict(),Y6=G.object({sourcedId:X.optional(),lineItem:L,student:L,class:L.nullable().optional(),scoreDate:K2,scoreStatus:G.enum(["exempt","fully graded","not submitted","partially graded","submitted"]),score:G.number().nullable().optional(),textScore:G.string().nullable().optional(),status:f,scoreScale:L.nullable().optional(),comment:G.string().nullable().optional(),learningObjectiveSet:m9.nullable().optional(),inProgress:G.string().optional(),incomplete:G.string().optional(),late:G.string().optional(),missing:G.string().optional(),metadata:v}).strict(),Q6=G.object({sourcedId:X.optional(),title:X.describe("title must be a non-empty string"),status:f,type:X,class:L,course:L.nullable().optional(),scoreScaleValue:G.array(G.object({itemValueLHS:X,itemValueRHS:X,value:G.string().optional(),description:G.string().optional()}).strict()),metadata:v}).strict(),G6=G.object({sourcedId:X.optional(),status:f,dateLastModified:y.optional(),title:X.describe("title must be a non-empty string"),description:G.string().nullable().optional(),class:L.nullable().optional(),parentAssessmentLineItem:L.nullable().optional(),scoreScale:L.nullable().optional(),resultValueMin:G.number().nullable().optional(),resultValueMax:G.number().nullable().optional(),component:L.nullable().optional(),componentResource:L.nullable().optional(),learningObjectiveSet:G.array(G.object({source:G.string(),learningObjectiveIds:G.array(G.string())})).optional().nullable(),course:L.nullable().optional(),metadata:v}).strict(),B6=G.object({sourcedId:X.optional(),status:f,dateLastModified:y.optional(),metadata:v,assessmentLineItem:L,student:L,score:G.number().nullable().optional(),textScore:G.string().nullable().optional(),scoreDate:K2,scoreScale:L.nullable().optional(),scorePercentile:G.number().nullable().optional(),scoreStatus:G.enum(["exempt","fully graded","not submitted","partially graded","submitted"]),comment:G.string().nullable().optional(),learningObjectiveSet:m9.nullable().optional(),inProgress:G.string().nullable().optional(),incomplete:G.string().nullable().optional(),late:G.string().nullable().optional(),missing:G.string().nullable().optional()}).strict(),_6=G.object({sourcedId:X.optional(),status:f.optional(),name:X.describe("name must be a non-empty string"),type:f5,identifier:G.string().nullish(),parent:L.optional(),metadata:v}).strict(),F6=G.object({sourcedId:X.optional(),status:f.optional(),name:X.describe("name must be a non-empty string"),type:G.literal("school").default("school"),identifier:G.string().nullish(),parent:L.optional(),metadata:v}).strict(),O6=G.object({sourcedId:X.describe("sourcedId must be a non-empty string"),status:f,title:X.describe("title must be a non-empty string"),startDate:K2,endDate:K2,type:G.enum(["gradingPeriod","semester","schoolYear","term"]),schoolYear:X.describe("schoolYear must be a non-empty string"),org:L,parent:L.optional(),children:G.array(L).optional(),metadata:v}).strict(),D6=G.object({sourcedId:X,title:X.describe("title must be a non-empty string"),courseComponent:L,resource:L,status:f,sortOrder:G.number().optional(),lessonType:p5.optional(),metadata:v}).strict(),w6=G.object({sourcedId:X.optional(),title:X.describe("title must be a non-empty string"),course:L,status:f,sortOrder:G.number().optional(),parent:L.nullable().optional(),courseComponent:L.nullable().optional(),prerequisites:G.array(G.string()).nullable().optional(),prerequisiteCriteria:G.string().nullable().optional(),unlockDate:K2.nullable().optional(),metadata:v}).strict().transform(({courseComponent:$,parent:J,...Z})=>({...Z,parent:J===void 0?$??void 0:J})),x6=G.object({sourcedId:X.describe("sourcedId must be a non-empty string"),role:G.enum(["student","teacher"]),primary:J2.optional(),beginDate:C2.optional(),endDate:C2.optional(),metadata:v}).strict(),U6=G.object({agentSourcedId:X.describe("agentSourcedId must be a non-empty string")}).strict(),M6=G.object({applicationName:X.describe("applicationName must be a non-empty string"),credentials:G.object({username:X.describe("username must be a non-empty string"),password:X.describe("password must be a non-empty string")})}).strict(),j6=G.object({sourcedId:X.describe("sourcedId must be a non-empty string"),status:f.optional(),metadata:v,birthDate:G.string().regex(/^\d{4}-\d{2}-\d{2}$/).nullable().optional(),sex:G.enum(["male","female"]).nullable().optional(),americanIndianOrAlaskaNative:J2.nullable().optional(),asian:J2.nullable().optional(),blackOrAfricanAmerican:J2.nullable().optional(),nativeHawaiianOrOtherPacificIslander:J2.nullable().optional(),white:J2.nullable().optional(),demographicRaceTwoOrMoreRaces:J2.nullable().optional(),hispanicOrLatinoEthnicity:J2.nullable().optional(),countryOfBirthCode:G.string().nullable().optional(),stateOfBirthAbbreviation:G.string().nullable().optional(),cityOfBirth:G.string().nullable().optional(),publicSchoolResidenceStatus:G.string().nullable().optional()}).strict(),G2=G.object({type:d5,subject:X2.nullish(),grades:G.array(n).nullish(),language:G.string().nullish(),xp:G.number().nullish(),url:G.url().nullish(),keywords:G.array(G.string()).nullish(),learningObjectiveSet:R9.nullish(),lessonType:G.string().nullish()}).passthrough(),EZ=G2.extend({type:G.literal("qti"),subType:m5,questionType:u5.optional(),difficulty:c5.optional()}),vZ=G2.extend({type:G.literal("text"),format:G.string(),author:G.string().optional(),pageCount:G.number().optional()}),yZ=G2.extend({type:G.literal("audio"),duration:G.string().regex(/^\d{2}:\d{2}:\d{2}(\.\d{2})?$/).optional(),format:G.string(),speaker:G.string().optional()}),fZ=G2.extend({type:G.literal("video"),duration:G.string().regex(/^\d{2}:\d{2}:\d{2}(\.\d{2})?$/).optional(),captionsAvailable:G.boolean().optional(),format:G.string()}),gZ=G2.extend({type:G.literal("interactive"),launchUrl:G.url().optional(),toolProvider:G.string().optional(),instructionalMethod:G.string().optional(),courseIdOnFail:G.string().nullable().optional(),fail_fast:N9}),dZ=G2.extend({type:G.literal("visual"),format:G.string(),resolution:G.string().optional()}),mZ=G2.extend({type:G.literal("course-material"),subType:l5,author:G.string().optional(),format:G.string(),instructionalMethod:G.string().optional()}),lZ=G2.extend({type:G.literal("assessment-bank"),resources:G.array(G.string())}),uZ=G.discriminatedUnion("type",[EZ,vZ,yZ,fZ,gZ,dZ,mZ,lZ]),cZ=new Set(["type","subject","grades","language","xp","url","keywords","learningObjectiveSet","lessonType","subType","questionType","difficulty","format","author","pageCount","duration","speaker","captionsAvailable","launchUrl","toolProvider","instructionalMethod","courseIdOnFail","resolution","resources"]),pZ=G.record(G.string(),G.unknown()).superRefine(($,J)=>{if("fail_fast"in $){let H=N9.safeParse($.fail_fast);if(!H.success)for(let K of H.error.issues)J.addIssue({...K,path:["fail_fast",...K.path]})}let Z=Object.keys($).filter((H)=>cZ.has(H));if(Z.length===0)return;J.addIssue({code:"custom",message:`metadata keys ${Z.map((H)=>`\`${H}\``).join(", ")} require a valid \`type\` discriminator`})}),L6=G.object({sourcedId:X.optional(),title:X.describe("title must be a non-empty string"),vendorResourceId:X.describe("vendorResourceId must be a non-empty string"),roles:G.array(G.enum(["primary","secondary"])).optional(),importance:G.enum(["primary","secondary"]).optional(),vendorId:X.nullable().optional(),applicationId:X.nullable().optional(),status:f.optional(),metadata:G.union([uZ,pZ]).nullable().optional()}).strict(),aZ=G.object({url:X.describe("courseStructure.url must be a non-empty string"),skillCode:X.describe("courseStructure.skillCode must be a non-empty string"),lessonCode:X.describe("courseStructure.lessonCode must be a non-empty string"),title:X.describe("courseStructure.title must be a non-empty string"),"unit-title":X.describe("courseStructure.unit-title must be a non-empty string"),status:X.describe("courseStructure.status must be a non-empty string"),xp:G.number()}).loose(),V6=G.object({course:G.object({sourcedId:X.describe("course.sourcedId must be a non-empty string").optional(),title:X.describe("course.title must be a non-empty string"),org:L,status:f,metadata:v}).strict(),courseStructure:G.record(G.string(),aZ)}).strict(),iZ=G.object({student:L}).loose(),k6=G.array(iZ).min(1,"results must have at least one item"),sZ=B.enum(["edulastic","mastery-track"]),oZ=B.enum(["powerpath-100","quiz","test-out","placement","unit-test","alpha-read-article"]),l9=B.array(n),u9=B.record(B.string(),B.unknown()).optional(),c9=B.object({courseId:X,lessonTitle:X.optional(),launchUrl:X.optional(),toolProvider:sZ,unitTitle:X.optional(),courseComponentSourcedId:X.optional(),vendorId:X.optional(),description:X.optional(),resourceMetadata:u9.nullable().optional(),grades:l9}),q6=c9.extend({lessonType:B.literal("test-out"),xp:B.number()}),C6=c9.extend({lessonType:B.literal("placement"),courseIdOnFail:X.nullable().optional(),xp:B.number().optional()}),q9=B.object({courseId:X,lessonType:oZ,lessonTitle:X.optional(),unitTitle:X.optional(),courseComponentSourcedId:X.optional(),resourceMetadata:u9.nullable().optional(),xp:B.number().optional(),grades:l9.optional(),courseIdOnFail:X.nullable().optional()}),A6=B.discriminatedUnion("testType",[q9.extend({testType:B.literal("qti"),qti:B.object({url:B.url(),title:X.optional(),metadata:B.record(B.string(),B.unknown()).optional()})}),q9.extend({testType:B.literal("assessment-bank"),assessmentBank:B.object({resources:B.array(B.object({url:B.url(),title:X.optional(),metadata:B.record(B.string(),B.unknown()).optional()})).min(1)})})]),z6=B.object({student:X,lesson:X}),P6=B.object({student:X,lesson:X}),T6=B.object({courseId:X,userId:X,classId:X.optional()}),q2=B.object({type:B.enum(["component","resource"]),id:X}),nZ=B.union([B.object({type:B.literal("set-skipped"),payload:B.object({target:q2,value:B.boolean()})}),B.object({type:B.literal("add-custom-resource"),payload:B.object({resource_id:X,parent_component_id:X,skipped:B.boolean().optional()})}),B.object({type:B.literal("move-item-before"),payload:B.object({target:q2,reference_id:X})}),B.object({type:B.literal("move-item-after"),payload:B.object({target:q2,reference_id:X})}),B.object({type:B.literal("move-item-to-start"),payload:B.object({target:q2})}),B.object({type:B.literal("move-item-to-end"),payload:B.object({target:q2})}),B.object({type:B.literal("change-item-parent"),payload:B.object({target:q2,new_parent_id:X,position:B.enum(["start","end"]).optional()})})]),R6=B.object({operation:nZ,reason:X.optional()}),N6=B.object({studentId:X,componentResourceId:X,result:B.object({status:B.enum(["active","tobedeleted"]),metadata:B.record(B.string(),B.unknown()).optional(),score:B.number().optional(),textScore:X.optional(),scoreDate:B.string().datetime(),scorePercentile:B.number().optional(),scoreStatus:y5,comment:X.optional(),learningObjectiveSet:B.array(B.object({source:X,learningObjectiveResults:B.array(B.object({learningObjectiveId:X,score:B.number().optional(),textScore:X.optional()}))})).optional(),inProgress:X.optional(),incomplete:X.optional(),late:X.optional(),missing:X.optional()})}),I6=B.object({student:X,lesson:X,applicationName:X.optional(),testId:X.optional(),skipCourseEnrollment:B.boolean().optional()}),b6=B.object({student:X,subject:X2}),h6=B.object({student:X,lesson:X}),S6=B.object({userId:X}),E6=B.object({userId:X,subject:B.enum(["Math","Reading","Language","Science"])}),v6=B.object({student:X,subject:X2,grade:n,testName:X.optional()}),y6=B.object({testName:X}),rZ=B.object({student:X,subject:X2,grade:n,testName:X.optional()}),f6=B.object({items:B.array(rZ)}),g6=B.object({spreadsheetUrl:B.url(),sheet:X}),d6=B.object({student:X,status:B.enum(["assigned","in_progress","completed","failed","expired","cancelled"]).optional(),subject:X.optional(),grade:n.optional(),limit:B.number().int().positive().max(3000).optional(),offset:B.number().int().nonnegative().optional()}),m6=B.object({student:X.optional(),status:B.enum(["assigned","in_progress","completed","failed","expired","cancelled"]).optional(),subject:X.optional(),grade:n.optional(),limit:B.number().int().positive().max(3000).optional(),offset:B.number().int().nonnegative().optional()}),l6=B.object({student:X,question:X,response:B.union([X,B.array(X)]).optional(),responses:B.record(B.string(),B.union([X,B.array(X)])).optional(),lesson:X,rendererOutcomes:B.object({score:B.number(),maxScore:B.number().min(0),isCorrect:B.boolean()}).optional(),playerState:B.string().optional()}).refine(($)=>$.response!==void 0||$.responses!==void 0,{message:"Either 'response' or 'responses' must be provided",path:["response","responses"]}).transform(($)=>{if($.response!==void 0&&$.responses===void 0)return{...$,responses:{RESPONSE:$.response}};return $}),u6=B.object({student:X,lesson:X,attempt:B.number().int().positive().optional()}),c6=B.object({student:X,lesson:X}),p6=B.object({student:X,lesson:X}),a6=B.object({student:X,course:X}),i6=B.object({student:X,lesson:X,applicationName:X.optional()}),s6=B.object({student:X,subject:X2}),o6=B.object({oneRosterSourcedId:X,subject:X}),n6=B.object({courseIds:B.array(X).min(1),rendererId:X,rendererUrl:B.url(),rendererVersion:X.optional(),suppressFeedback:B.boolean().optional(),suppressCorrectResponse:B.boolean().optional()}),r6=B.object({status:B.enum(["active","tobedeleted"]).optional()}),I8=Y.enum(["choice","text-entry","extended-text","inline-choice","match","order","associate","select-point","graphic-order","graphic-associate","graphic-gap-match","hotspot","hottext","slider","drawing","media","upload"]),b8=Y.enum(["single","multiple","ordered","record"]),h8=Y.enum(["identifier","boolean","integer","float","string","point","pair","directedPair","duration","file","uri"]),tZ=Y.enum(["easy","medium","hard"]),eZ=Y.enum(["linear","nonlinear"]),$0=Y.enum(["individual","simultaneous"]),S8=Y.enum(["show","hide"]),p9=Y.enum(["test","item","stimulus"]),t6=Y.enum(["QUESTION","LESSON"]),J0=Y.object({value:Y.array(Y.string())}).strict(),a9=Y.object({identifier:X,cardinality:b8,baseType:h8.optional(),correctResponse:J0}).strict(),i9=Y.object({identifier:X,cardinality:b8,baseType:h8.optional()}).strict(),s9=Y.object({identifier:X,cardinality:b8.optional(),baseType:h8,normalMaximum:Y.number().optional(),normalMinimum:Y.number().optional(),defaultValue:Y.object({value:Y.unknown().optional()}).strict().optional()}).strict(),Z0=Y.object({outcomeIdentifier:X,variableIdentifier:X}).strict(),o9=Y.object({templateType:Y.enum(["match_correct","map_response"]),responseDeclarationIdentifier:X,outcomeIdentifier:X,correctResponseIdentifier:X,incorrectResponseIdentifier:X,inlineFeedback:Z0.optional()}).strict(),H0=Y.object({source:X,learningObjectiveIds:Y.array(Y.string())}).strict(),E8=Y.object({subject:Y.string().optional(),grade:n.optional(),difficulty:tZ.optional(),learningObjectiveSet:Y.array(H0).optional()}).loose(),n9=Y.object({outcomeIdentifier:X,identifier:X,showHide:S8,content:Y.string(),title:Y.string()}).strict(),r9=Y.object({outcomeIdentifier:X,identifier:X,showHide:S8,content:Y.string(),class:Y.array(Y.string()).optional()}).strict(),t9=Y.object({outcomeIdentifier:X,identifier:X,showHide:S8,content:Y.string(),class:Y.array(Y.string()).optional()}).strict(),K0=Y.object({identifier:X,content:Y.string(),feedbackInline:Y.string().nullable().optional(),feedbackOutcomeIdentifier:X.optional()}).loose(),X0=Y.object({prompt:Y.string().optional(),choices:Y.array(K0).optional()}).loose(),W0=Y.object({"expected-length":Y.number().int().nonnegative().optional(),"pattern-mask":Y.string().optional(),placeholder:Y.string().optional()}).loose(),e9=Y.object({type:I8,responseIdentifier:X,shuffle:Y.boolean().optional(),maxChoices:Y.number().int().nonnegative().optional(),attributes:W0.optional(),questionStructure:X0}).loose(),$$=Y.object({use:X,view:X,body:Y.string()}).loose(),J$=Y.object({identifier:X,href:X.optional(),title:Y.string().optional()}).loose(),Z$=Y.object({href:X,type:X}).strict(),H$=Y.object({id:X,support:Y.string(),content:Y.string()}).strict(),e6=Y.object({query:Y.string().optional(),page:Y.number().int().positive().optional(),limit:Y.number().int().positive().optional(),sort:Y.string().optional(),order:Y.enum(["asc","desc"]).optional()}).strict(),Y0=Y.object({format:Y.string().pipe(Y.literal("xml")),xml:X,metadata:E8.optional()}).strict(),Q0=Y.object({format:Y.literal("json").optional(),identifier:X,title:X,type:I8,qtiVersion:Y.string().optional(),timeDependent:Y.boolean().optional(),adaptive:Y.boolean().optional(),preInteraction:Y.string().optional(),interaction:e9.optional(),postInteraction:Y.string().optional(),responseDeclarations:Y.array(a9).optional(),outcomeDeclarations:Y.array(i9).optional(),responseProcessing:o9.optional(),metadata:E8.optional(),modalFeedback:Y.array(n9).optional(),feedbackInline:Y.array(r9).optional(),feedbackBlock:Y.array(t9).optional(),rubrics:Y.array($$).optional(),stimulus:J$.optional()}).strict(),$7=Y.union([Y0,Q0]),J7=Y.object({format:Y.literal("json").optional(),identifier:X.optional(),title:X,type:I8,qtiVersion:Y.string().optional(),timeDependent:Y.boolean().optional(),adaptive:Y.boolean().optional(),preInteraction:Y.string().optional(),interaction:e9.optional(),postInteraction:Y.string().optional(),responseDeclarations:Y.array(a9).optional(),outcomeDeclarations:Y.array(i9).optional(),responseProcessing:o9.optional(),metadata:E8.optional(),modalFeedback:Y.array(n9).optional(),feedbackInline:Y.array(r9).optional(),feedbackBlock:Y.array(t9).optional(),rubrics:Y.array($$).optional(),stimulus:J$.optional(),rawXml:Y.string(),content:Y.record(Y.string(),Y.unknown())}).strict(),Z7=Y.object({identifier:X,response:Y.union([Y.string(),Y.array(Y.string())])}).strict(),K$=Y.object({identifier:X,href:X,sequence:Y.number().int().positive().optional()}).strict(),G0=Y.object({identifier:X,title:X,visible:Y.boolean(),required:Y.boolean().optional(),fixed:Y.boolean().optional(),sequence:Y.number().int().positive(),"qti-assessment-item-ref":Y.array(K$).optional()}).strict(),X$=Y.object({identifier:X,navigationMode:Y.string().pipe(eZ),submissionMode:Y.string().pipe($0),"qti-assessment-section":Y.array(G0)}).strict(),H7=Y.object({items:Y.array(K$).min(1)}).strict(),K7=Y.object({metadata:Y.record(Y.string(),Y.unknown()).optional()}).strict(),X7=Y.object({identifier:X,title:X,qtiVersion:Y.string().optional(),toolName:Y.string().optional(),toolVersion:Y.string().optional(),timeLimit:Y.number().optional(),maxAttempts:Y.number().optional(),toolsEnabled:Y.record(Y.string(),Y.boolean()).optional(),metadata:Y.record(Y.string(),Y.unknown()).optional(),"qti-test-part":Y.array(X$),"qti-outcome-declaration":Y.array(s9).optional()}).strict(),W7=Y.object({identifier:X.optional(),title:X,qtiVersion:Y.string().optional(),toolName:Y.string().optional(),toolVersion:Y.string().optional(),timeLimit:Y.number().optional(),maxAttempts:Y.number().optional(),toolsEnabled:Y.record(Y.string(),Y.boolean()).optional(),metadata:Y.record(Y.string(),Y.unknown()).optional(),"qti-test-part":Y.array(X$),"qti-outcome-declaration":Y.array(s9).optional()}).strict(),Y7=Y.object({identifier:X,title:X,label:Y.string().optional(),language:Y.string().optional(),stylesheet:Z$.optional(),content:Y.string(),catalogInfo:Y.array(H$).optional(),toolName:Y.string().optional(),toolVersion:Y.string().optional(),metadata:Y.record(Y.string(),Y.unknown()).optional()}).strict(),Q7=Y.object({identifier:X.optional(),title:X,label:Y.string().optional(),language:Y.string().optional(),stylesheet:Z$.optional(),content:Y.string(),catalogInfo:Y.array(H$).optional(),toolName:Y.string().optional(),toolVersion:Y.string().optional(),metadata:Y.record(Y.string(),Y.unknown()).optional()}).strict(),G7=Y.object({xml:Y.string().optional(),schema:p9,entityId:Y.string().optional()}).strict(),B7=Y.object({xml:Y.array(Y.string()),schema:p9,entityIds:Y.array(Y.string())}).strict(),_7=Y.object({questionId:Y.string().optional(),userId:X,feedback:X,lessonId:X,humanApproved:Y.boolean().optional()}).strict(),B0=A2.enum(["creator_only","same_org","all_orgs"]),_0=A2.string().uuid(),F7=A2.email(),O7=A2.object({sql:X}),D7=A2.object({endpointName:X,sql:X,authMode:B0,description:X.optional()}),w7=A2.object({endpointId:_0});class W${transport;eventTransformer;constructor($,J){this.transport=$,this.eventTransformer=J?.eventTransformer}send($,J){o(JZ,{sensor:$,events:J},"send events");let Z={sensor:$,sendTime:new Date().toISOString(),dataVersion:"http://purl.imsglobal.org/ctx/caliper/v1p2",data:J};return this.sendEnvelope(Z)}async sendEnvelope($){o(M9,$,"caliper envelope"),S.debug("Sending Caliper envelope",{sensor:$.sensor,eventCount:$.data.length});let J=this.eventTransformer?this.eventTransformer.transformEnvelope($):$,H=(await this.transport.request(this.transport.paths.send,{method:"POST",body:J}))?.jobId;return S.debug("Events sent",{jobId:H??"(none)"}),{jobId:H}}async validate($){let J=this.transport.paths.validate;if(!J)throw Error("validate() is not supported on this platform");o(M9,$,"caliper envelope"),S.debug("Validating Caliper envelope",{sensor:$.sensor,eventCount:$.data.length});let Z=await this.transport.request(J,{method:"POST",body:$});return S.debug("Validation complete",{status:Z.status}),Z}async list($={}){let J=this.transport.paths.list;if(!J)throw Error("list() is not supported on this platform");o(j9,$,"list events params"),S.debug("Listing events",{params:$});let Z={limit:$.limit??100,offset:$.offset??0};if($.sensor)Z.sensor=$.sensor;if($.startDate)Z.startDate=$.startDate;if($.endDate)Z.endDate=$.endDate;if($.actorId)Z.actorId=$.actorId;if($.actorEmail)Z.actorEmail=$.actorEmail;let H=await this.transport.request(J,{params:Z});return{events:H.events??[],pagination:H.pagination}}stream($={}){let J=this.transport.paths.list;if(!J)throw Error("stream() is not supported on this platform");let{max:Z,...H}=$;o(j9,H,"list events params"),z8($),S.debug("Streaming events",{params:$});let K={};if(H.limit!==void 0)K.limit=H.limit;if(H.offset!==void 0)K.offset=H.offset;if(H.sensor)K.sensor=H.sensor;if(H.startDate)K.startDate=H.startDate;if(H.endDate)K.endDate=H.endDate;if(H.actorId)K.actorId=H.actorId;if(H.actorEmail)K.actorEmail=H.actorEmail;return new A9(this.transport,J,{...K,max:Z})}async get($){let J=this.transport.paths.get;if(!J)throw Error("get() is not supported on this platform");u2($,"externalId"),S.debug("Getting event",{externalId:$});let Z=J.replace("{id}",encodeURIComponent($)),H=await this.transport.request(Z);if(!H.event)throw Error(`Event not found: ${$}`);return H.event}sendActivity($,J){o(r5,J,"activity event");let Z=P8(J);return S.debug("Sending ActivityCompletedEvent",{eventId:Z.id,actor:J.actor.email,subject:J.object.subject,metricsCount:J.metrics.length}),this.send($,[Z])}sendTimeSpent($,J){o(t5,J,"time spent event");let Z=T8(J);return S.debug("Sending TimeSpentEvent",{eventId:Z.id,actor:J.actor.email,subject:J.object.subject,metricsCount:J.metrics.length}),this.send($,[Z])}sendQuestionSeen($,J){o(KZ,J,"question seen event");let Z=k5(J);return S.debug("Sending AssessmentItemEvent.Started",{eventId:Z.id,actor:J.actor,object:J.object.id}),this.send($,[Z])}sendQuestionAnswered($,J){o(XZ,J,"question answered event");let Z=q5(J);return S.debug("Sending AssessmentItemEvent.Completed",{eventId:Z.id,actor:J.actor,object:J.object.id}),this.send($,[Z])}sendQuestionGraded($,J){o(WZ,J,"question graded event");let Z=C5(J);return S.debug("Sending GradeEvent.Graded",{eventId:Z.id,actor:J.actor,object:J.object,scoreGiven:J.generated.scoreGiven}),this.send($,[Z])}}class Y${transport;constructor($){this.transport=$}async getStatus($){let J=this.transport.paths.jobStatus;if(!J)throw Error("getStatus() is not supported on this platform");u2($,"jobId"),S.debug("Getting job status",{jobId:$});let Z=J.replace("{id}",encodeURIComponent($));return(await this.transport.request(Z)).job}async waitForCompletion($,J={}){u2($,"jobId"),F0(J);let{timeoutMs:Z=30000,pollIntervalMs:H=1000}=J,K=Date.now();S.debug("Waiting for job completion",{jobId:$,timeoutMs:Z,pollIntervalMs:H});while(Date.now()-K<Z){let W=await this.getStatus($);if(W.state==="completed")return S.info("Job completed",{jobId:$}),W;if(W.state==="failed")throw S.error("Job failed",{jobId:$}),Error(`Job ${$} failed`);await new Promise((_)=>{setTimeout(_,H)})}throw Error(`Job ${$} timed out after ${Z}ms`)}}function F0($){if(!$)return;let J=[];if($.timeoutMs!==void 0){if(!Number.isInteger($.timeoutMs)||$.timeoutMs<=0)J.push({path:"timeoutMs",message:"Must be a positive integer"})}if($.pollIntervalMs!==void 0){if(!Number.isInteger($.pollIntervalMs)||$.pollIntervalMs<=0)J.push({path:"pollIntervalMs",message:"Must be a positive integer"})}if(J.length>0)throw N2("Invalid polling options",J)}function O0($=l2){return class{transport;_provider;events;jobs;constructor(Z={}){let H=h5(Z,$),K;if(H.mode==="transport")this.transport=H.transport,S.info("Client initialized with custom transport");else{let{provider:W}=H,{baseUrl:_,paths:F}=W.getEndpointWithPaths("caliper"),O=W.getTokenProvider("caliper");if(!O)throw Error("Caliper API requires authentication");if(this._provider=W,this.transport=new C9({baseUrl:_,tokenProvider:O,timeout:W.timeout,paths:F}),W.platform===W9)K=new z9;S.info("Client initialized",{platform:W.platform,env:W.env,baseUrl:_})}this.events=new W$(this.transport,{eventTransformer:K}),this.jobs=new Y$(this.transport)}getTransport(){return this.transport}checkAuth(){if(!this._provider)throw Error("Cannot check auth: client initialized with custom transport");return this._provider.checkAuth()}}}var x7=O0();class W2 extends Error{course;env;constructor($,J){let Z=$.grade===void 0?$.courseCode??$.subject:`${$.subject} grade ${$.grade}`;super(`Course "${Z}" is missing a synced ID for ${J}. Run \`timeback resources push\` first.`);this.name="MissingSyncedCourseIdError",this.course=$,this.env=J}}class a2 extends Error{sensor;constructor($){super(`Invalid sensor URL "${$}". Sensor must be a valid absolute URL (e.g., "https://sensor.example.com") to support slug-based activity IDs.`);this.name="InvalidSensorUrlError",this.sensor=$}}var Q$="/ims/oneroster/rostering/v1p2";function G$($,J){return`${$.replace(/\/+$/,"")}/${J.replace(/^\/+/,"")}`}function D0($,J){return G$($,`${Q$}/courses/${J}`)}function w0($,J){return G$($,`${Q$}/users/${J}`)}function B$($,J){let Z=$.ids?.[J];if(!Z)throw new W2($,J);return Z}function x0($,J,Z){let H=B$(J,Z);return D0($,H)}function U0($){if($.courseCode)return $.courseCode;if($.grade!==void 0)return`${$.subject} G${String($.grade)}`;return $.subject}function v8($,J,Z){let H;try{H=new URL($)}catch{throw new a2($)}let K="grade"in J?`${J.subject}/g${String(J.grade)}`:J.code,W=H.pathname.replace(/\/+$/,"");return H.pathname=`${W}/activities/${K}/${encodeURIComponent(Z)}`,H.toString()}function _$($,J,Z,H,K,W,_){return{id:v8(K,$.course,$.id),type:"TimebackActivityContext",subject:J.subject,app:{name:Z},activity:{name:$.name},course:{id:x0(W,J,H),name:U0(J)},process:_??!0}}function M0($){let J=[];if($.totalQuestions!==void 0)J.push({type:"totalQuestions",value:$.totalQuestions});if($.correctQuestions!==void 0)J.push({type:"correctQuestions",value:$.correctQuestions});if($.xpEarned!==void 0)J.push({type:"xpEarned",value:$.xpEarned});if($.masteredUnits!==void 0)J.push({type:"masteredUnits",value:$.masteredUnits});return J}function j0($,J){let Z=[{type:"active",value:Math.max(0,$)/1000}];if(J>0)Z.push({type:"inactive",value:Math.max(0,J)/1000});return Z}function L0($){return $===void 0?void 0:{pctCompleteApp:$}}function F$($,J){return{courseId:B$($,J)}}function O$($){if(!$)return;return`urn:uuid:${$}`}function D$($,J,Z){return{id:w0($,J),type:"TimebackUser",email:Z}}function w$($){let{sensor:J,timebackId:Z,email:H,payload:K,process:W,course:_,appName:F,apiEnv:O,onerosterBaseUrl:x,attempt:V,runId:A}=$,C=D$(x,Z,H),q=_$(K,_,F,O,J,x,W??K.process),z=M0(K.metrics),N=L0(K.pctComplete),I=O$(A),r=F$(_,O),Y2=P8({actor:C,object:q,metrics:z,eventTime:K.endedAt,generatedExtensions:N,extensions:r,attempt:V,session:I});return{sensor:J,actor:C,object:q,event:Y2,payload:K,course:_,appName:F,apiEnv:O,email:H,timebackId:Z}}function i2($){let{sensor:J,timebackId:Z,email:H,payload:K,course:W,appName:_,apiEnv:F,onerosterBaseUrl:O,runId:x}=$,V=D$(O,Z,H),A=_$(K,W,_,F,J,O),C=j0(K.elapsedMs,K.pausedMs),q=F$(W,F),z=O$(x),N=T8({actor:V,object:A,metrics:C,eventTime:K.endedAt,extensions:q,session:z});return{sensor:J,actor:V,object:A,event:N,payload:{id:K.id,name:K.name,course:K.course,startedAt:K.startedAt,endedAt:K.endedAt,elapsedMs:K.elapsedMs,pausedMs:K.pausedMs},course:W,appName:_,apiEnv:F,email:H,timebackId:Z,runId:x}}import*as h from"zod";import*as b2 from"zod";var V0=b2.object({subject:x$,grade:U$}),k0=b2.object({code:E}),M2=b2.union([V0,k0]);class B2 extends Error{code;selector;count;constructor($,J,Z){super($);this.code=$,this.selector=J,this.count=Z}get selectorDescription(){if("grade"in this.selector)return`${this.selector.subject} grade ${this.selector.grade}`;return`code "${this.selector.code}"`}}function j2($,J){let Z;if("grade"in J)Z=$.filter((H)=>H.subject===J.subject&&H.grade===J.grade);else Z=$.filter((H)=>H.courseCode===J.code);if(Z.length===0)throw new B2("unknown_course",J);if(Z.length>1)throw new B2("ambiguous_course",J,Z.length);return Z[0]}var z2=R("handlers:activity:schema"),q0=h.object({totalQuestions:h.number().int().nonnegative().optional(),correctQuestions:h.number().int().nonnegative().optional(),xpEarned:h.number(),masteredUnits:h.number().int().nonnegative().optional()}).superRefine(o2);function C0($){return Math.min(100,Math.max(0,$))}function s2($){if("grade"in $)return`${$.subject} grade ${$.grade}`;return`code "${$.code}"`}var A0=h.object({id:E,name:E,course:M2,runId:h.string().uuid(),startedAt:h.iso.datetime(),endedAt:h.iso.datetime(),elapsedMs:h.number().int().nonnegative(),pausedMs:h.number().int().nonnegative()});function M$($,J,Z){let H=A0.safeParse($);if(!H.success)return{ok:!1,response:M("INVALID_PAYLOAD","Invalid payload",400,{details:H.error.flatten()})};let K=H.data,W;try{W=j2(J.courses,K.course)}catch(F){if(F instanceof B2){let O=s2(K.course);if(F.code==="unknown_course")return z2.warn("Unknown course selector",{selector:K.course}),{ok:!1,response:M("UNKNOWN_COURSE",`Unknown course: ${O}`,400)};return z2.error("Ambiguous course selector",{selector:K.course}),{ok:!1,response:M("AMBIGUOUS_COURSE_SELECTOR","Ambiguous course selector in timeback.config.json",500)}}throw F}let _=h2(J,W,Z);if(!_){let F=s2(K.course);return z2.error("Missing sensor for course",{selector:K.course}),{ok:!1,response:M("MISSING_SENSOR",`Course "${F}" has no sensor configured.`,500)}}return{ok:!0,payload:K,course:W,sensor:_}}var z0=h.object({id:E,name:E,course:M2,process:h.boolean().optional(),runId:h.string().uuid(),endedAt:h.iso.datetime(),metrics:q0,pctComplete:h.number().optional().transform(($)=>$===void 0?void 0:C0($))});function j$($,J,Z){let H=z0.safeParse($);if(!H.success)return{ok:!1,response:M("INVALID_PAYLOAD","Invalid payload",400,{details:H.error.flatten()})};let K=H.data,W;try{W=j2(J.courses,K.course)}catch(F){if(F instanceof B2){let O=s2(K.course);if(F.code==="unknown_course")return z2.warn("Unknown course selector",{selector:K.course}),{ok:!1,response:M("UNKNOWN_COURSE",`Unknown course: ${O}`,400)};return z2.error("Ambiguous course selector",{selector:K.course}),{ok:!1,response:M("AMBIGUOUS_COURSE_SELECTOR","Ambiguous course selector in timeback.config.json",500)}}throw F}let _=h2(J,W,Z);if(!_){let F=s2(K.course);return z2.error("Missing sensor for course",{selector:K.course}),{ok:!1,response:M("MISSING_SENSOR",`Course "${F}" has no sensor configured.`,500)}}return{ok:!0,payload:K,course:W,sensor:_}}import{getServiceUrlsForEnv as z$}from"@timeback/core";var y8=R("handlers:activity:attempts");async function L$($,J){let Z=[$,J].join("_");return`caliper_${await S2(Z)}`}function P0($,J){return $.find((Z)=>Z.scoreDate===J)}function T0($){let J=0;for(let Z of $){let K=Z.metadata?.attempt;if(typeof K==="number"&&K>J)J=K}return J}function R0($){let J=$.metadata;return typeof J?.attempt==="number"&&J.attempt>=1?J.attempt:1}async function V$($,J,Z,H){let K;try{K=await $.oneroster.assessmentResults.listAll({where:{status:"active","assessmentLineItem.sourcedId":J,"student.sourcedId":Z}})}catch{return y8.debug("No existing results found (line item may not exist yet)",{lineItemId:J}),1}if(K.length===0)return 1;let W=P0(K,H);if(W){let O=R0(W);return y8.debug("Retry detected, reusing attempt number",{lineItemId:J,timebackId:Z,endedAt:H,attempt:O}),O}let _=T0(K),F=_+1;return y8.debug("New attempt computed",{lineItemId:J,timebackId:Z,endedAt:H,maxAttempt:_,nextAttempt:F}),F}var k$=R("handlers:activity:completion");async function C$($){let{client:J,courseId:Z,timebackId:H,pctComplete:K,appName:W}=$;if(K!==100)return;let _=q$(Z),F=`timeback_sdk_${await S2(`mastery-completion_${Z}`)}`,O=`timeback_sdk_${await S2(`mastery-completion_${Z}_${H}`)}`;try{let x=!1;try{await J.oneroster.assessmentLineItems(F).get(),x=!0}catch{}if(!x)await J.oneroster.assessmentLineItems.create({sourcedId:F,title:`${W}: Complete`,status:"active",course:{sourcedId:_.course},componentResource:{sourcedId:_.componentResource},resultValueMin:0,resultValueMax:100,metadata:{appName:W}});let V=new Date().toISOString();await J.oneroster.assessmentResults.upsert(O,{status:"active",assessmentLineItem:{sourcedId:F},student:{sourcedId:H},score:100,scoreDate:V,scoreStatus:"fully graded",metadata:{isMasteryCompletion:!0,completedAt:V,appName:W}}),k$.debug("Created mastery completion entry",{courseId:Z,timebackId:H,lineItemId:F,resultId:O})}catch(x){let V=x instanceof Error?x.message:"Unknown error";k$.error("Failed to create mastery completion entry",{courseId:Z,timebackId:H,lineItemId:F,error:V})}}import{aggregateActivityMetrics as N0}from"@timeback/core/utils";var P2=R("handlers:activity:progress");function I0($,J){let Z=u(J),H=$.overrides?.[Z]?.metadata?.metrics,K=$.metadata?.metrics;return H?.totalLessons??K?.totalLessons}function b0($,J){let Z=$/J*100;return Math.min(100,Math.max(0,Math.round(Z)))}async function A$($){let{client:J,courseId:Z,timebackId:H,payload:K,course:W,env:_}=$;if(K.pctComplete!==void 0)return;let F=K.metrics.masteredUnits;if(typeof F!=="number"||F<=0)return;let O=I0(W,_);if(!O||O<=0){P2.debug("Skipping progress computation: totalLessons not configured",{courseId:Z});return}let x;try{x=(await J.edubridge.enrollments.list({userId:H})).find((N)=>N.course.id===Z)?.id}catch(z){let N=z instanceof Error?z.message:"Unknown error";P2.warn("Failed to fetch enrollments for progress computation",{courseId:Z,timebackId:H,error:N});return}if(!x){P2.warn("Skipping progress computation: enrollment not found for student/course",{courseId:Z,timebackId:H});return}let V=0;try{let z=await J.edubridge.analytics.getEnrollmentFacts({enrollmentId:x});V=N0(z.facts).masteredUnits}catch(z){let N=z instanceof Error?z.message:"Unknown error";P2.warn("Failed to fetch enrollment facts for progress computation",{courseId:Z,timebackId:H,enrollmentId:x,error:N});return}let A=!0;try{if((await J.edubridge.analytics.getWeeklyFacts({studentId:H,weekDate:K.endedAt})).some((I)=>{if(I.activityId!==K.id)return!1;if(I.enrollmentId&&I.enrollmentId===x)return!0;if(I.courseId&&I.courseId===Z)return!0;return!1}))A=!1}catch(z){let N=z instanceof Error?z.message:"Unknown error";P2.warn("Failed to fetch weekly facts for retry-safe progress computation",{courseId:Z,timebackId:H,enrollmentId:x,activityId:K.id,error:N}),A=!1}let C=V+(A?F:0),q=b0(C,O);return P2.debug("Computed pctComplete",{courseId:Z,timebackId:H,enrollmentId:x,historicalMasteredUnits:V,currentMasteredUnits:F,shouldIncludeCurrentMasteredUnits:A,totalMastered:C,totalLessons:O,pctComplete:q}),{pctComplete:q}}var f8=R("handlers:activity:submit"),h0={computeProgress:A$,maybeWriteCompletionEntry:C$};function P$($,J){return $.timebackId??_2({email:$.email,client:J})}async function n2($,J,Z=h0){let H=u($.env),{userInfo:K,payload:W,course:_,sensor:F,preview:O=!1,runId:x}=J,V=_.ids?.[H];if(!V)throw new W2(_,H);let A=$.getClient(),C=await P$(K,A),q=W;if(W.pctComplete===void 0){let y2=await Z.computeProgress({client:A,courseId:V,timebackId:C,payload:W,course:_,env:$.env});if(y2)q={...W,pctComplete:y2.pctComplete}}let z;if(!O){let y2=v8(F,q.course,q.id),LJ=await L$(y2,V);z=await V$(A,LJ,C,q.endedAt)}let I=z$(H).oneroster,r=w$({sensor:F,timebackId:C,email:K.email,payload:q,process:q.process,course:_,appName:$.appConfig.name,apiEnv:H,onerosterBaseUrl:I,attempt:z,runId:x}),Y2=$.hooks?.beforeActivitySend,v2=Y2?await Y2(r):r,p=v2??r;if(O||v2===null)return{success:!0,preview:!0,sensor:p.sensor,actor:p.actor,object:p.object,event:p.event};return await A.caliper.events.send(p.sensor,[p.event]),await Z.maybeWriteCompletionEntry({client:A,courseId:V,timebackId:p.timebackId,pctComplete:p.payload.pctComplete,appName:p.appName}),f8.debug("Recorded completion",{courseSelector:W.course,activityId:W.id}),{success:!0}}async function T$($,J){let Z=u($.env),{userInfo:H,payload:K,course:W,sensor:_,runId:F}=J;if(!W.ids?.[Z])throw new W2(W,Z);let x=$.getClient(),V=await P$(H,x),C=z$(Z).oneroster,q=i2({sensor:_,timebackId:V,email:H.email,payload:K,course:W,appName:$.appConfig.name,apiEnv:Z,onerosterBaseUrl:C,runId:F}),z=$.hooks?.beforeTimeSpentSend,N=z?await z(q):q,I=N??q;if(N===null){f8.debug("Hook skipped time-spent send",{activityId:K.id});return}await x.caliper.events.send(I.sensor,[I.event]),f8.debug("Sent time-spent event",{activityId:K.id,elapsedMs:K.elapsedMs})}var E2=R("handlers:activity:submit");async function T2($,J){if($.mode==="custom"){let H=await $.getEmail(J);return H?{email:H}:void 0}let Z=await $.getUser(J);return Z?{email:Z.email,timebackId:Z.id}:void 0}function r2($){return async(J)=>{let Z=await T2($.identity,J);if(!Z)return M("UNAUTHORIZED","Unauthorized",401);let H=j$(await J.json(),$.appConfig,$.env);if(!H.ok)return H.response;let{payload:K,course:W,sensor:_}=H,F={id:K.id,name:K.name,course:K.course,process:K.process,endedAt:K.endedAt,metrics:K.metrics,pctComplete:K.pctComplete};try{if((await n2({env:$.env,api:$.api,appConfig:$.appConfig,getClient:$.getClient,hooks:$.hooks},{userInfo:Z,payload:F,course:W,sensor:_,preview:!1,runId:K.runId})).preview)return P({preview:!0});return E2.debug("Submitted activity",{runId:K.runId,activityId:K.id}),new Response(null,{status:204})}catch(O){if(O instanceof d)return E2.warn("Failed to resolve Timeback user",{code:O.code}),M("USER_RESOLUTION_FAILED","Unable to resolve Timeback identity",F2(O));if(O instanceof W2)return E2.warn("Course not synced",{course:O.course,env:O.env}),M("MISSING_SYNCED_COURSE_ID",O.message,503);if(O instanceof a2)return E2.error("Invalid sensor URL",{sensor:O.sensor}),M("INVALID_SENSOR_URL",O.message,500);let x=O instanceof Error?O.message:"Unknown error";return E2.error("Failed to submit activity",{error:x}),M("INTERNAL_ERROR",x,502)}}}var R2=R("handlers:activity:heartbeat"),t2=new Map,E0=300000;function v0(){let $=Date.now();for(let[J,Z]of t2)if($-Z>E0)t2.delete(J)}function y0($){return v0(),t2.has($)}function R$($){t2.set($,Date.now())}function e2($){return async(J)=>{let Z=await T2($.identity,J);if(!Z)return M("UNAUTHORIZED","Unauthorized",401);let H=M$(await J.json(),$.appConfig,$.env);if(!H.ok)return H.response;let{payload:K,course:W,sensor:_}=H,F=new Date(K.startedAt).getTime(),O=`${K.runId}:${F}`;if(y0(O))return R2.debug("Duplicate heartbeat, skipping",{runId:K.runId,windowKey:O}),P({duplicate:!0});let x=u($.env);if(!W.ids?.[x]){let C=new W2(W,x);return R2.warn("Course not synced",{course:K.course,env:x}),M("MISSING_SYNCED_COURSE_ID",C.message,503)}let A=$.getClient();try{let C=Z.timebackId??await _2({email:Z.email,client:A}),z=S0(x).oneroster,N=i2({sensor:_,timebackId:C,email:Z.email,payload:K,course:W,appName:$.appConfig.name,apiEnv:x,onerosterBaseUrl:z,runId:K.runId}),I=$.hooks?.beforeTimeSpentSend,r=I?await I(N):N,Y2=r??N;if(r===null)return R$(O),R2.debug("Hook skipped heartbeat send",{runId:K.runId}),new Response(null,{status:204});return await A.caliper.events.send(Y2.sensor,[Y2.event]),R$(O),R2.debug("Sent heartbeat",{runId:K.runId,activityId:K.id,elapsedMs:K.elapsedMs}),new Response(null,{status:204})}catch(C){if(C instanceof d)return R2.warn("Failed to resolve Timeback user",{code:C.code}),M("USER_RESOLUTION_FAILED","Unable to resolve Timeback identity",F2(C));let q=C instanceof Error?C.message:"Unknown error";return R2.error("Failed to send heartbeat",{error:q}),M("INTERNAL_ERROR",q,502)}}}async function g$($,J,Z){if(Z.mode!=="sso")return L2.warn("SSO not configured"),P({error:"SSO not configured"},400);return await v$({req:$,env:J,clientId:Z.clientId,issuer:Z.issuer,redirectUri:Z.redirectUri,buildState:Z.buildState})}async function f0($,J,Z,H,K,W,_){try{let F=W.issuer??N$(K),O=f$(J,W.redirectUri);L2.debug("Exchanging auth code for tokens",{issuer:F,clientId:W.clientId});let x=await I$({issuer:F,clientId:W.clientId,clientSecret:W.clientSecret,code:$,redirectUri:O}),V=await b$({issuer:F,accessToken:x.access_token}),A=typeof V.identities==="string"?JSON.parse(V.identities):V.identities;L2.debug("SSO completed, resolving Timeback user",{user:{...V,identities:A}});let C=await O2({env:K,apiCredentials:_.credentials,userInfo:V,client:_.getClient()});L2.debug("Timeback user resolved",{timebackId:C.id});let q={user:C,idp:{tokens:x,userInfo:V},state:Z,req:H,redirect:$8,json:P};return W.onCallbackSuccess(q)}catch(F){let O=F instanceof Error?F:Error("Unknown error"),x=F instanceof d?F.code:"token_exchange_failed";if(L2.error("SSO callback failed",{error:O.message,errorCode:x}),W.onCallbackError)return W.onCallbackError(h$(O,x,Z,H));if(F instanceof d)return P({error:O.message},F2(F));return P({error:O.message},500)}}async function d$($,J,Z,H){if(Z.mode!=="sso")return L2.warn("SSO not configured"),P({error:"SSO not configured"},400);let{url:K,code:W,errorParam:_,state:F}=y$($);if(_)return S$(_,K,F,$,Z.onCallbackError);if(!W)return E$(F,$,Z.onCallbackError);return await f0(W,K,F,$,J,Z,H)}function J8($){let{env:J,identity:Z}=$;return(H)=>g$(H,J,Z)}function Z8($){let{env:J,identity:Z,api:H}=$;return(K)=>d$(K,J,Z,H)}function H8(){return()=>$8("/")}var m$=($)=>{return async(J)=>{return await $.getClient().powerpath.assessments.getAssessmentProgress({student:J.student,lesson:J.lesson,attempt:J.attempt})}};var l$=($)=>{return async(J)=>{return(await $.getClient().powerpath.assessments.getAttempts({student:J.student,lesson:J.lesson})).attempts.map((H)=>({attempt:H.attempt??void 0,score:H.score,startedAt:H.startedAt??void 0,completedAt:H.completedAt??void 0,scoreStatus:H.scoreStatus}))}};var u$=($)=>{return async(J)=>{let Z=$.getClient().powerpath.assessments,H=await Z.getAssessmentProgress({student:J.student,lesson:J.lesson}),K;if(H.lessonType!=="powerpath-100"&&H.finalized!==!0){try{K=await Z.finalStudentAssessmentResponse({student:J.student,lesson:J.lesson})}catch{}H=await Z.getAssessmentProgress({student:J.student,lesson:J.lesson})}let W=H.lessonType==="powerpath-100"?!0:H.finalized===!0;return{...K??{},score:H.score??0,totalQuestions:H.totalQuestions,correctQuestions:H.correctQuestions,accuracy:H.accuracy,finalized:W}}};function c$($){let J=$.metadata?.questionCount;return typeof J==="number"?J:void 0}function K8($){return{id:$.id,title:$.title,difficulty:$.difficulty,content:$.content?{rawXml:$.content.rawXml}:void 0,index:$.index,url:$.url,humanApproved:$.humanApproved,response:$.response,responses:$.responses,correct:$.correct,result:$.result,resultId:$.resultId,learningObjectives:$.learningObjectives}}function p$($,J){if(!J)return{lessonId:$,lessonType:"quiz",score:0,seenQuestions:0,finalized:!1};return{lessonId:$,lessonType:J.lessonType,attempt:J.attempt,score:J.score??0,questionCount:J.totalQuestions,seenQuestions:J.lessonType==="powerpath-100"?J.seenQuestions.length:0,finalized:J.lessonType==="powerpath-100"?!1:J.finalized}}function a$($){let J=$.questions,Z=J.filter((H)=>H.response!==void 0).map((H)=>H.id);return{questions:J.map(K8),answeredIds:Z,score:$.score??0,finalized:$.finalized,complete:$.finalized}}function g0($){if($.lessonType==="powerpath-100")return $.responseResult.isCorrect;return!1}function d0($){if($.lessonType==="powerpath-100")return $.powerpathScore;return 0}function i$($){let J=d0($);return{correct:g0($),score:J,complete:$.lessonType==="powerpath-100"&&J>=100,questionResult:$.questionResult}}function s$($,J){return Array.from(new Set($.map((Z)=>Z.ids?.[J]).filter((Z)=>Boolean(Z))))}function o$($){return String($.sourcedId??"")}var n$=($)=>{return async(J={})=>{let Z=$.getClient(),H=u($.env),K;if(J.course){let F=j2($.appConfig.courses,J.course).ids?.[H];K=F?[F]:[]}else K=s$($.appConfig.courses,H);let W=[];for(let _ of K){let F=await Z.oneroster.courses(_).components({where:{status:"active"}}),O=g8(F);for(let x of O){let V=o$(x);if(!V)continue;let A=await Z.oneroster.courses.componentResources({where:{"courseComponent.sourcedId":V,status:"active"}}),C=g8(A);for(let q of C){if(!q.sourcedId)continue;let z=q.metadata??{},N=c$(q);W.push({id:q.sourcedId,name:q.title??q.sourcedId,type:z.lessonType??"quiz",courseId:_,questionCount:N,metadata:z})}}}return W}};class X8 extends Error{name="LessonTypeMismatchError"}var r$=($)=>{return async(J)=>{let Z=$.getClient().powerpath.assessments;if(J.lessonType==="powerpath-100"){let K=await Z.getNextQuestion({student:J.student,lesson:J.lesson});return K8(K.question)}let H=await Z.getAssessmentProgress({student:J.student,lesson:J.lesson});if(H.lessonType==="powerpath-100"){if(J.lessonType!==void 0)throw new X8(`Expected quiz progress but got powerpath-100 for lesson ${J.lesson}`);let K=await Z.getNextQuestion({student:J.student,lesson:J.lesson});return K8(K.question)}return a$(H)}};var m0=R("lessons:start"),t$=($)=>{return async(J)=>{let Z=$.getClient().powerpath.assessments,H=J.lesson,K=J.student,W=await Z.getAssessmentProgress({student:K,lesson:H});if(J.forceNew){if(W.lessonType!=="powerpath-100"&&W.finalized!==!0)try{await Z.finalStudentAssessmentResponse({student:K,lesson:H})}catch{}try{await Z.createNewAttempt({student:K,lesson:H}),W=await Z.getAssessmentProgress({student:K,lesson:H})}catch(_){m0.warn("Failed to create new lesson attempt",{lessonId:H,error:_})}}else if(W.lessonType!=="powerpath-100"&&W.finalized!==!0&&(W.questions?.length??0)===0)try{await Z.createNewAttempt({student:K,lesson:H}),W=await Z.getAssessmentProgress({student:K,lesson:H})}catch{}return p$(H,W)}};var e$=($)=>{return async(J)=>{let H=await $.getClient().powerpath.assessments.updateStudentQuestionResponse({student:J.student,lesson:J.lesson,question:J.question,responses:{RESPONSE:J.response}});return i$(H)}};function m($){return{list:n$($),start:t$($),next:r$($),submit:e$($),complete:u$($),attempts:l$($),attemptDetails:m$($)}}async function a($,J){let Z=await T2($.identity,J);if(!Z)return null;if(Z.timebackId)return Z.timebackId;return await _2({email:Z.email,client:$.getClient()})}async function $J($,J){let Z=await T2($.identity,J);return Boolean(Z)}var l0=R("handlers:lessons");function c($,J){if($ instanceof d)return M("USER_RESOLUTION_FAILED","Unable to resolve Timeback identity",F2($));if($ instanceof X8)return M("LESSON_TYPE_MISMATCH",$.message,400);let Z=$ instanceof Error?$.message:"Unknown error";return l0.error(J,{error:Z}),M("INTERNAL_ERROR",Z,500)}import*as i from"zod";var u0=i.object({course:M2.optional()}).partial(),c0=i.object({lessonId:E,forceNew:i.boolean().optional()}),p0=i.object({lessonId:E,lessonType:E.optional()}),a0=i.object({lessonId:E,questionId:E,response:E}),i0=i.object({lessonId:E}),s0=i.object({lessonId:E}),o0=i.object({lessonId:E,attempt:i.number().int().positive()});async function n0($){try{let J=await $.json();if(!J||typeof J!=="object"||Array.isArray(J))return null;return J}catch{return null}}async function V2($,J){let Z=await n0($);if(!Z)return{ok:!1,response:M("INVALID_PAYLOAD","Invalid JSON body",400)};let H=J.safeParse(Z);if(!H.success)return{ok:!1,response:M("INVALID_PAYLOAD","Invalid payload",400,{details:H.error.flatten()})};return{ok:!0,payload:H.data}}async function JJ($){return await V2($,u0)}async function ZJ($){return await V2($,c0)}async function HJ($){return await V2($,p0)}async function KJ($){return await V2($,a0)}async function XJ($){return await V2($,i0)}async function WJ($){return await V2($,s0)}async function YJ($){return await V2($,o0)}function W8($){let J=m($);return async(Z)=>{try{let H=await YJ(Z);if(!H.ok)return H.response;let K=await a($,Z);if(!K)return M("UNAUTHORIZED","Unauthorized",401);let W=await J.attemptDetails({lesson:H.payload.lessonId,attempt:H.payload.attempt,student:K});return P(W)}catch(H){return c(H,"Failed to fetch lesson attempt details")}}}function Y8($){let J=m($);return async(Z)=>{try{let H=await WJ(Z);if(!H.ok)return H.response;let K=await a($,Z);if(!K)return M("UNAUTHORIZED","Unauthorized",401);let W=await J.attempts({lesson:H.payload.lessonId,student:K});return P({attempts:W})}catch(H){return c(H,"Failed to list lesson attempts")}}}function Q8($){let J=m($);return async(Z)=>{try{let H=await XJ(Z);if(!H.ok)return H.response;let K=await a($,Z);if(!K)return M("UNAUTHORIZED","Unauthorized",401);let W=await J.complete({lesson:H.payload.lessonId,student:K});return P(W)}catch(H){return c(H,"Failed to complete lesson")}}}function G8($){let J=m($);return async(Z)=>{try{if(!await $J($,Z))return M("UNAUTHORIZED","Unauthorized",401);let H=await JJ(Z);if(!H.ok)return H.response;let K=await J.list({course:H.payload.course});return P({lessons:K})}catch(H){return c(H,"Failed to list lessons")}}}function B8($){let J=m($);return async(Z)=>{try{let H=await HJ(Z);if(!H.ok)return H.response;let K=await a($,Z);if(!K)return M("UNAUTHORIZED","Unauthorized",401);let W=await J.next({lesson:H.payload.lessonId,lessonType:H.payload.lessonType,student:K});return P(W)}catch(H){return c(H,"Failed to fetch next lesson question")}}}function _8($){let J=m($);return async(Z)=>{try{let H=await ZJ(Z);if(!H.ok)return H.response;let K=await a($,Z);if(!K)return M("UNAUTHORIZED","Unauthorized",401);let W=await J.start({lesson:H.payload.lessonId,student:K,forceNew:H.payload.forceNew});return P(W)}catch(H){return c(H,"Failed to start lesson")}}}function F8($){let J=m($);return async(Z)=>{try{let H=await KJ(Z);if(!H.ok)return H.response;let K=await a($,Z);if(!K)return M("UNAUTHORIZED","Unauthorized",401);let W=await J.submit({lesson:H.payload.lessonId,question:H.payload.questionId,response:H.payload.response,student:K});return P(W)}catch(H){return c(H,"Failed to submit lesson answer")}}}function QJ($,J){let Z=new Map;for(let H of $){let K=H.ids?.[J];if(K)Z.set(K,H)}return Z}function GJ($,J){return $.map((Z)=>{let H=J.get(Z.course.id);return{id:Z.course.id,code:H?.courseCode??Z.course.id,name:Z.course.title}})}function BJ($){return $.map((J)=>J.metadata?.goals).find(Boolean)}function _J($){let J=new Date(Date.UTC($.getUTCFullYear(),$.getUTCMonth(),$.getUTCDate())),Z=new Date(Date.UTC($.getUTCFullYear(),$.getUTCMonth(),$.getUTCDate(),23,59,59,999));return{start:J,end:Z}}function d8($){return Object.values($).reduce((J,Z)=>{return J+Object.values(Z).reduce((H,K)=>{return H+(K.activityMetrics?.xpEarned??0)},0)},0)}async function O8($,J,Z,H){let K=await $.edubridge.enrollments.list({userId:J.id}),W=QJ(Z.courses,H),_=GJ(K,W),F=BJ(K),{start:O,end:x}=_J(new Date),[V,A]=await Promise.all([$.edubridge.analytics.getActivity({studentId:J.id,startDate:O.toISOString(),endDate:x.toISOString()}),$.edubridge.analytics.getActivity({studentId:J.id,startDate:"2000-01-01",endDate:x.toISOString()})]);return{id:J.id,email:J.email,name:J.name,school:J.school,grade:J.grade,courses:_.length?_:void 0,goals:F,xp:{today:d8(V.facts),all:d8(A.facts)}}}var m8=R("handlers:user");async function r0($,J){if($.mode==="custom"){let H=await $.getEmail(J);if(!H)return;return{sub:H,email:H}}let Z=await $.getUser(J);if(!Z)return;return{sub:Z.id,email:Z.email}}function t0($){if(m8.warn("Timeback user resolution failed",{code:$.code}),$.code==="timeback_user_ambiguous")return M("USER_AMBIGUOUS","Timeback user resolution ambiguous",409);if($.code==="timeback_user_not_found")return M("USER_NOT_FOUND","Timeback user not found",404);return M("USER_RESOLUTION_FAILED",$.message,502)}function D8($){return async(J)=>{try{let Z=await r0($.identity,J);if(!Z)return M("UNAUTHORIZED","Unauthorized",401);let H=u($.env),K=$.getClient();try{let W=await O2({env:$.env,apiCredentials:$.api,userInfo:Z,client:K}),_=await O8(K,W,$.appConfig,H);return P(_)}catch(W){if(W instanceof d)return t0(W);let _=W instanceof Error?W.message:"Unknown error";return m8.error("Failed to build user profile",{error:_}),M("INTERNAL_ERROR",_,502)}}catch(Z){let H=Z instanceof Error?Z.message:"Unknown error";return m8.error("Unhandled error in user handler",{error:H}),M("INTERNAL_ERROR",H,500)}}}var l8=R("handlers:user:verify");async function e0($,J){if($.mode==="custom"){let H=await $.getEmail(J);if(!H)return;return{sub:H,email:H}}let Z=await $.getUser(J);if(!Z)return;return{sub:Z.id,email:Z.email}}function w8($){return async(J)=>{try{let Z=await e0($.identity,J);if(!Z)return M("UNAUTHORIZED","Unauthorized",401);let H=$.getClient();try{let K=await O2({env:$.env,apiCredentials:$.api,userInfo:Z,client:H});return P({verified:!0,timebackId:K.id})}catch(K){if(K instanceof d){if(l8.warn("Timeback user resolution failed",{code:K.code}),K.code==="timeback_user_ambiguous")return M("USER_AMBIGUOUS","Timeback user resolution ambiguous",409);if(K.code==="timeback_user_not_found")return P({verified:!1});return M("USER_RESOLUTION_FAILED",K.message,502)}let W=K instanceof Error?K.message:"Unknown error";return l8.error("Failed to verify user",{error:W}),M("INTERNAL_ERROR",W,502)}}catch(Z){let H=Z instanceof Error?Z.message:"Unknown error";return l8.error("Unhandled error in verify handler",{error:H}),M("INTERNAL_ERROR",H,500)}}}import*as T from"zod";var $1=T.object({email:T.email(),timebackId:T.string().optional()}),J1=T.object({id:E,name:E,course:M2}),Z1=T.object({totalQuestions:T.number().int().nonnegative().optional(),correctQuestions:T.number().int().nonnegative().optional(),xpEarned:T.number(),masteredUnits:T.number().int().nonnegative().optional(),pctComplete:T.number().min(0).max(100).optional()}).superRefine(o2),H1=T.object({startedAt:T.union([T.iso.datetime(),T.date()]).optional(),endedAt:T.union([T.iso.datetime(),T.date()]).optional(),activeMs:T.number().int().nonnegative().optional(),inactiveMs:T.number().int().nonnegative().optional()}),K1=T.uuid().optional(),FJ=T.object({user:$1,activity:J1,metrics:Z1,time:H1.optional(),runId:K1});var OJ=R("activity:record");class DJ extends Error{code="VALIDATION_ERROR";details;constructor($,J){super($);this.name="ActivityRecordValidationError",this.details=J}}class u8 extends Error{code="COURSE_ERROR";constructor($){super($);this.name="ActivityRecordCourseError"}}function X1($){let J=$.time?.endedAt?typeof $.time.endedAt==="string"?$.time.endedAt:$.time.endedAt.toISOString():new Date().toISOString();return{id:$.activity.id,name:$.activity.name,course:$.activity.course,endedAt:J,metrics:{totalQuestions:$.metrics.totalQuestions,correctQuestions:$.metrics.correctQuestions,xpEarned:$.metrics.xpEarned,masteredUnits:$.metrics.masteredUnits},pctComplete:$.metrics.pctComplete}}function W1($,J){let Z=$.time,H=Z.activeMs??0,K=Z.inactiveMs??0,W;if(Z.startedAt)W=typeof Z.startedAt==="string"?Z.startedAt:Z.startedAt.toISOString();else if(Z.activeMs!==void 0||Z.inactiveMs!==void 0){let _=new Date(J),F=H+K;W=new Date(_.getTime()-F).toISOString()}else W=J;return{id:$.activity.id,name:$.activity.name,course:$.activity.course,startedAt:W,endedAt:J,elapsedMs:H,pausedMs:K}}function Y1($,J,Z){let H;try{H=j2($.courses,J)}catch(W){if(W instanceof B2)throw new u8(W.code==="unknown_course"?`Unknown course: ${JSON.stringify(J)}`:"Ambiguous course selector in timeback.config.json");throw W}let K=h2($,H,Z);if(!K)throw new u8(`Course "${JSON.stringify(J)}" has no sensor configured.`);return{course:H,sensor:K}}var Q1={recordCompletion:n2,sendTimeSpent:T$};function c8($,J=Q1){return async(Z)=>{let H=FJ.safeParse(Z);if(!H.success)throw OJ.warn("Invalid record input",{error:H.error.flatten()}),new DJ("Invalid activity record input",H.error.flatten());let K=H.data,{course:W,sensor:_}=Y1($.appConfig,K.activity.course,$.env),F=X1(K),O={env:$.env,api:$.api,appConfig:$.appConfig,getClient:$.getClient,hooks:$.hooks};if(await J.recordCompletion(O,{userInfo:{email:K.user.email,timebackId:K.user.timebackId},payload:F,course:W,sensor:_,preview:!1,runId:K.runId}),K.time){let x=W1(K,F.endedAt);await J.sendTimeSpent(O,{userInfo:{email:K.user.email,timebackId:K.user.timebackId},payload:x,course:W,sensor:_,runId:K.runId})}OJ.debug("Recorded activity",{activityId:K.activity.id,hasTime:!!K.time})}}var x8=R("user:verify");function p8($){return async(J)=>{x8.debug("Verifying user by email");let Z=$.getClient();try{let H=await _2({email:J,client:Z});return x8.debug("User verified",{timebackId:H}),{verified:!0,timebackId:H}}catch(H){if(H instanceof d){if(H.code==="timeback_user_not_found")return x8.debug("User not found in Timeback"),{verified:!1};throw H}let K=H instanceof Error?H.message:"Unknown error";throw x8.error("Failed to verify user",{error:K}),H}}}var a8=R("user:getProfile");function i8($){return async(J)=>{a8.debug("Building user profile by email");let Z=$.getClient(),H=u($.env);try{let K=await O2({env:$.env,apiCredentials:$.api,userInfo:{sub:J,email:J},client:Z}),W=await O8(Z,K,$.appConfig,H);return a8.debug("User profile built",{userId:W.id}),W}catch(K){if(K instanceof d)throw K;let W=K instanceof Error?K.message:"Unknown error";throw a8.error("Failed to build user profile",{error:W}),K}}}async function B1($){let{loadConfig:J}=await import("./chunk-jgp0bayr.js");return await J($)}function _1($){return $.map((J)=>{if(J.grade!==void 0)return J;if(J.courseCode)return J;throw Error(`Invalid course config: missing both grade and courseCode for subject "${J.subject}"`)})}async function MJ($){if(!globalThis.process?.versions?.node&&!globalThis.Bun)throw Error("createTimeback() requires Node.js or Bun — it reads timeback.config.json from the filesystem. "+"For edge runtimes (Cloudflare Workers, Vercel Edge, etc.), use createTimebackIdentity() from '@timeback/sdk' instead.");wJ({logger:$.logger,logLevel:$.logLevel});let J=xJ($.env),Z=await B1({configPath:$.configPath});if(!Z.success)throw Error(`Failed to load timeback config: ${Z.error}`);let H=Z.config,K,W=()=>{if(!K)K=new G1({env:u(J),auth:{clientId:$.api.clientId,clientSecret:$.api.clientSecret}});return K},_=$.hooks,F=(V,A)=>UJ(V,_,A),O={env:J,identity:$.identity,appConfig:{name:H.name,sensor:H.sensor,launchUrl:H.launchUrl,courses:_1(H.courses)},api:$.api,getClient:W,hooks:_},x={env:J,identity:$.identity,api:{credentials:$.api,getClient:W}};return{config:$,handle:{activity:{heartbeat:F("activity.heartbeat",e2(O)),submit:F("activity.submit",r2(O))},identity:{signIn:F("identity.signIn",J8(x)),callback:F("identity.callback",Z8(x)),signOut:H8()},lessons:{list:F("lessons.list",G8(O)),start:F("lessons.start",_8(O)),next:F("lessons.next",B8(O)),submit:F("lessons.submit",F8(O)),complete:F("lessons.complete",Q8(O)),attempts:F("lessons.attempts",Y8(O)),attemptDetails:F("lessons.attemptDetails",W8(O))},user:{me:F("user.me",D8(O)),verify:F("user.verify",w8(O))}},activity:{record:c8({...O})},lessons:m({...O}),user:{verify:p8({...O}),getProfile:i8({...O})},get api(){return W()},close(){if(K)K.close(),K=void 0}}}import{TimebackClient as mK}from"@timeback/core";import{ApiError as uK,ForbiddenError as cK,isApiError as pK,NotFoundError as aK,UnauthorizedError as iK,ValidationError as sK}from"@timeback/core";export{O1 as toNativeHandler,pK as isApiError,jJ as createTimebackIdentity,MJ as createTimeback,sK as ValidationError,iK as UnauthorizedError,mK as TimebackClient,F1 as ROUTES,aK as NotFoundError,cK as ForbiddenError,uK as ApiError};