@trayai/helix-sdk 1.13.2 → 1.15.0

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/CHANGELOG.md CHANGED
@@ -8,6 +8,36 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
8
8
  The SDK and [`@trayai/helix-cli`](https://www.npmjs.com/package/@trayai/helix-cli) are
9
9
  released together and share a version — install matching versions.
10
10
 
11
+ ## 1.14.0
12
+
13
+ ### Added
14
+
15
+ - **`ctx.identity.user.email` and `ctx.identity.user.name`.** `ctx.identity` is now
16
+ `{ user: { id, email, name } }` for requests made by logged-in users and project API
17
+ tokens, and is still `null` when there is no user (schedules, `ctx.callFunctionAsync`
18
+ runs, anonymous callers). `email` and `name` are `null` when the platform has no value
19
+ for them. `helix dev` has no sign-in flow, so `ctx.identity` is `null` locally. In tests,
20
+ pass an `identity` to `runWithContext` to set them.
21
+ - **`MockContext` type** (from `@trayai/helix-sdk/testing`) for typing `runWithContext`
22
+ fixtures; `identity.user.email` and `.name` are optional in it.
23
+
24
+ ### Changed
25
+
26
+ - **`TrayContext['identity']` and `PlatformContext['identity']` now require `email` and
27
+ `name`** (each `string | null`). This is a compile-time break for code that builds an
28
+ identity value, shipped in a minor release as a deliberate exception to the 1.0 promise:
29
+ reads are unaffected, nothing changes at runtime, the documented inline `runWithContext`
30
+ pattern still compiles, and the fix is one line. Affected: fixtures typed
31
+ `Partial<PlatformContext>` (the old `runWithContext` parameter type), hand-built
32
+ `TrayContext` or `PlatformContext` literals that set `identity`, handlers that assign
33
+ `ctx.identity = { user: { id } }`, and helpers whose return type is
34
+ `TrayContext['identity']`. Add `email` and `name`, or retype fixtures as `MockContext`.
35
+ `runWithContext` still accepts identity mocks without them, such as
36
+ `runWithContext({ identity: { user: { id } } }, …)`, and defaults both to `null`. Note
37
+ that `helix deploy` type-checks everything your `tsconfig.json` includes (`functions/**`
38
+ by default), so an affected fixture or helper there fails the deploy after upgrading
39
+ until it is updated.
40
+
11
41
  ## 1.13.2
12
42
 
13
43
  No user-visible changes in this release — co-versioned with `@trayai/helix-cli`'s changes.
package/README.md CHANGED
@@ -91,7 +91,7 @@ Every HTTP handler receives a `ctx` (`TrayContext`); scheduled handlers receive
91
91
  | `ctx.status(code)` | Set the response status |
92
92
  | `ctx.error(code, message)` | Throw an HTTP error mapped to that status |
93
93
  | `ctx.executionId` / `ctx.deploymentId` / `ctx.traceId` | Invocation identifiers |
94
- | `ctx.identity` | Minimal caller identity (`{ user: { id } }` or `null`) |
94
+ | `ctx.identity` | The caller's identity — `{ user: { id, email, name } }`, or `null` when no user is known. `email` and `name` are `null` when the platform has no value for them |
95
95
  | `ctx.request` | The raw underlying request event |
96
96
 
97
97
  ## Authenticated HTTP
@@ -615,14 +615,14 @@ const result = await runWithContext({ input: { name: 'Ada' } }, async () => {
615
615
  });
616
616
  ```
617
617
 
618
- The mock context is a Proxy: touching an always-present field (`http`, `db`, `log`, `executionId`, …) you didn't provide throws a descriptive error, so tests fail loudly — as does touching a field that isn't part of the context at all. Fields that aren't guaranteed on every execution (for example `userId` and `identity`) instead return `undefined` when unset, just as they can at runtime.
618
+ The mock context is a Proxy: touching an always-present field (`http`, `db`, `log`, `executionId`, …) you didn't provide throws a descriptive error, so tests fail loudly — as does touching a field that isn't part of the context at all. Fields that aren't guaranteed on every execution (for example `userId` and `identity`) instead return `undefined` when unset, just as they can at runtime. To test code that reads the caller's email or name, pass an identity: `runWithContext({ userId: 'u-1', identity: { user: { id: 'u-1', email: 'ada@example.com', name: 'Ada' } } }, …)`. In a mock identity, `email` and `name` may be omitted — they default to `null`, as in a real context. Type your own fixtures with the exported `MockContext`.
619
619
 
620
620
  ## Entry points
621
621
 
622
622
  | Import | Contents |
623
623
  |--------|----------|
624
624
  | `@trayai/helix-sdk` | `defineFunction`, `defineSchedule`, `defineConfig`, `getContext`, `loadConfig`, `requireWorkspaceId`, `createConfigService`, and the public types |
625
- | `@trayai/helix-sdk/testing` | `runWithContext` |
625
+ | `@trayai/helix-sdk/testing` | `runWithContext`, `MockContext` (type) |
626
626
 
627
627
  Key exported types include `TrayContext`, `ScheduleContext`, `ScheduleTrigger`, `TrayConfig`, `LoadedTrayConfig`, `HttpClient`, `KeyValueStore`, `FileSystemClient`, `Logger`, `ConfigService`, and `WorkspaceIdRequiredError`.
628
628
 
@@ -1 +1 @@
1
- import{A as u,B as d,D as p,F as m,G as c,H as k,I as g,J as b,j as l}from"../chunk-JKFMPHA4.js";import{z as s}from"zod";function v(e,t){let r=`${l(e).hosts.api}/private/v1/helix/authentications/templates`;return t==="dev"?`${r}/dev`:r}var h=s.object({templates:s.array(s.object({serviceName:s.string(),serviceVersion:s.number().int(),authenticationType:s.string(),strategy:s.string().optional()}))}),S=3e4;async function y(e){let t=new Headers;for(let[n,T]of Object.entries(e.credentialHeaders))t.set(n,T);let r=await fetch(e.templatesUrl,{method:"GET",headers:t,redirect:"manual",signal:AbortSignal.timeout(e.timeoutMs??S)}),a=await r.text(),o=a;try{o=JSON.parse(a)}catch{}if(r.ok){let n=h.safeParse(o);return n.success?{kind:"templates",result:n.data}:{kind:"brokerError",status:r.status,message:"malformed templates-discovery response",body:o}}let i=u.safeParse(o);return i.success?{kind:"brokerError",status:r.status,code:i.data.error.code,message:i.data.error.message,body:o}:{kind:"brokerError",status:r.status,message:a||`templates-discovery request failed with status ${r.status}`,body:o}}async function R(e){let t=p({authenticationId:e.authenticationId,method:e.method,url:e.url,body:e.body,headers:e.headers,query:e.query}),r=await c({proxyUrl:d(e.env,"dev"),credentialHeaders:{Authorization:`Bearer ${e.devToken}`},request:t,timeoutMs:e.timeoutMs??m});return r.kind==="brokerError"?{kind:"brokerError",brokerStatus:r.status,code:r.code,body:r.body}:{kind:"upstream",upstream:r.response}}async function f(e){k(e.url);let t=await b({signUrl:g(e.env,"dev"),credentialHeaders:{Authorization:`Bearer ${e.devToken}`},body:{authenticationId:e.authenticationId,url:e.url,...e.method!==void 0?{method:e.method}:{},...e.expiresIn!==void 0?{expiresIn:e.expiresIn}:{}},timeoutMs:e.timeoutMs});return t.kind==="brokerError"?{kind:"brokerError",brokerStatus:t.status,code:t.code,body:t.body}:{kind:"signed",signed:t.result}}async function x(e){let t=await y({templatesUrl:v(e.env,"dev"),credentialHeaders:{Authorization:`Bearer ${e.devToken}`},timeoutMs:e.timeoutMs});return t.kind==="brokerError"?{kind:"brokerError",brokerStatus:t.status,code:t.code,body:t.body}:{kind:"templates",templates:t.result.templates}}export{R as callBrokerDev,f as callS3SignDev,x as callTemplatesDev};
1
+ import{A as u,B as d,D as p,F as m,G as c,H as k,I as g,J as b,j as l}from"../chunk-LKZKDHYO.js";import{z as s}from"zod";function v(e,t){let r=`${l(e).hosts.api}/private/v1/helix/authentications/templates`;return t==="dev"?`${r}/dev`:r}var h=s.object({templates:s.array(s.object({serviceName:s.string(),serviceVersion:s.number().int(),authenticationType:s.string(),strategy:s.string().optional()}))}),S=3e4;async function y(e){let t=new Headers;for(let[n,T]of Object.entries(e.credentialHeaders))t.set(n,T);let r=await fetch(e.templatesUrl,{method:"GET",headers:t,redirect:"manual",signal:AbortSignal.timeout(e.timeoutMs??S)}),a=await r.text(),o=a;try{o=JSON.parse(a)}catch{}if(r.ok){let n=h.safeParse(o);return n.success?{kind:"templates",result:n.data}:{kind:"brokerError",status:r.status,message:"malformed templates-discovery response",body:o}}let i=u.safeParse(o);return i.success?{kind:"brokerError",status:r.status,code:i.data.error.code,message:i.data.error.message,body:o}:{kind:"brokerError",status:r.status,message:a||`templates-discovery request failed with status ${r.status}`,body:o}}async function R(e){let t=p({authenticationId:e.authenticationId,method:e.method,url:e.url,body:e.body,headers:e.headers,query:e.query}),r=await c({proxyUrl:d(e.env,"dev"),credentialHeaders:{Authorization:`Bearer ${e.devToken}`},request:t,timeoutMs:e.timeoutMs??m});return r.kind==="brokerError"?{kind:"brokerError",brokerStatus:r.status,code:r.code,body:r.body}:{kind:"upstream",upstream:r.response}}async function f(e){k(e.url);let t=await b({signUrl:g(e.env,"dev"),credentialHeaders:{Authorization:`Bearer ${e.devToken}`},body:{authenticationId:e.authenticationId,url:e.url,...e.method!==void 0?{method:e.method}:{},...e.expiresIn!==void 0?{expiresIn:e.expiresIn}:{}},timeoutMs:e.timeoutMs});return t.kind==="brokerError"?{kind:"brokerError",brokerStatus:t.status,code:t.code,body:t.body}:{kind:"signed",signed:t.result}}async function x(e){let t=await y({templatesUrl:v(e.env,"dev"),credentialHeaders:{Authorization:`Bearer ${e.devToken}`},timeoutMs:e.timeoutMs});return t.kind==="brokerError"?{kind:"brokerError",brokerStatus:t.status,code:t.code,body:t.body}:{kind:"templates",templates:t.result.templates}}export{R as callBrokerDev,f as callS3SignDev,x as callTemplatesDev};
@@ -1,4 +1,4 @@
1
- import{a as mn,b as Ve}from"./chunk-WUCX7RZO.js";import{A as yn,B as fe,C as z,D as ne,E as hn,G as wn,H as Sn,I as bn,J as vn,a as U,b as de,d as E,e as ue,f as $,h as un,j,k as pn,o as fn,r as d,t as Ie,u as ze,v as te,w as Re,x as Ge,y as pe,z as gn}from"./chunk-JKFMPHA4.js";var sc="tray-config-bridge",ic="tray-dev-token-bridge",Je=null;function ac(e){Je=e}function A(){if(!Je)throw new Error("Active tray config not seeded. Worker boot must call setActiveConfig() before handlers run.");return Je}function cc(){Je=null}import{AsyncLocalStorage as Bn}from"async_hooks";import{trace as cs,SpanKind as ls,SpanStatusCode as Ze}from"@opentelemetry/api";import{ExportResultCode as ds,W3CTraceContextPropagator as us}from"@opentelemetry/core";import{NodeTracerProvider as ps,SimpleSpanProcessor as fs,BatchSpanProcessor as ms}from"@opentelemetry/sdk-trace-node";import{OTLPTraceExporter as Jo}from"@opentelemetry/exporter-trace-otlp-proto";import{OTLPLogExporter as Wo}from"@opentelemetry/exporter-logs-otlp-proto";function Ct(e){return j(e).hosts.ingest}function Xo(){return $()??""}function xn(){return{[U]:Xo()}}function An(){let e=Ct(A().region);return new Jo({url:`${e}/v1/traces`,headers:()=>Promise.resolve(xn())})}function En(){let e=Ct(A().region);return new Wo({url:`${e}/v1/logs`,headers:()=>Promise.resolve(xn())})}import{logs as Cn,SeverityNumber as We}from"@opentelemetry/api-logs";import{LoggerProvider as Zo,BatchLogRecordProcessor as es}from"@opentelemetry/sdk-logs";function Ce(e){try{return JSON.stringify(e)}catch(t){return JSON.stringify({_serialization_error:t instanceof Error?t.message:String(t)})}}function Yo(e){return new TextEncoder().encode(e).length}var In="\u2026[truncated]",Qo=Yo(In),Te=4096;function re(e,t=Te){let n=new TextEncoder().encode(e);if(n.length<=t)return e;let r=n.subarray(0,t-Qo);return new TextDecoder("utf-8").decode(r).replace(/�$/,"")+In}function k(e,t=Te){return re(Ce(e),t)}var ts="@trayai/helix-sdk",ke,Rn={debug:{number:We.DEBUG,text:"DEBUG"},info:{number:We.INFO,text:"INFO"},warn:{number:We.WARN,text:"WARN"},error:{number:We.ERROR,text:"ERROR"}};function ns(){return E().mode==="lambda"?[new es({exporter:En()})]:[]}function Tn(){if(ke!==void 0)return;let e=ns();e.length!==0&&(ke=new Zo({processors:e}),Cn.setGlobalLoggerProvider(ke))}function rs(e,t,n){let r=Rn[e]??Rn.info;return{severityNumber:r.number,severityText:r.text,body:t,...n?{attributes:{"tray.log.meta":k(n)}}:{}}}function kn(e,t,n){Cn.getLogger(ts).emit(rs(e,t,n))}async function Pn(e=2e3){if(ke===void 0)return;let t;try{await Promise.race([ke.forceFlush(),new Promise(n=>{t=setTimeout(n,e)})])}catch(n){process.stderr.write(`[helix-sdk] otel log flush failed: ${n instanceof Error?n.message:String(n)}
1
+ import{a as mn,b as Ve}from"./chunk-WUCX7RZO.js";import{A as yn,B as fe,C as z,D as ne,E as hn,G as wn,H as Sn,I as bn,J as vn,a as U,b as de,d as E,e as ue,f as $,h as un,j,k as pn,o as fn,r as d,t as Ie,u as ze,v as te,w as Re,x as Ge,y as pe,z as gn}from"./chunk-LKZKDHYO.js";var sc="tray-config-bridge",ic="tray-dev-token-bridge",Je=null;function ac(e){Je=e}function A(){if(!Je)throw new Error("Active tray config not seeded. Worker boot must call setActiveConfig() before handlers run.");return Je}function cc(){Je=null}import{AsyncLocalStorage as Bn}from"async_hooks";import{trace as cs,SpanKind as ls,SpanStatusCode as Ze}from"@opentelemetry/api";import{ExportResultCode as ds,W3CTraceContextPropagator as us}from"@opentelemetry/core";import{NodeTracerProvider as ps,SimpleSpanProcessor as fs,BatchSpanProcessor as ms}from"@opentelemetry/sdk-trace-node";import{OTLPTraceExporter as Jo}from"@opentelemetry/exporter-trace-otlp-proto";import{OTLPLogExporter as Wo}from"@opentelemetry/exporter-logs-otlp-proto";function Ct(e){return j(e).hosts.ingest}function Xo(){return $()??""}function xn(){return{[U]:Xo()}}function An(){let e=Ct(A().region);return new Jo({url:`${e}/v1/traces`,headers:()=>Promise.resolve(xn())})}function En(){let e=Ct(A().region);return new Wo({url:`${e}/v1/logs`,headers:()=>Promise.resolve(xn())})}import{logs as Cn,SeverityNumber as We}from"@opentelemetry/api-logs";import{LoggerProvider as Zo,BatchLogRecordProcessor as es}from"@opentelemetry/sdk-logs";function Ce(e){try{return JSON.stringify(e)}catch(t){return JSON.stringify({_serialization_error:t instanceof Error?t.message:String(t)})}}function Yo(e){return new TextEncoder().encode(e).length}var In="\u2026[truncated]",Qo=Yo(In),Te=4096;function re(e,t=Te){let n=new TextEncoder().encode(e);if(n.length<=t)return e;let r=n.subarray(0,t-Qo);return new TextDecoder("utf-8").decode(r).replace(/�$/,"")+In}function k(e,t=Te){return re(Ce(e),t)}var ts="@trayai/helix-sdk",ke,Rn={debug:{number:We.DEBUG,text:"DEBUG"},info:{number:We.INFO,text:"INFO"},warn:{number:We.WARN,text:"WARN"},error:{number:We.ERROR,text:"ERROR"}};function ns(){return E().mode==="lambda"?[new es({exporter:En()})]:[]}function Tn(){if(ke!==void 0)return;let e=ns();e.length!==0&&(ke=new Zo({processors:e}),Cn.setGlobalLoggerProvider(ke))}function rs(e,t,n){let r=Rn[e]??Rn.info;return{severityNumber:r.number,severityText:r.text,body:t,...n?{attributes:{"tray.log.meta":k(n)}}:{}}}function kn(e,t,n){Cn.getLogger(ts).emit(rs(e,t,n))}async function Pn(e=2e3){if(ke===void 0)return;let t;try{await Promise.race([ke.forceFlush(),new Promise(n=>{t=setTimeout(n,e)})])}catch(n){process.stderr.write(`[helix-sdk] otel log flush failed: ${n instanceof Error?n.message:String(n)}
2
2
  `)}finally{t!==void 0&&clearTimeout(t)}}function Tt(){let e=process.env.TRAY_PRETTY_LOGS;return e==="1"||e==="true"}function os(){if(process.env.NO_COLOR!==void 0)return!1;let e=process.env.FORCE_COLOR;return e!==void 0&&e!=="0"&&e!=="false"?!0:!!process.stdout.isTTY&&process.env.TERM!=="dumb"}function D(e,t){return os()?`\x1B[${e}m${t}\x1B[0m`:t}var ss=5,is={FN:"1;35",INFO:"34",AUTH:"35",API:"36",AGENT:"1;36",TOOL:"36",WARN:"33",ERROR:"31",DEBUG:"90"},Xe="32",Ye="31",as="33",oe="2",Qe="1";function se(e){return D(is[e]??"0",e.padEnd(ss))}function On(e,t){return`${se("FN")} ${D(Qe,`${e} ${t}`.trim())}`}function _n(e,t,n,r){let o=e.toUpperCase(),i=`${r?`${D(oe,r)} `:""}${se(o)} ${t}`;return n&&Object.keys(n).length>0&&(i+=` ${D(oe,Ce(n))}`),i}function Dn(e){return new Date(e[0]*1e3).toTimeString().slice(0,8)}function Mn(e){return`${se("AUTH")} ${e}`}function Fn(e,t,n,r,o){let s=n===void 0?"ERR":String(n),i=D(o==="error"?Ye:Xe,s);return`${se("API")} ${e} ${t} \u2192 ${i} ${D(oe,`${r}ms`)}`}function Ln(e){return`${se("AGENT")} ${D(Qe,e)}`}function Nn(e,t,n,r){let o=t==="error"?Ye:t==="awaiting-approval"?as:Xe,s=n!==void 0?`${D(oe,`${n} step${n===1?"":"s"}`)} `:"";return`${se("AGENT")} ${D(Qe,e)} \u2192 ${D(o,t)} ${s}${D(oe,`${r}ms`)}`}function Un(e,t,n){let r=t==="error"?D(Ye,"error"):D(Xe,"ok");return`${se("TOOL")} ${e} \u2192 ${r} ${D(oe,`${n}ms`)}`}function $n(e,t,n){let r=t?Ye:Xe,o=D(r,"\u25CF"),s=D(r,t?"error":"success");return`${o} ${D(Qe,e)} ${s} ${D(oe,`${n}ms`)}`}function H(e){try{process.stdout.write(e+`
3
3
  `)}catch{}}var Kn=new Bn,gs=new Bn;function O(e){let t=gs.getStore();t&&(t[e]=!0)}var ys=/^[0-9a-f]{32}$/;function hs(e){let t=e.replace(/-/g,"").toLowerCase();return ys.test(t)?t:null}var ws={0:"STATUS_CODE_UNSET",1:"STATUS_CODE_OK",2:"STATUS_CODE_ERROR"},me=new Map;function Hn(e,t,n){let r=me.get(e);r?r[t]=n:me.set(e,{[t]:n})}function q(e,t,n){e.setAttribute(t,k(n))}var Pe;function jn(e){return`${e[0]}${String(e[1]).padStart(9,"0")}`}function kt(e){return Math.round(e[0]*1e3+e[1]/1e6)}function qn(e){try{process.stdout.write(Ce(e)+`
4
4
  `)}catch{}}var Pt=class{export(t,n){for(let r of t){let o=r.spanContext().spanId,s=me.get(o),i={...r.attributes};if(s!==void 0){for(let[l,u]of Object.entries(s))typeof u=="string"?i[l]=re(u):typeof u=="object"&&u!==null?i[l]=k(u):i[l]=u;me.delete(o)}let a=Kn.getStore(),c=a?hs(a):null;qn({_otel:"span",traceId:c??r.spanContext().traceId,spanId:o,parentSpanId:r.parentSpanContext?.spanId??"",name:r.name,kind:r.kind,startTimeUnixNano:jn(r.startTime),endTimeUnixNano:jn(r.endTime),attributes:i,status:{code:ws[r.status.code]??"STATUS_CODE_UNSET",...r.status.message?{message:re(r.status.message)}:{}}})}n({code:ds.SUCCESS})}forceFlush(){return Promise.resolve()}shutdown(){return Promise.resolve()}},Ot=class{onStart(t,n){}onEnd(t){me.delete(t.spanContext().spanId)}forceFlush(){return Promise.resolve()}shutdown(){return Promise.resolve()}},_t=class{onStart(t){let n=t;(n.name==="function"||n.name==="App")&&H(`
@@ -0,0 +1 @@
1
+ var b="X-Helix-Project-Execution-Token",R="X-Tray-Token",q={mode:"dev",deploymentId:null},k={...q},p={};function te(e){let{internalJwt:r,helixExecutionJwt:t,devToken:n,...i}=e;"internalJwt"in e&&(p.internalJwt=r),"helixExecutionJwt"in e&&(p.helixExecutionJwt=t),"devToken"in e&&(p.devToken=n);let o="userId"in e||"executionId"in e?{userEmail:void 0,userName:void 0}:{};k={...k,...o,...i}}function ne(){return k}function S(){return p.internalJwt}function P(){return p.helixExecutionJwt}function I(){return p.devToken}var O=new Set(["us1","eu1","ap1","ap2"]),s=new Map,h={name:"us1",exposedName:"us1",displayName:"us1",hosts:{api:"https://api.tray.io",broker:"https://api.tray.io/private/v1/code",ingest:"https://api.tray.io/private/v1/helix/otlp",weaver:"https://weaver.tray.io",app:"https://app.tray.io",projectHost:"helix-app.ai",dashboard:"https://app.helix.tray.ai",auth:"https://auth.tray.io"},login:{storePrefix:"PROD",appUrl:"https://app.tray.io",cookieName:"prod_tray_lid",cookieDomain:"tray.io"}},v={name:"eu1",exposedName:"eu1",displayName:"eu1",hosts:{api:"https://api.eu1.tray.io",broker:"https://api.eu1.tray.io/private/v1/code",ingest:"https://api.eu1.tray.io/private/v1/helix/otlp",weaver:"https://weaver.eu1.tray.io",app:"https://app.eu1.tray.io",projectHost:"eu1.helix-app.ai",dashboard:"https://app.helix.eu1.tray.ai",auth:"https://auth.eu1.tray.io"},login:{storePrefix:"EU1",appUrl:"https://app.eu1.tray.io",cookieName:"prod_tray_lid_eu",cookieDomain:"tray.io"}},x={name:"ap1",exposedName:"ap1",displayName:"ap1",hosts:{api:"https://api.ap1.tray.io",broker:"https://api.ap1.tray.io/private/v1/code",ingest:"https://api.ap1.tray.io/private/v1/helix/otlp",weaver:"https://weaver.ap1.tray.io",app:"https://app.ap1.tray.io",projectHost:"ap1.helix-app.ai",dashboard:"https://app.helix.ap1.tray.ai",auth:"https://auth.ap1.tray.io"},login:{storePrefix:"AP1",appUrl:"https://app.ap1.tray.io",cookieName:"prod_tray_lid_ap",cookieDomain:"tray.io"}},E={name:"ap2",exposedName:"ap2",displayName:"ap2",hosts:{api:"https://api.ap2.tray.io",broker:"https://api.ap2.tray.io/private/v1/code",ingest:"https://api.ap2.tray.io/private/v1/helix/otlp",weaver:"https://weaver.ap2.tray.io",app:"https://app.ap2.tray.io",projectHost:"ap2.helix-app.ai",dashboard:"https://app.helix.ap2.tray.ai",auth:"https://auth.ap2.tray.io"},login:{storePrefix:"AP2",appUrl:"https://app.ap2.tray.io",cookieName:"prod_tray_lid_ap2",cookieDomain:"tray.io"}};s.set(h.name,h);s.set(v.name,v);s.set(x.name,x);s.set(E.name,E);var T=["api","broker","ingest","weaver","app","projectHost","dashboard"],N=["auth"],D=["storePrefix","appUrl","cookieName","cookieDomain"];function C(e){if(!e.name||typeof e.name!="string")throw new Error("RegionProfile.name must be a non-empty string");if(!e.exposedName||typeof e.exposedName!="string")throw new Error("RegionProfile.exposedName must be a non-empty string");if(!e.displayName||typeof e.displayName!="string")throw new Error("RegionProfile.displayName must be a non-empty string");if(!e.hosts||typeof e.hosts!="object")throw new Error("RegionProfile.hosts must be an object");if(!e.login||typeof e.login!="object")throw new Error("RegionProfile.login must be an object");for(let r of T)if(typeof e.hosts[r]!="string"||!e.hosts[r])throw new Error(`RegionProfile.hosts.${r} must be a non-empty string`);for(let r of N){let t=e.hosts[r];if(t!==void 0&&(typeof t!="string"||!t))throw new Error(`RegionProfile.hosts.${r} must be a non-empty string when set`)}for(let r of D)if(typeof e.login[r]!="string"||!e.login[r])throw new Error(`RegionProfile.login.${r} must be a non-empty string`)}function j(e,r){return e.name===r.name&&e.exposedName===r.exposedName&&e.displayName===r.displayName&&T.every(t=>e.hosts[t]===r.hosts[t])&&N.every(t=>e.hosts[t]===r.hosts[t])&&D.every(t=>e.login[t]===r.login[t])}function oe(e){C(e);let r=s.get(e.name);if(r){if(j(r,e))return;throw new Error(`RegionProfile.name "${e.name}" is already registered with different values`)}for(let t of s.values())if(t.exposedName===e.exposedName)throw new Error(`RegionProfile.exposedName "${e.exposedName}" is already used by "${t.name}"`);s.set(e.name,e)}function H(e){return s.has(e)}function se(e){return s.get(e)}function m(e){let r=s.get(e);if(!r)throw new Error(`Unknown region: ${e}`);return r}function ae(){return[...s.keys()]}function de(){return[...s.values()].map(e=>e.exposedName)}function F(e){for(let r of s.values())if(r.exposedName===e)return r.name}var f=Symbol.for("@trayai/helix-sdk.forcedEnvironment");function B(e){let r=globalThis;if(e===void 0||e.trim()===""){delete r[f];return}let t=e.trim(),n=F(t);if(n){r[f]=n;return}if(H(t)){r[f]=t;return}throw new Error(`Unknown region: ${t}`)}function le(){return globalThis[f]}function ue(){return[...s.values()].filter(e=>!O.has(e.name))}function ce(){B(void 0),s.clear();for(let e of[h,v,x,E])s.set(e.name,{...e,hosts:{...e.hosts},login:{...e.login}})}var u=class e extends Error{detail;constructor(r){super(L(r)),this.name="SdkError",this.detail=r}get kind(){return this.detail.kind}static unknownAlias(r,t){return new e({kind:"unknown_alias",alias:r,available:t})}static inputValidationFailed(r){return new e({kind:"input_validation_failed",fields:r})}static outputValidationFailed(r){return new e({kind:"output_validation_failed",fields:r})}static configLoadFailed(r){return new e({kind:"config_load_failed",cause:r})}static brokerError(r,t,n,i){return new e({kind:"broker_error",status:r,message:t,body:n,code:i})}static unsupportedBodyType(r){return new e({kind:"unsupported_body_type",actualType:r})}static unsupportedScheme(r){return new e({kind:"unsupported_scheme",scheme:r})}static missingExecutionCredentials(){return new e({kind:"missing_execution_credentials"})}static missingTrayToken(){return new e({kind:"missing_tray_token"})}static dbCallFailed(r,t){return new e({kind:"db_call_failed",message:r,cause:t})}static dbQueryFailed(r){return new e({kind:"db_query_failed",message:r})}static dbInvalidParameters(r){return new e({kind:"db_invalid_parameters",message:r})}static kvKeyInvalid(r){return new e({kind:"kv_key_invalid",message:r})}static kvValueInvalid(r){return new e({kind:"kv_value_invalid",message:r})}static kvValueTooLarge(r,t){return new e({kind:"kv_value_too_large",message:r,maxBytes:t})}static kvTtlInvalid(r){return new e({kind:"kv_ttl_invalid",message:r})}static kvNotAvailable(){return new e({kind:"kv_not_available"})}static kvCallFailed(r,t,n){return new e({kind:"kv_call_failed",status:r,message:t,body:n})}static kvRequiresProvisioning(){return new e({kind:"kv_requires_provisioning"})}static filesPathInvalid(r){return new e({kind:"files_path_invalid",message:r})}static filesValueInvalid(r){return new e({kind:"files_value_invalid",message:r})}static filesValueTooLarge(r,t){return new e({kind:"files_value_too_large",message:r,maxBytes:t})}static filesNotAvailable(){return new e({kind:"files_not_available"})}static filesCallFailed(r,t,n){return new e({kind:"files_call_failed",status:r,message:t,body:n})}static filesRequiresProvisioning(){return new e({kind:"files_requires_provisioning"})}static callFunctionPathInvalid(r){return new e({kind:"call_function_path_invalid",message:r})}static callFunctionCallFailed(r,t,n){return new e({kind:"call_function_call_failed",status:r,message:t,body:n})}static callFunctionRequiresProvisioning(){return new e({kind:"call_function_requires_provisioning"})}static callFunctionNotAvailable(){return new e({kind:"call_function_not_available"})}static callFunctionMissingExecutionJwt(){return new e({kind:"call_function_missing_execution_jwt"})}static aiUnsupportedService(r,t,n){return new e({kind:"ai_unsupported_service",alias:r,service:t,supported:n})}static aiModelIdRequired(r,t){return new e({kind:"ai_model_id_required",alias:r,operation:t})}static aiModelInstanceRequired(r){return new e({kind:"ai_model_instance_required",modelId:r})}static aiProviderNotConfigured(r,t){return new e({kind:"ai_provider_not_configured",alias:r,supported:t})}static aiProviderMisconfigured(r,t,n){return new e({kind:"ai_provider_misconfigured",alias:r,service:t,message:n})}static aiForeignModelRejected(){return new e({kind:"ai_foreign_model_rejected"})}static agentSessionsFailed(r){return new e({kind:"agent_sessions_failed",message:r})}};function ge(e){return e instanceof u}function L(e){switch(e.kind){case"unknown_alias":return`Unknown auth alias "${e.alias}". Available: ${e.available.join(", ")||"(none)"}`;case"input_validation_failed":return`Input validation failed for fields: ${e.fields.join(", ")}`;case"output_validation_failed":return`Output validation failed for fields: ${e.fields.join(", ")}`;case"config_load_failed":return`Config load failed: ${e.cause}`;case"broker_error":return e.code?`broker error: ${e.status} ${e.code}: ${e.message}`:`broker error: ${e.status} ${e.message}`;case"unsupported_body_type":return`unsupported body type: ${e.actualType}`;case"unsupported_scheme":return`unsupported scheme: ${e.scheme} (only https supported)`;case"missing_execution_credentials":return"missing execution credentials: at least one of internalJwt / helixExecutionJwt must be set before an authed broker/KV call";case"missing_tray_token":return"Not logged in. Run `helix login` to authenticate before making authed HTTP calls in dev.";case"db_call_failed":return`Database call failed: ${e.message}`;case"db_query_failed":return`Database query failed: ${e.message}`;case"db_invalid_parameters":return`Invalid database parameters: ${e.message}`;case"kv_key_invalid":return`Invalid KV key: ${e.message}`;case"kv_value_invalid":return e.message;case"kv_value_too_large":return e.message;case"kv_ttl_invalid":return e.message;case"kv_not_available":return"Key-value store is not available in this environment";case"kv_call_failed":return`KV platform error: ${e.status} ${e.message}`;case"kv_requires_provisioning":return"Key-value store requires a provisioned project (run helix project set)";case"files_path_invalid":return`Invalid file path: ${e.message}`;case"files_value_invalid":return e.message;case"files_value_too_large":return e.message;case"files_not_available":return"File storage is not available in this environment";case"files_call_failed":return`Files platform error: ${e.status} ${e.message}`;case"files_requires_provisioning":return"File storage requires a provisioned project (run helix project set)";case"call_function_path_invalid":return`Invalid function path: ${e.message}`;case"call_function_call_failed":return`Async function call failed: ${e.status} ${e.message}`;case"call_function_requires_provisioning":return"callFunctionAsync requires a provisioned project (run helix project set)";case"call_function_not_available":return"callFunctionAsync is not available: no running dev server was found";case"call_function_missing_execution_jwt":return"ctx.callFunctionAsync requires a helix project-execution JWT \u2014 a legacy internalJwt-only execution cannot call it";case"ai_unsupported_service":return`Authentication alias "${e.alias}" resolves to service "${e.service}", which ctx.ai does not support. Supported AI services: ${e.supported.join(", ")}`;case"ai_model_id_required":return`ctx.ai("${e.alias}").${e.operation} requires \`model\` as a string model id. To pass a model instance, use the top-level ctx.ai.${e.operation} instead.`;case"ai_model_instance_required":return`ctx.ai.* call functions require a model instance from ctx.ai(alias), got the string "${e.modelId}". Bare model ids would route outside the credentials broker and are not supported.`;case"ai_provider_not_configured":return`No AI provider configured for authentication alias "${e.alias}". Add \`aiProviders: { "${e.alias}": "<service>" }\` to helix.config.ts (supported services: ${e.supported.join(", ")}; bedrock needs the object form with region, openai-compatible the object form with baseUrl).`;case"ai_provider_misconfigured":return`aiProviders entry for authentication alias "${e.alias}" (service "${e.service}") is incomplete: ${e.message}`;case"ai_foreign_model_rejected":return"ctx.ai.* call functions require a model instance minted by ctx.ai(alias). A model built directly against a raw @ai-sdk/* provider carries its own transport and credentials, and would bypass the credentials broker, proxy policy, and metering.";case"agent_sessions_failed":return`Agent session store error: ${e.message}`}}import{z as g}from"zod";var A="x-helix-destination-url",U="x-helix-authentication-id",J="x-helix-deployment-id",_="x-execution-id",M="x-helix-broker-error",he="route_not_found",K=new Set([A,U,J,"authorization","x-tray-token","x-helix-project-execution-token","host","content-length","connection","transfer-encoding","te","upgrade","keep-alive","expect","proxy-authorization","proxy-connection","accept-encoding","x-request-id",_]);function V(e){let r=e.toLowerCase();return K.has(r)||r.startsWith("x-tray-internal-")}var w=g.object({error:g.object({code:g.string(),message:g.string(),issues:g.array(g.unknown()).optional()})});function ve(e,r){let t=`${m(e).hosts.api}/private/v1/helix/broker/http/raw`;return r==="dev"?`${t}/dev`:t}function xe(e){if(e.mode==="lambda"){let t=S(),n=P(),i=!!(t&&t.trim().length>0),o=!!(n&&n.trim().length>0);if(!i&&!o)throw u.missingExecutionCredentials();let a={};return i&&(a[R]=t),o&&(a[b]=n),{headers:a,deploymentId:e.deploymentId??null}}let r=I();if(!r)throw u.missingTrayToken();return{headers:{Authorization:`Bearer ${r}`},deploymentId:null}}function G(e){return typeof e=="string"||e instanceof ArrayBuffer||ArrayBuffer.isView(e)||typeof Blob<"u"&&e instanceof Blob||typeof FormData<"u"&&e instanceof FormData||e instanceof URLSearchParams||typeof ReadableStream<"u"&&e instanceof ReadableStream}function Ee(e){let r=new URL(e.url);if(r.protocol!=="https:")throw u.unsupportedScheme(r.protocol.replace(/:$/,""));if(e.query!==void 0)if(e.query instanceof URLSearchParams)for(let[l,d]of e.query.entries())r.searchParams.append(l,d);else for(let[l,d]of Object.entries(e.query))for(let $ of Array.isArray(d)?d:[d])r.searchParams.append(l,$);let t;e.headers===void 0?t=[]:e.headers instanceof Headers?t=Array.from(e.headers.entries()):Array.isArray(e.headers)?t=e.headers:t=Object.entries(e.headers);let n=t.filter(([l])=>!V(l)),i=e.body!==void 0&&e.body!==null,o,a,c=!1;return i&&(G(e.body)?(o=e.body,c=typeof ReadableStream<"u"&&e.body instanceof ReadableStream):(o=JSON.stringify(e.body),n.some(([d])=>d.toLowerCase()==="content-type")||(a="application/json"))),{authenticationId:e.authenticationId,method:e.method.toUpperCase(),destinationUrl:r.toString(),headers:n,body:o,isStreamBody:c,defaultContentType:a}}async function X(e,r){let t=await e.text(),n=t,i=t||r;try{n=JSON.parse(t);let o=w.safeParse(n);o.success&&(i=o.data.error.message)}catch{}return{status:e.status,code:r,message:i,body:n}}var Y=6e4;function z(e){return e.includes("json")}function W(e){return e.startsWith("text/")||e.includes("xml")||e.includes("urlencoded")||e.includes("javascript")||e.includes("ecmascript")}function Q(e,r){if(e.byteLength===0)return;let t=r.toLowerCase();if(z(t)){let n=new TextDecoder("utf-8").decode(e);try{return JSON.parse(n)}catch{return n}}return W(t)?new TextDecoder("utf-8").decode(e):e}function Z(e){let r={};for(let[t,n]of e.entries())r[t.toLowerCase()]=n;return r}async function we(e){let{request:r}=e,t=new Headers;for(let[l,d]of r.headers)t.append(l,d);r.defaultContentType&&!t.has("content-type")&&t.set("content-type",r.defaultContentType),t.set(A,r.destinationUrl),t.set(U,r.authenticationId);for(let[l,d]of Object.entries(e.credentialHeaders))t.set(l,d);e.executionId&&t.set(_,e.executionId);let n={method:r.method,headers:t,redirect:"manual",signal:AbortSignal.timeout(e.timeoutMs??Y)};r.body!==void 0&&(n.body=r.body,r.isStreamBody&&(n.duplex="half"));let i=await fetch(e.proxyUrl,n),o=i.headers.get(M);if(o!==null)return{kind:"brokerError",...await X(i,o)};let a=new Uint8Array(await i.arrayBuffer()),c=i.headers.get("content-type")??"";return{kind:"upstream",response:{status:i.status,headers:Z(i.headers),body:Q(a,c)}}}import{z as y}from"zod";var ee=3e4;function Te(e){let r=new URL(e);if(r.protocol!=="https:")throw u.unsupportedScheme(r.protocol.replace(/:$/,""))}function Ne(e,r){let t=`${m(e).hosts.api}/private/v1/helix/broker/s3/sign`;return r==="dev"?`${t}/dev`:t}var re=y.object({url:y.string(),method:y.string(),expiresAt:y.string()});async function De(e){let r=new Headers({"content-type":"application/json"});for(let[a,c]of Object.entries(e.credentialHeaders))r.set(a,c);e.executionId&&r.set(_,e.executionId);let t=await fetch(e.signUrl,{method:"POST",headers:r,body:JSON.stringify(e.body),redirect:"manual",signal:AbortSignal.timeout(e.timeoutMs??ee)}),n=await t.text(),i=n;try{i=JSON.parse(n)}catch{}if(t.ok){let a=re.safeParse(i);return a.success?{kind:"signed",result:a.data}:{kind:"brokerError",status:t.status,message:"malformed s3-sign response from credential broker",body:i}}let o=w.safeParse(i);return o.success?{kind:"brokerError",status:t.status,code:o.data.error.code,message:o.data.error.message,body:i}:{kind:"brokerError",status:t.status,message:n||`s3-sign request failed with status ${t.status}`,body:i}}export{b as a,R as b,te as c,ne as d,S as e,P as f,oe as g,H as h,se as i,m as j,ae as k,de as l,F as m,B as n,le as o,ue as p,ce as q,u as r,ge as s,A as t,U as u,J as v,_ as w,M as x,he as y,V as z,w as A,ve as B,xe as C,Ee as D,X as E,Y as F,we as G,Te as H,Ne as I,De as J};
@@ -1,5 +1,5 @@
1
1
  import { z, ZodType } from 'zod';
2
- import { P as PlatformContext } from './types-CVW_-1wh.js';
2
+ import { P as PlatformContext } from './types-BSbvztCi.js';
3
3
 
4
4
  interface SdkRuntimeConfig {
5
5
  /**
@@ -20,6 +20,20 @@ interface SdkRuntimeConfig {
20
20
  * `x-tray-user-id` header.
21
21
  */
22
22
  userId?: string;
23
+ /**
24
+ * Email of the calling user for the current invocation. Set via
25
+ * `setSdkConfig(...)` at handler entry in lambda mode. In `dev` mode,
26
+ * define-function reads from the `x-tray-user-email` header. Only exposed
27
+ * on `ctx.identity` when `userId` is also set.
28
+ */
29
+ userEmail?: string;
30
+ /**
31
+ * Display name of the calling user for the current invocation. Set via
32
+ * `setSdkConfig(...)` at handler entry in lambda mode. In `dev` mode,
33
+ * define-function reads from the `x-tray-user-name` header. Only exposed
34
+ * on `ctx.identity` when `userId` is also set.
35
+ */
36
+ userName?: string;
23
37
  /**
24
38
  * Deployment ID for the current invocation. Set via `setSdkConfig(...)` at
25
39
  * handler entry. Only meaningful in `lambda` mode; `dev` mode has no
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import * as h3 from 'h3';
2
2
  import { ZodType } from 'zod';
3
- import { F as FunctionHandler, D as DefineFunctionOptions, a as DefineScheduleConfig, S as ScheduleDefinition, P as PlatformContext } from './types-CVW_-1wh.js';
4
- export { A as AgentApprovalDecision, b as AgentCallOptions, c as AgentClient, d as AgentPendingApproval, e as AgentResult, f as AgentSession, g as AgentSessionPage, h as AgentSessionPageOptions, i as AgentSessionSummary, j as AgentSessionsList, k as AgentStreamResult, l as AiEmbeddingModelInstance, m as AiImageModelInstance, n as AiLanguageModelInstance, o as AiSpeechModelInstance, p as AiTranscriptionModelInstance, B as BrokerAuthedClient, q as BrokerCallOptions, r as BrokerCallResult, C as CallFunctionAsync, s as DbCallParameters, t as DbClient, u as FileSystemClient, H as HelixAI, v as HelixAIProvider, w as HelixAgent, x as HelixCost, y as HelixResultMeta, z as HttpClient, K as KeyValueStore, L as Logger, E as S3SignOptions, G as S3SignResult, I as ScheduleContext, J as ScheduleHandler, M as ScheduleTrigger, N as SqlBuilder, T as TrayContext, U as UnvalidatedInput } from './types-CVW_-1wh.js';
5
- import { T as TrayConfig, L as LoadedTrayConfig, W as WatchErrorPhase } from './define-agent-DXV_nHvs.js';
6
- export { A as AGENT_DEFINITION_KIND, a as AI_SERVICES, b as AgentDefinition, c as AgentDefinitionConfig, d as AgentSessionsConfig, e as AiProviderEntry, f as AiService, C as ConfigFileOptions, D as DefineToolConfig, H as HELIX_CONFIG_ENV, g as HelixTool, h as HelixToolLike, P as ProvisionedTrayConfig, S as SdkRuntimeConfig, i as TOOL_DEFINITION_KIND, U as UnprovisionedTrayConfig, j as WORKSPACE_ID_REQUIRED_CODE, k as WorkspaceIdRequiredError, l as agentSessionsSchema, m as aiProviderEntrySchema, n as defineAgent, o as defineTool, p as getSdkConfig, q as isAgentDefinition, r as isToolDefinition, s as loadConfig, t as loadedTrayConfigSchema, u as projectIdSchema, v as requireWorkspaceId, w as resolveConfigFile, x as resolveConfigOverride, y as workspaceIdSchema } from './define-agent-DXV_nHvs.js';
3
+ import { F as FunctionHandler, D as DefineFunctionOptions, a as DefineScheduleConfig, S as ScheduleDefinition, P as PlatformContext } from './types-BSbvztCi.js';
4
+ export { A as AgentApprovalDecision, b as AgentCallOptions, c as AgentClient, d as AgentPendingApproval, e as AgentResult, f as AgentSession, g as AgentSessionPage, h as AgentSessionPageOptions, i as AgentSessionSummary, j as AgentSessionsList, k as AgentStreamResult, l as AiEmbeddingModelInstance, m as AiImageModelInstance, n as AiLanguageModelInstance, o as AiSpeechModelInstance, p as AiTranscriptionModelInstance, B as BrokerAuthedClient, q as BrokerCallOptions, r as BrokerCallResult, C as CallFunctionAsync, s as DbCallParameters, t as DbClient, u as FileSystemClient, H as HelixAI, v as HelixAIProvider, w as HelixAgent, x as HelixCost, y as HelixResultMeta, z as HttpClient, K as KeyValueStore, L as Logger, E as S3SignOptions, G as S3SignResult, I as ScheduleContext, J as ScheduleHandler, M as ScheduleTrigger, N as SqlBuilder, T as TrayContext, U as UnvalidatedInput } from './types-BSbvztCi.js';
5
+ import { T as TrayConfig, L as LoadedTrayConfig, W as WatchErrorPhase } from './define-agent-BEUgQ_5-.js';
6
+ export { A as AGENT_DEFINITION_KIND, a as AI_SERVICES, b as AgentDefinition, c as AgentDefinitionConfig, d as AgentSessionsConfig, e as AiProviderEntry, f as AiService, C as ConfigFileOptions, D as DefineToolConfig, H as HELIX_CONFIG_ENV, g as HelixTool, h as HelixToolLike, P as ProvisionedTrayConfig, S as SdkRuntimeConfig, i as TOOL_DEFINITION_KIND, U as UnprovisionedTrayConfig, j as WORKSPACE_ID_REQUIRED_CODE, k as WorkspaceIdRequiredError, l as agentSessionsSchema, m as aiProviderEntrySchema, n as defineAgent, o as defineTool, p as getSdkConfig, q as isAgentDefinition, r as isToolDefinition, s as loadConfig, t as loadedTrayConfigSchema, u as projectIdSchema, v as requireWorkspaceId, w as resolveConfigFile, x as resolveConfigOverride, y as workspaceIdSchema } from './define-agent-BEUgQ_5-.js';
7
7
  export { a as REGION_VALUES, R as Region, r as regionSchema } from './region-schema-COfWyGI9.js';
8
8
  import { StopCondition, ToolSet } from 'ai';
9
9
  export { EmbedManyResult, EmbedResult, EmbeddingModel, FinishReason, GenerateImageResult, GenerateObjectResult, GenerateTextResult, ImageModel, LanguageModel, LanguageModelUsage, ModelMessage, Output, PrepareStepFunction, SpeechModel, SpeechResult, StopCondition, StreamObjectResult, StreamTextResult, TextStreamPart, ToolChoice, ToolSet, TranscriptionModel, TranscriptionResult, UIMessage, convertToModelMessages, cosineSimilarity, dynamicTool, hasToolCall, jsonSchema, smoothStream, stepCountIs, tool, zodSchema } from 'ai';
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import{A as le,B as fe,C as pe,D as ge,E as me,F as he,G as ye,H as x,I as k,J as V,K as z,L as y,M as Ce,N as ve,O as B,P as Se,Q as we,R as Ee,Y as _e,Z as xe,_ as ke,ba as Te,ca as G,da as be,ea as Ie,f as A,fa as Re,g as _,ga as Ae,h as P,i as h,j as H,k as F,l as D,m as O,n as ae,o as j,p as M,q,r as N,s as Z,w as K,x as $,y as ue,z as ce}from"./chunk-3WKD2ENP.js";import{a as L,b as de}from"./chunk-WUCX7RZO.js";import{d as E,r as W,s as U}from"./chunk-JKFMPHA4.js";import{randomUUID as We}from"crypto";import{SpanStatusCode as ee,SpanKind as Ue}from"@opentelemetry/api";import{defineEventHandler as qe,getMethod as Ne,getRequestURL as Ze,getHeaders as re,getHeader as te}from"h3";import{readBody as Pe,getQuery as He,getRouterParams as Fe}from"h3";async function J(e,t){let r=await De(e),n=He(e),o=Fe(e)??{},s={...n,...r,...o};return t?Oe(s,t):s}async function De(e){try{let t=await Pe(e);return t&&typeof t=="object"?t:(t!=null&&t!==""&&console.warn("[helix-sdk] Request body present but not a JSON object \u2014 ignored"),{})}catch(t){if(t instanceof Error&&"statusCode"in t&&t.statusCode===400){let n=new Error("Malformed request body");throw n.statusCode=400,n.data={message:"Request body is not valid JSON"},n}let r=e.method?.toUpperCase();if(r==="GET"||r==="HEAD"||r==="DELETE")return{};throw t}}function Oe(e,t){let r=t.safeParse(e);if(!r.success){let n=new Error("Input validation failed");throw n.statusCode=400,n.data=r.error.flatten(),n}return r.data}var C=class extends Error{statusCode;constructor(t,r){super(r),this.statusCode=t,this.name="HttpError"}};function Q(e){return t=>{e.node.res.statusCode=t}}function X(){return(e,t)=>{throw new C(e,t)}}function Y(e,t){let{statusCode:r,message:n}=Le(t.detail);return e.node.res.statusCode=r,{error:n,statusCode:r}}function Le(e){switch(e.kind){case"unknown_alias":return{statusCode:400,message:"Unknown authentication alias"};case"input_validation_failed":return{statusCode:400,message:"Input validation failed"};case"output_validation_failed":return{statusCode:500,message:"Internal server error"};case"config_load_failed":return{statusCode:500,message:"Configuration error"};case"broker_error":return{statusCode:502,message:"Broker error"};case"unsupported_body_type":return{statusCode:400,message:"Unsupported request body type"};case"unsupported_scheme":return{statusCode:400,message:"Unsupported URL scheme"};case"missing_execution_credentials":return{statusCode:401,message:"Missing execution credentials"};case"missing_tray_token":return{statusCode:500,message:"Missing Tray token"};case"db_call_failed":return{statusCode:502,message:e.message};case"db_query_failed":return{statusCode:502,message:`Database query failed: ${e.message}`};case"db_invalid_parameters":return{statusCode:400,message:e.message};case"kv_key_invalid":return{statusCode:400,message:e.message};case"kv_value_invalid":return{statusCode:400,message:e.message};case"kv_value_too_large":return{statusCode:400,message:e.message};case"kv_ttl_invalid":return{statusCode:400,message:e.message};case"kv_not_available":return{statusCode:501,message:"Key-value store is not available in this environment"};case"kv_call_failed":return{statusCode:502,message:"Key-value store request failed"};case"kv_requires_provisioning":return{statusCode:500,message:"Internal server error"};case"files_path_invalid":return{statusCode:400,message:e.message};case"files_value_invalid":return{statusCode:400,message:e.message};case"files_value_too_large":return{statusCode:400,message:e.message};case"files_not_available":return{statusCode:501,message:"File storage is not available in this environment"};case"files_call_failed":return{statusCode:502,message:"File storage request failed"};case"files_requires_provisioning":return{statusCode:500,message:"Internal server error"};case"call_function_path_invalid":return{statusCode:400,message:e.message};case"call_function_call_failed":return{statusCode:502,message:"Async function call failed"};case"call_function_requires_provisioning":return{statusCode:500,message:"Internal server error"};case"call_function_not_available":return{statusCode:501,message:"callFunctionAsync is not available in this environment"};case"call_function_missing_execution_jwt":return{statusCode:401,message:"Missing execution credentials"};case"ai_unsupported_service":case"ai_provider_misconfigured":case"ai_model_id_required":case"ai_model_instance_required":case"ai_provider_not_configured":case"ai_foreign_model_rejected":case"agent_sessions_failed":return{statusCode:500,message:e.kind==="ai_unsupported_service"?`AI service not supported for alias "${e.alias}"`:e.kind==="ai_provider_misconfigured"?`AI provider misconfigured for alias "${e.alias}"`:"Internal server error"};default:return{statusCode:500,message:`Unhandled error kind: ${e.kind}`}}}var je=["authorization","x-tray-token","set-cookie","x-kong-request-id","traceparent","x-real-ip","cookie"];function Me(e){return e.toLowerCase().includes("tray_lid")}function T(e){let t={};for(let[r,n]of Object.entries(e))if(!je.includes(r.toLowerCase())){if(r.toLowerCase()==="cookie"&&n){let o=n.split(";").map(s=>s.trim()).filter(s=>{let d=s.split("=")[0].trim();return!Me(d)}).join("; ");o&&(t[r]=o);continue}t[r]=n}return t}function Ke(e,t){let{inputSchema:r,outputSchema:n}=Je(t),o=e;return qe(async s=>{let d=E(),{executionId:a,userId:i,deploymentId:f}=Qe(d,s),c=d.mode==="lambda"?d.parentExecutionId??null:null,p=Date.now(),v=new Date().toISOString(),l=Ne(s),u=Ze(s).pathname,g=M(),m=j(),se=`${l} ${u}`;H();let R={hasDb:!1,hasExternal:!1,hasAuth:!1,hasAi:!1,hasError:!1};return $e(()=>_.run(R,()=>A.run(a,async()=>{let S=await Ve(s,r);if(!S.ok)return{response:S.response,errored:!1,errorMessage:null};let ie=Ye(s,S.input,g,m,l,u,a,f,i,c);return ze(o,ie,n,s,m,a,f,{method:l,path:u,rawInput:S.input})})),{executionId:a,deploymentId:f,routeOrJob:se,startedAt:v,startMs:p,userId:i,flags:R})})}async function $e(e,t){let r=!1,n=null;try{let o=await e();return r=o.errored,n=o.errorMessage,o.response}finally{O({...t,errored:r,errorMessage:n}),await F()}}async function Ve(e,t){try{return{ok:!0,input:await J(e,t)}}catch(r){let n=Xe(e,r);if(n)return{ok:!1,response:n};throw r}}async function ze(e,t,r,n,o,s,d,a){return D.startActiveSpan("function",{root:!0,kind:Ue.SERVER,attributes:{method:a.method,route:a.path,executionId:s,...d?{deploymentId:d}:{}}},async i=>{t.traceId=i.spanContext().traceId;let f=T(re(n));h(i,"input",a.rawInput),h(i,"request",{method:a.method,path:a.path,headers:f,body:a.rawInput});let c=!1,p=null,v,l;try{let u=await L.run(t,()=>e(t));if(v=u,u==null)n.node.res.statusCode=204,l="";else if(u instanceof Response)l=u;else if(r){let g=r.safeParse(u);if(!g.success){let m=Object.keys(g.error.flatten().fieldErrors);throw o.error("Output validation failed",{fields:m,executionId:s}),W.outputValidationFailed(m)}l=g.data}else l=u}catch(u){c=!0,p=u instanceof Error?u.message:String(u),P("hasError"),l=Be(u,n,o,s)}finally{Ge(i,n,{errored:c,errorMessage:p,handlerResult:v,response:l})}return{response:l,errored:c,errorMessage:p}})}function Be(e,t,r,n){if(e instanceof C)return t.node.res.statusCode=e.statusCode,{error:e.message,statusCode:e.statusCode};if(U(e))return Y(t,e);r.error("Unhandled error in handler",{error:e instanceof Error?e.message:String(e),executionId:n}),t.node.res.statusCode=500;let o=process.env.NODE_ENV==="development";return{error:o&&e instanceof Error?e.message:"Internal server error",statusCode:500,...o&&e instanceof Error&&e.stack?{stack:e.stack}:{}}}function Ge(e,t,r){e.setAttribute("statusCode",t.node.res.statusCode),!r.errored&&r.handlerResult!==void 0&&h(e,"output",r.handlerResult),h(e,"response",r.response);let n=_.getStore();e.setAttribute("hasAuth",n?.hasAuth??!1),e.setAttribute("hasAi",n?.hasAi??!1),e.setAttribute("hasExternal",n?.hasExternal??!1),e.setAttribute("hasDb",n?.hasDb??!1),e.setAttribute("status",r.errored?"error":"success");let o=r.errored||(n?.hasError??!1);e.setStatus({code:o?ee.ERROR:ee.OK,...r.errorMessage?{message:r.errorMessage}:{}}),e.end()}function Je(e){if(!e)return{inputSchema:void 0,outputSchema:void 0};if(e instanceof Object&&"_def"in e)return{inputSchema:e,outputSchema:void 0};if(typeof e=="object"&&("input"in e||"output"in e)){let t=e;return{inputSchema:t.input,outputSchema:t.output}}return{inputSchema:e,outputSchema:void 0}}function Qe(e,t){let r=e.mode==="lambda",n=(r?e.executionId:te(t,"x-tray-execution-id"))??We(),o=(r?e.userId:te(t,"x-tray-user-id"))??null,s=r?e.deploymentId??null:null;return{executionId:n,userId:o,deploymentId:s}}function Xe(e,t){if(!(t instanceof Error)||!("statusCode"in t)||!("data"in t))return null;let r=t.statusCode,n=t.data;e.node.res.statusCode=r;let o=n&&typeof n=="object"&&"fieldErrors"in n?n.fieldErrors:void 0;return{error:"Input validation failed",statusCode:r,...o?{fields:Object.keys(o)}:{}}}function Ye(e,t,r,n,o,s,d,a,i,f){return{input:t,method:o,path:s,headers:T(re(e)),http:q(),db:c=>N(c),kv:()=>Z(),files:()=>K(),callFunctionAsync:$(),ai:B(),agent:c=>G(c),log:n,config:r,status:Q(e),error:X(),state:{},request:e,executionId:d,deploymentId:a,userId:i,parentExecutionId:f,identity:i!==null?{user:{id:i}}:null,traceId:""}}function et(e){return e}import{existsSync as tt,watch as rt,writeSync as nt}from"fs";import{basename as ot,dirname as st,join as it,resolve as w}from"path";import{watchConfig as at}from"c12";function dt(e,t){let r=e instanceof Error?e.message:String(e);nt(2,`[helix-watch] ${t.phase} error: ${r}
2
- `)}function b(){return{kind:"unprovisioned",name:"",authentications:{},config:{},region:"us1"}}var ut=/^(?:helix|tray)\.config\.(?:m|c)?[jt]s$/,ne=new Set;function oe(e,t){return k(e,{configFile:t})!==void 0}async function ct(e,t,r){if(oe(e.cwd,t))try{return{current:await y(e.cwd,{configFile:t}),initialLoadSucceeded:!0}}catch(n){return r(n,{phase:"reload"}),{current:b(),initialLoadSucceeded:!1}}if(e.watch){let n=t!==void 0?w(e.cwd,t):w(e.cwd);ne.has(n)||(process.stderr.write(t!==void 0?`warning: config file ${w(e.cwd,t)} not found; tray running with default config
1
+ import{A as pe,B as ge,C as me,D as he,E as ye,F as Ce,G as ve,H as k,I as T,J as B,K as G,L as C,M as Se,N as Ee,O as J,P as we,Q as _e,R as xe,Y as ke,Z as Te,_ as be,ba as Ie,ca as Q,da as Re,ea as Ae,f as H,fa as Pe,g as x,ga as He,h as F,i as y,j as D,k as O,l as L,m as j,n as ue,o as W,p as N,q as Z,r as K,s as $,w as V,x as z,y as le,z as fe}from"./chunk-GMEVZH35.js";import{a as M,b as ce}from"./chunk-WUCX7RZO.js";import{d as _,r as U,s as q}from"./chunk-LKZKDHYO.js";import{randomUUID as Ue}from"crypto";import{SpanStatusCode as re,SpanKind as qe}from"@opentelemetry/api";import{defineEventHandler as Ze,getMethod as Ke,getRequestURL as $e,getHeaders as ne,getHeader as E}from"h3";import{readBody as Fe,getQuery as De,getRouterParams as Oe}from"h3";async function X(e,t){let r=await Le(e),n=De(e),o=Oe(e)??{},s={...n,...r,...o};return t?je(s,t):s}async function Le(e){try{let t=await Fe(e);return t&&typeof t=="object"?t:(t!=null&&t!==""&&console.warn("[helix-sdk] Request body present but not a JSON object \u2014 ignored"),{})}catch(t){if(t instanceof Error&&"statusCode"in t&&t.statusCode===400){let n=new Error("Malformed request body");throw n.statusCode=400,n.data={message:"Request body is not valid JSON"},n}let r=e.method?.toUpperCase();if(r==="GET"||r==="HEAD"||r==="DELETE")return{};throw t}}function je(e,t){let r=t.safeParse(e);if(!r.success){let n=new Error("Input validation failed");throw n.statusCode=400,n.data=r.error.flatten(),n}return r.data}var v=class extends Error{statusCode;constructor(t,r){super(r),this.statusCode=t,this.name="HttpError"}};function Y(e){return t=>{e.node.res.statusCode=t}}function ee(){return(e,t)=>{throw new v(e,t)}}function te(e,t){let{statusCode:r,message:n}=Me(t.detail);return e.node.res.statusCode=r,{error:n,statusCode:r}}function Me(e){switch(e.kind){case"unknown_alias":return{statusCode:400,message:"Unknown authentication alias"};case"input_validation_failed":return{statusCode:400,message:"Input validation failed"};case"output_validation_failed":return{statusCode:500,message:"Internal server error"};case"config_load_failed":return{statusCode:500,message:"Configuration error"};case"broker_error":return{statusCode:502,message:"Broker error"};case"unsupported_body_type":return{statusCode:400,message:"Unsupported request body type"};case"unsupported_scheme":return{statusCode:400,message:"Unsupported URL scheme"};case"missing_execution_credentials":return{statusCode:401,message:"Missing execution credentials"};case"missing_tray_token":return{statusCode:500,message:"Missing Tray token"};case"db_call_failed":return{statusCode:502,message:e.message};case"db_query_failed":return{statusCode:502,message:`Database query failed: ${e.message}`};case"db_invalid_parameters":return{statusCode:400,message:e.message};case"kv_key_invalid":return{statusCode:400,message:e.message};case"kv_value_invalid":return{statusCode:400,message:e.message};case"kv_value_too_large":return{statusCode:400,message:e.message};case"kv_ttl_invalid":return{statusCode:400,message:e.message};case"kv_not_available":return{statusCode:501,message:"Key-value store is not available in this environment"};case"kv_call_failed":return{statusCode:502,message:"Key-value store request failed"};case"kv_requires_provisioning":return{statusCode:500,message:"Internal server error"};case"files_path_invalid":return{statusCode:400,message:e.message};case"files_value_invalid":return{statusCode:400,message:e.message};case"files_value_too_large":return{statusCode:400,message:e.message};case"files_not_available":return{statusCode:501,message:"File storage is not available in this environment"};case"files_call_failed":return{statusCode:502,message:"File storage request failed"};case"files_requires_provisioning":return{statusCode:500,message:"Internal server error"};case"call_function_path_invalid":return{statusCode:400,message:e.message};case"call_function_call_failed":return{statusCode:502,message:"Async function call failed"};case"call_function_requires_provisioning":return{statusCode:500,message:"Internal server error"};case"call_function_not_available":return{statusCode:501,message:"callFunctionAsync is not available in this environment"};case"call_function_missing_execution_jwt":return{statusCode:401,message:"Missing execution credentials"};case"ai_unsupported_service":case"ai_provider_misconfigured":case"ai_model_id_required":case"ai_model_instance_required":case"ai_provider_not_configured":case"ai_foreign_model_rejected":case"agent_sessions_failed":return{statusCode:500,message:e.kind==="ai_unsupported_service"?`AI service not supported for alias "${e.alias}"`:e.kind==="ai_provider_misconfigured"?`AI provider misconfigured for alias "${e.alias}"`:"Internal server error"};default:return{statusCode:500,message:`Unhandled error kind: ${e.kind}`}}}var We=["authorization","x-tray-token","set-cookie","x-kong-request-id","traceparent","x-real-ip","x-tray-user-email","x-tray-user-name","cookie"];function Ne(e){return e.toLowerCase().includes("tray_lid")}function b(e){let t={};for(let[r,n]of Object.entries(e))if(!We.includes(r.toLowerCase())){if(r.toLowerCase()==="cookie"&&n){let o=n.split(";").map(s=>s.trim()).filter(s=>{let d=s.split("=")[0].trim();return!Ne(d)}).join("; ");o&&(t[r]=o);continue}t[r]=n}return t}function Ve(e,t){let{inputSchema:r,outputSchema:n}=Xe(t),o=e;return Ze(async s=>{let d=_(),{executionId:a,userId:i,userEmail:g,userName:c,deploymentId:l}=Ye(d,s),p=d.mode==="lambda"?d.parentExecutionId??null:null,f=Date.now(),u=new Date().toISOString(),m=Ke(s),h=$e(s).pathname,ie=N(),A=W(),ae=`${m} ${h}`;D();let P={hasDb:!1,hasExternal:!1,hasAuth:!1,hasAi:!1,hasError:!1};return ze(()=>x.run(P,()=>H.run(a,async()=>{let S=await Be(s,r);if(!S.ok)return{response:S.response,errored:!1,errorMessage:null};let de=tt(s,S.input,ie,A,m,h,a,l,i,g,c,p);return Ge(o,de,n,s,A,a,l,{method:m,path:h,rawInput:S.input})})),{executionId:a,deploymentId:l,routeOrJob:ae,startedAt:u,startMs:f,userId:i,flags:P})})}async function ze(e,t){let r=!1,n=null;try{let o=await e();return r=o.errored,n=o.errorMessage,o.response}finally{j({...t,errored:r,errorMessage:n}),await O()}}async function Be(e,t){try{return{ok:!0,input:await X(e,t)}}catch(r){let n=et(e,r);if(n)return{ok:!1,response:n};throw r}}async function Ge(e,t,r,n,o,s,d,a){return L.startActiveSpan("function",{root:!0,kind:qe.SERVER,attributes:{method:a.method,route:a.path,executionId:s,...d?{deploymentId:d}:{}}},async i=>{t.traceId=i.spanContext().traceId;let g=b(ne(n));y(i,"input",a.rawInput),y(i,"request",{method:a.method,path:a.path,headers:g,body:a.rawInput});let c=!1,l=null,p,f;try{let u=await M.run(t,()=>e(t));if(p=u,u==null)n.node.res.statusCode=204,f="";else if(u instanceof Response)f=u;else if(r){let m=r.safeParse(u);if(!m.success){let h=Object.keys(m.error.flatten().fieldErrors);throw o.error("Output validation failed",{fields:h,executionId:s}),U.outputValidationFailed(h)}f=m.data}else f=u}catch(u){c=!0,l=u instanceof Error?u.message:String(u),F("hasError"),f=Je(u,n,o,s)}finally{Qe(i,n,{errored:c,errorMessage:l,handlerResult:p,response:f})}return{response:f,errored:c,errorMessage:l}})}function Je(e,t,r,n){if(e instanceof v)return t.node.res.statusCode=e.statusCode,{error:e.message,statusCode:e.statusCode};if(q(e))return te(t,e);r.error("Unhandled error in handler",{error:e instanceof Error?e.message:String(e),executionId:n}),t.node.res.statusCode=500;let o=process.env.NODE_ENV==="development";return{error:o&&e instanceof Error?e.message:"Internal server error",statusCode:500,...o&&e instanceof Error&&e.stack?{stack:e.stack}:{}}}function Qe(e,t,r){e.setAttribute("statusCode",t.node.res.statusCode),!r.errored&&r.handlerResult!==void 0&&y(e,"output",r.handlerResult),y(e,"response",r.response);let n=x.getStore();e.setAttribute("hasAuth",n?.hasAuth??!1),e.setAttribute("hasAi",n?.hasAi??!1),e.setAttribute("hasExternal",n?.hasExternal??!1),e.setAttribute("hasDb",n?.hasDb??!1),e.setAttribute("status",r.errored?"error":"success");let o=r.errored||(n?.hasError??!1);e.setStatus({code:o?re.ERROR:re.OK,...r.errorMessage?{message:r.errorMessage}:{}}),e.end()}function Xe(e){if(!e)return{inputSchema:void 0,outputSchema:void 0};if(e instanceof Object&&"_def"in e)return{inputSchema:e,outputSchema:void 0};if(typeof e=="object"&&("input"in e||"output"in e)){let t=e;return{inputSchema:t.input,outputSchema:t.output}}return{inputSchema:e,outputSchema:void 0}}function Ye(e,t){let r=e.mode==="lambda",n=(r?e.executionId:E(t,"x-tray-execution-id"))??Ue(),o=(r?e.userId:E(t,"x-tray-user-id"))||null,s=(r?e.userEmail:E(t,"x-tray-user-email"))||null,d=(r?e.userName:E(t,"x-tray-user-name"))||null,a=r?e.deploymentId??null:null;return{executionId:n,userId:o,userEmail:s,userName:d,deploymentId:a}}function et(e,t){if(!(t instanceof Error)||!("statusCode"in t)||!("data"in t))return null;let r=t.statusCode,n=t.data;e.node.res.statusCode=r;let o=n&&typeof n=="object"&&"fieldErrors"in n?n.fieldErrors:void 0;return{error:"Input validation failed",statusCode:r,...o?{fields:Object.keys(o)}:{}}}function tt(e,t,r,n,o,s,d,a,i,g,c,l){return{input:t,method:o,path:s,headers:b(ne(e)),http:Z(),db:p=>K(p),kv:()=>$(),files:()=>V(),callFunctionAsync:z(),ai:J(),agent:p=>Q(p),log:n,config:r,status:Y(e),error:ee(),state:{},request:e,executionId:d,deploymentId:a,userId:i,parentExecutionId:l,identity:i!==null?{user:{id:i,email:g,name:c}}:null,traceId:""}}function rt(e){return e}import{existsSync as nt,watch as ot,writeSync as st}from"fs";import{basename as it,dirname as at,join as dt,resolve as w}from"path";import{watchConfig as ut}from"c12";function ct(e,t){let r=e instanceof Error?e.message:String(e);st(2,`[helix-watch] ${t.phase} error: ${r}
2
+ `)}function I(){return{kind:"unprovisioned",name:"",authentications:{},config:{},region:"us1"}}var lt=/^(?:helix|tray)\.config\.(?:m|c)?[jt]s$/,oe=new Set;function se(e,t){return T(e,{configFile:t})!==void 0}async function ft(e,t,r){if(se(e.cwd,t))try{return{current:await C(e.cwd,{configFile:t}),initialLoadSucceeded:!0}}catch(n){return r(n,{phase:"reload"}),{current:I(),initialLoadSucceeded:!1}}if(e.watch){let n=t!==void 0?w(e.cwd,t):w(e.cwd);oe.has(n)||(process.stderr.write(t!==void 0?`warning: config file ${w(e.cwd,t)} not found; tray running with default config
3
3
  `:`warning: no helix.config.ts found at ${e.cwd}; tray running with default config \u2014 create one via \`helix init\`
4
- `),ne.add(n))}return{current:b(),initialLoadSucceeded:!1}}var I=class{constructor(t,r,n,o){this.cwd=t;this.configFile=r;this.onError=n;this.emit=o}cwd;configFile;onError;emit;stopped=!1;directoryWatcher=null;c12Unwatch=null;c12AttachPromise=null;updateChain=Promise.resolve();start(t){t?this.attachC12Watcher():this.attachCreationWatcher()}watcherReady(){return this.c12AttachPromise===null?Promise.resolve():this.c12AttachPromise.catch(()=>{})}async stop(){this.stopped=!0,this.directoryWatcher&&(this.directoryWatcher.close(),this.directoryWatcher=null),this.c12AttachPromise&&await this.c12AttachPromise.catch(t=>this.onError(t,{phase:"attach"})),this.c12Unwatch&&(await this.c12Unwatch(),this.c12Unwatch=null)}attachC12Watcher(){this.c12AttachPromise===null&&(this.c12AttachPromise=at({...V(this.cwd,{configFile:this.configFile}),onUpdate:({newConfig:t})=>{this.stopped||(this.updateChain=this.updateChain.then(async()=>{if(this.stopped)return;let r;try{r=z(t.config,this.cwd)}catch(n){this.onError(n,{phase:"validation"});return}try{this.emit(r)}catch(n){this.onError(n,{phase:"reload"})}}))}}).then(async t=>{if(this.stopped){t.unwatch();return}this.c12Unwatch=t.unwatch;let{watch:r}=await import("chokidar"),n=r(this.cwd,{persistent:!1,depth:0});try{await new Promise((o,s)=>{n.once("ready",o),n.once("error",s)})}finally{await n.close()}}).catch(t=>{this.onError(t,{phase:"attach"})}))}attachCreationWatcher(){let t=this.configFile!==void 0?w(this.cwd,this.configFile):void 0,r=t!==void 0?st(t):this.cwd;try{this.directoryWatcher=rt(r,{persistent:!1},(n,o)=>{if(this.stopped||!o)return;let s=o.toString();if(t!==void 0){if(s!==ot(t))return}else if(!ut.test(s))return;tt(it(r,s))&&(this.updateChain=this.updateChain.then(async()=>{if(this.stopped)return;let d;try{d=await y(this.cwd,{configFile:this.configFile})}catch(i){this.onError(i,{phase:"reload"});return}if(this.stopped)return;this.emit(d);let a=this.directoryWatcher;a&&(this.directoryWatcher=null,a.close()),this.attachC12Watcher()}))}),this.directoryWatcher.on("error",n=>{this.onError(n,{phase:"attach"})})}catch(n){this.onError(n,{phase:"attach"})}}};async function lt(e){let t=e.onError??dt,r=new Set,n=x(e.configFile),o=await ct(e,n,t),s=o.current;function d(i){s=i;for(let f of[...r])try{f(i)}catch(c){t(c,{phase:"reload"})}}let a=new I(e.cwd,n,t,d);return e.watch&&a.start(o.initialLoadSucceeded),{get(){return s},async reload(){if(!oe(e.cwd,n)){let i=b();return d(i),i}try{let i=await y(e.cwd,{configFile:n});return d(i),i}catch(i){return t(i,{phase:"reload"}),s}},subscribe(i){return r.add(i),()=>{r.delete(i)}},async stop(){r.clear(),await a.stop()},ready(){return a.watcherReady()}}}import{tool as sr,dynamicTool as ir,jsonSchema as ar,zodSchema as dr,stepCountIs as ur,hasToolCall as cr,convertToModelMessages as lr,cosineSimilarity as fr,smoothStream as pr,Output as gr}from"ai";export{_e as AGENT_DEFINITION_KIND,ge as AI_SERVICES,ye as HELIX_CONFIG_ENV,gr as Output,ue as REGION_VALUES,be as SCHEDULE_DEFINITION_KIND,Ie as ScheduleConfigError,Se as TOOL_DEFINITION_KIND,Ce as WORKSPACE_ID_REQUIRED_CODE,pe as agentSessionsSchema,me as aiProviderEntrySchema,lr as convertToModelMessages,fr as cosineSimilarity,lt as createConfigService,xe as defineAgent,et as defineConfig,Ke as defineFunction,Re as defineSchedule,we as defineTool,ir as dynamicTool,de as getContext,E as getSdkConfig,cr as hasToolCall,ke as isAgentDefinition,Ae as isScheduleDefinition,Ee as isToolDefinition,ar as jsonSchema,y as loadConfig,he as loadedTrayConfigSchema,le as projectIdSchema,ce as regionSchema,ve as requireWorkspaceId,k as resolveConfigFile,x as resolveConfigOverride,ae as runWithinAppSpan,pr as smoothStream,ur as stepCountIs,sr as tool,Te as totalToolCallsIs,fe as workspaceIdSchema,dr as zodSchema};
4
+ `),oe.add(n))}return{current:I(),initialLoadSucceeded:!1}}var R=class{constructor(t,r,n,o){this.cwd=t;this.configFile=r;this.onError=n;this.emit=o}cwd;configFile;onError;emit;stopped=!1;directoryWatcher=null;c12Unwatch=null;c12AttachPromise=null;updateChain=Promise.resolve();start(t){t?this.attachC12Watcher():this.attachCreationWatcher()}watcherReady(){return this.c12AttachPromise===null?Promise.resolve():this.c12AttachPromise.catch(()=>{})}async stop(){this.stopped=!0,this.directoryWatcher&&(this.directoryWatcher.close(),this.directoryWatcher=null),this.c12AttachPromise&&await this.c12AttachPromise.catch(t=>this.onError(t,{phase:"attach"})),this.c12Unwatch&&(await this.c12Unwatch(),this.c12Unwatch=null)}attachC12Watcher(){this.c12AttachPromise===null&&(this.c12AttachPromise=ut({...B(this.cwd,{configFile:this.configFile}),onUpdate:({newConfig:t})=>{this.stopped||(this.updateChain=this.updateChain.then(async()=>{if(this.stopped)return;let r;try{r=G(t.config,this.cwd)}catch(n){this.onError(n,{phase:"validation"});return}try{this.emit(r)}catch(n){this.onError(n,{phase:"reload"})}}))}}).then(async t=>{if(this.stopped){t.unwatch();return}this.c12Unwatch=t.unwatch;let{watch:r}=await import("chokidar"),n=r(this.cwd,{persistent:!1,depth:0});try{await new Promise((o,s)=>{n.once("ready",o),n.once("error",s)})}finally{await n.close()}}).catch(t=>{this.onError(t,{phase:"attach"})}))}attachCreationWatcher(){let t=this.configFile!==void 0?w(this.cwd,this.configFile):void 0,r=t!==void 0?at(t):this.cwd;try{this.directoryWatcher=ot(r,{persistent:!1},(n,o)=>{if(this.stopped||!o)return;let s=o.toString();if(t!==void 0){if(s!==it(t))return}else if(!lt.test(s))return;nt(dt(r,s))&&(this.updateChain=this.updateChain.then(async()=>{if(this.stopped)return;let d;try{d=await C(this.cwd,{configFile:this.configFile})}catch(i){this.onError(i,{phase:"reload"});return}if(this.stopped)return;this.emit(d);let a=this.directoryWatcher;a&&(this.directoryWatcher=null,a.close()),this.attachC12Watcher()}))}),this.directoryWatcher.on("error",n=>{this.onError(n,{phase:"attach"})})}catch(n){this.onError(n,{phase:"attach"})}}};async function pt(e){let t=e.onError??ct,r=new Set,n=k(e.configFile),o=await ft(e,n,t),s=o.current;function d(i){s=i;for(let g of[...r])try{g(i)}catch(c){t(c,{phase:"reload"})}}let a=new R(e.cwd,n,t,d);return e.watch&&a.start(o.initialLoadSucceeded),{get(){return s},async reload(){if(!se(e.cwd,n)){let i=I();return d(i),i}try{let i=await C(e.cwd,{configFile:n});return d(i),i}catch(i){return t(i,{phase:"reload"}),s}},subscribe(i){return r.add(i),()=>{r.delete(i)}},async stop(){r.clear(),await a.stop()},ready(){return a.watcherReady()}}}import{tool as ar,dynamicTool as dr,jsonSchema as ur,zodSchema as cr,stepCountIs as lr,hasToolCall as fr,convertToModelMessages as pr,cosineSimilarity as gr,smoothStream as mr,Output as hr}from"ai";export{ke as AGENT_DEFINITION_KIND,he as AI_SERVICES,ve as HELIX_CONFIG_ENV,hr as Output,le as REGION_VALUES,Re as SCHEDULE_DEFINITION_KIND,Ae as ScheduleConfigError,we as TOOL_DEFINITION_KIND,Se as WORKSPACE_ID_REQUIRED_CODE,me as agentSessionsSchema,ye as aiProviderEntrySchema,pr as convertToModelMessages,gr as cosineSimilarity,pt as createConfigService,Te as defineAgent,rt as defineConfig,Ve as defineFunction,Pe as defineSchedule,_e as defineTool,dr as dynamicTool,ce as getContext,_ as getSdkConfig,fr as hasToolCall,be as isAgentDefinition,He as isScheduleDefinition,xe as isToolDefinition,ur as jsonSchema,C as loadConfig,Ce as loadedTrayConfigSchema,pe as projectIdSchema,fe as regionSchema,Ee as requireWorkspaceId,T as resolveConfigFile,k as resolveConfigOverride,ue as runWithinAppSpan,mr as smoothStream,lr as stepCountIs,ar as tool,Ie as totalToolCallsIs,ge as workspaceIdSchema,cr as zodSchema};
@@ -1,7 +1,7 @@
1
- import { L as LoadedTrayConfig, b as AgentDefinition } from '../define-agent-DXV_nHvs.js';
2
- export { z as SdkConfigInput, B as setSdkConfig } from '../define-agent-DXV_nHvs.js';
3
- import { j as AgentSessionsList, b as AgentCallOptions, e as AgentResult } from '../types-CVW_-1wh.js';
4
- export { O as SessionExpiredError, Q as clearAgentSessions } from '../types-CVW_-1wh.js';
1
+ import { L as LoadedTrayConfig, b as AgentDefinition } from '../define-agent-BEUgQ_5-.js';
2
+ export { z as SdkConfigInput, B as setSdkConfig } from '../define-agent-BEUgQ_5-.js';
3
+ import { j as AgentSessionsList, b as AgentCallOptions, e as AgentResult } from '../types-BSbvztCi.js';
4
+ export { O as SessionExpiredError, Q as clearAgentSessions } from '../types-BSbvztCi.js';
5
5
  import 'zod';
6
6
  import 'h3';
7
7
  import 'ky';
@@ -69,9 +69,12 @@ declare function runScheduledFunction(definition: unknown, invocation: ScheduleI
69
69
  * @internal — exported via `@trayai/helix-sdk/internal` only.
70
70
  */
71
71
  /** Caller identity for user-scoped agents — the dev route forwards
72
- `x-tray-user-id` here, mirroring `readInvocationContext` in dev. */
72
+ `x-tray-user-id` / `-email` / `-name` here, mirroring
73
+ `readInvocationContext` in dev. */
73
74
  interface StandaloneIdentity {
74
75
  userId?: string | null;
76
+ userEmail?: string | null;
77
+ userName?: string | null;
75
78
  }
76
79
  /** Invoke an agent outside a defineFunction execution. */
77
80
  declare function runAgentStandalone(name: string, options: AgentCallOptions, identity?: StandaloneIdentity): Promise<AgentResult>;
@@ -314,4 +317,4 @@ declare function getAdditionalRegionProfiles(): RegionProfile[];
314
317
  /** Test helper: drop non-builtin profiles and restore the built-in regions. */
315
318
  declare function resetRegionRegistryForTests(): void;
316
319
 
317
- export { AgentCallerError, CONFIG_BRIDGE_CHANNEL, DEV_TOKEN_BRIDGE_CHANNEL, type RegionProfile, type ScheduleInvocation, ScheduleInvocationError, SdkError, assertValidPath, clearActiveConfig, clearAgentRegistry, contentFilePath, getActiveConfig, getAdditionalRegionProfiles, getAgentDefinition, getRegionProfile, isKnownRegion, isSdkError, listAgentSessionsStandalone, listAgents, listExposedRegionNames, listRegionNames, metaFilePath, parseExposedRegionName, registerRegionProfile, requireRegionProfile, resetRegionRegistryForTests, resolveForcedRegion, runAgentStandalone, runScheduledFunction, setActiveConfig, setAgentBaseDir, setAgentInstructions, setForcedRegion };
320
+ export { AgentCallerError, CONFIG_BRIDGE_CHANNEL, DEV_TOKEN_BRIDGE_CHANNEL, type RegionProfile, type ScheduleInvocation, ScheduleInvocationError, SdkError, type StandaloneIdentity, assertValidPath, clearActiveConfig, clearAgentRegistry, contentFilePath, getActiveConfig, getAdditionalRegionProfiles, getAgentDefinition, getRegionProfile, isKnownRegion, isSdkError, listAgentSessionsStandalone, listAgents, listExposedRegionNames, listRegionNames, metaFilePath, parseExposedRegionName, registerRegionProfile, requireRegionProfile, resetRegionRegistryForTests, resolveForcedRegion, runAgentStandalone, runScheduledFunction, setActiveConfig, setAgentBaseDir, setAgentInstructions, setForcedRegion };
@@ -1 +1 @@
1
- import{$ as At,O as E,S as ft,T as dt,U as mt,V as gt,W as pt,X as ht,a as J,aa as St,b as V,c as q,ca as l,d as R,e as z,f as g,g as P,ga as v,h as F,i as N,j as p,k as O,l as k,m as j,o as A,p as M,q as S,r as x,s as y,t as lt,u as ct,v as ut,w as I,x as C}from"../chunk-3WKD2ENP.js";import{a as h}from"../chunk-WUCX7RZO.js";import{c as G,d as D,g as Q,h as W,i as X,j as Y,k as Z,l as tt,m as et,n as rt,o as ot,p as nt,q as it,r as st,s as at}from"../chunk-JKFMPHA4.js";import{randomUUID as xt}from"crypto";import{SpanStatusCode as H,SpanKind as yt}from"@opentelemetry/api";var i=class extends Error{constructor(t){super(`runScheduledFunction: ${t}`),this.name="ScheduleInvocationError"}};async function It(e,t){if(typeof t!="object"||t===null)throw new i("`invocation` must be an object");let{schedulePath:r}=t;if(typeof r!="string"||r.length===0)throw new i("`schedulePath` must be a non-empty string");if(typeof t.isManual!="boolean")throw new i("`isManual` must be a boolean");if(!v(e))throw new i(`default export of "${r}" is not a defineSchedule definition`);let c=L("scheduledAt",t.scheduledAt),b=L("firedAt",t.firedAt),a=D(),u=a.executionId??xt(),f=a.deploymentId??null,K=Date.now(),$=new Date().toISOString(),U=M(),_=A();p();let s={hasDb:!1,hasExternal:!1,hasAuth:!1,hasAi:!1,hasError:!1},d=!1,m=null;try{await P.run(s,()=>g.run(u,()=>k.startActiveSpan("schedule",{root:!0,kind:yt.SERVER,attributes:{method:"SCHEDULE",route:r,executionId:u,...f?{deploymentId:f}:{}}},async n=>{let B={type:"schedule",scheduledAt:c,firedAt:b,isManual:t.isManual},w={http:S(),db:o=>x(o),kv:()=>y(),files:()=>I(),callFunctionAsync:C(),ai:E(),agent:o=>l(o),log:_,config:U,state:{},executionId:u,deploymentId:f,traceId:n.spanContext().traceId,parentExecutionId:null,trigger:B};N(n,"input",{scheduledAt:t.scheduledAt,firedAt:t.firedAt,isManual:t.isManual});try{await h.run(w,()=>e.handler(w))}catch(o){throw d=!0,m=o instanceof Error?o.message:String(o),F("hasError"),o}finally{n.setAttribute("hasAuth",s.hasAuth),n.setAttribute("hasAi",s.hasAi),n.setAttribute("hasExternal",s.hasExternal),n.setAttribute("hasDb",s.hasDb),n.setAttribute("status",d?"error":"success");let o=d||s.hasError;n.setStatus({code:o?H.ERROR:H.OK,...m?{message:m}:{}}),n.end()}})))}finally{j({executionId:u,deploymentId:f,triggerType:"schedule",routeOrJob:r,startedAt:$,startMs:K,errored:d,errorMessage:m,userId:null,flags:s}),await O()}}function L(e,t){if(typeof t!="string"||t.length===0)throw new i(`\`${e}\` must be a timestamp string; got ${JSON.stringify(t)}`);let r=new Date(t);if(Number.isNaN(r.getTime()))throw new i(`\`${e}\` must be a Date-parseable timestamp; got ${JSON.stringify(t)}`);return r}function T(e,t){p();let r=R(),c=crypto.randomUUID(),b={http:S(),db:a=>x(a),kv:()=>y(),files:()=>I(),callFunctionAsync:C(),ai:E(),agent:a=>l(a),log:A(),config:r.config??{},state:{},executionId:c,deploymentId:null,traceId:"",parentExecutionId:null,userId:e.userId??null};return g.run(c,()=>h.run(b,t))}async function Ct(e,t,r={}){return T(r,()=>l(e).generate(t))}async function Et(e,t){return T({userId:t.userId},()=>l(e).sessions({...t.first!==void 0?{first:t.first}:{},...t.cursor!==void 0?{cursor:t.cursor}:{}}))}export{ft as AgentCallerError,J as CONFIG_BRIDGE_CHANNEL,V as DEV_TOKEN_BRIDGE_CHANNEL,i as ScheduleInvocationError,st as SdkError,At as SessionExpiredError,lt as assertValidPath,z as clearActiveConfig,ht as clearAgentRegistry,St as clearAgentSessions,ct as contentFilePath,R as getActiveConfig,nt as getAdditionalRegionProfiles,gt as getAgentDefinition,X as getRegionProfile,W as isKnownRegion,at as isSdkError,Et as listAgentSessionsStandalone,pt as listAgents,tt as listExposedRegionNames,Z as listRegionNames,ut as metaFilePath,et as parseExposedRegionName,Q as registerRegionProfile,Y as requireRegionProfile,it as resetRegionRegistryForTests,ot as resolveForcedRegion,Ct as runAgentStandalone,It as runScheduledFunction,q as setActiveConfig,dt as setAgentBaseDir,mt as setAgentInstructions,rt as setForcedRegion,G as setSdkConfig};
1
+ import{$ as Ae,O as C,S as fe,T as me,U as de,V as ge,W as pe,X as he,a as J,aa as Se,b as V,c as q,ca as l,d as R,e as z,f as g,g as P,ga as v,h as F,i as N,j as p,k as O,l as k,m as j,o as A,p as M,q as S,r as x,s as y,t as le,u as ce,v as ue,w as I,x as E}from"../chunk-GMEVZH35.js";import{a as h}from"../chunk-WUCX7RZO.js";import{c as G,d as D,g as Q,h as W,i as X,j as Y,k as Z,l as ee,m as te,n as re,o as oe,p as ne,q as se,r as ie,s as ae}from"../chunk-LKZKDHYO.js";import{randomUUID as xe}from"crypto";import{SpanStatusCode as H,SpanKind as ye}from"@opentelemetry/api";var s=class extends Error{constructor(e){super(`runScheduledFunction: ${e}`),this.name="ScheduleInvocationError"}};async function Ie(t,e){if(typeof e!="object"||e===null)throw new s("`invocation` must be an object");let{schedulePath:r}=e;if(typeof r!="string"||r.length===0)throw new s("`schedulePath` must be a non-empty string");if(typeof e.isManual!="boolean")throw new s("`isManual` must be a boolean");if(!v(t))throw new s(`default export of "${r}" is not a defineSchedule definition`);let b=L("scheduledAt",e.scheduledAt),c=L("firedAt",e.firedAt),u=D(),i=u.executionId??xe(),f=u.deploymentId??null,K=Date.now(),$=new Date().toISOString(),U=M(),_=A();p();let a={hasDb:!1,hasExternal:!1,hasAuth:!1,hasAi:!1,hasError:!1},m=!1,d=null;try{await P.run(a,()=>g.run(i,()=>k.startActiveSpan("schedule",{root:!0,kind:ye.SERVER,attributes:{method:"SCHEDULE",route:r,executionId:i,...f?{deploymentId:f}:{}}},async n=>{let B={type:"schedule",scheduledAt:b,firedAt:c,isManual:e.isManual},w={http:S(),db:o=>x(o),kv:()=>y(),files:()=>I(),callFunctionAsync:E(),ai:C(),agent:o=>l(o),log:_,config:U,state:{},executionId:i,deploymentId:f,traceId:n.spanContext().traceId,parentExecutionId:null,trigger:B};N(n,"input",{scheduledAt:e.scheduledAt,firedAt:e.firedAt,isManual:e.isManual});try{await h.run(w,()=>t.handler(w))}catch(o){throw m=!0,d=o instanceof Error?o.message:String(o),F("hasError"),o}finally{n.setAttribute("hasAuth",a.hasAuth),n.setAttribute("hasAi",a.hasAi),n.setAttribute("hasExternal",a.hasExternal),n.setAttribute("hasDb",a.hasDb),n.setAttribute("status",m?"error":"success");let o=m||a.hasError;n.setStatus({code:o?H.ERROR:H.OK,...d?{message:d}:{}}),n.end()}})))}finally{j({executionId:i,deploymentId:f,triggerType:"schedule",routeOrJob:r,startedAt:$,startMs:K,errored:m,errorMessage:d,userId:null,flags:a}),await O()}}function L(t,e){if(typeof e!="string"||e.length===0)throw new s(`\`${t}\` must be a timestamp string; got ${JSON.stringify(e)}`);let r=new Date(e);if(Number.isNaN(r.getTime()))throw new s(`\`${t}\` must be a Date-parseable timestamp; got ${JSON.stringify(e)}`);return r}function T(t,e){p();let r=t.userId||null,b=R(),c=crypto.randomUUID(),u={http:S(),db:i=>x(i),kv:()=>y(),files:()=>I(),callFunctionAsync:E(),ai:C(),agent:i=>l(i),log:A(),config:b.config??{},state:{},executionId:c,deploymentId:null,traceId:"",parentExecutionId:null,userId:r,identity:r!==null?{user:{id:r,email:t.userEmail||null,name:t.userName||null}}:null};return g.run(c,()=>h.run(u,e))}async function Ee(t,e,r={}){return T(r,()=>l(t).generate(e))}async function Ce(t,e){return T({userId:e.userId},()=>l(t).sessions({...e.first!==void 0?{first:e.first}:{},...e.cursor!==void 0?{cursor:e.cursor}:{}}))}export{fe as AgentCallerError,J as CONFIG_BRIDGE_CHANNEL,V as DEV_TOKEN_BRIDGE_CHANNEL,s as ScheduleInvocationError,ie as SdkError,Ae as SessionExpiredError,le as assertValidPath,z as clearActiveConfig,he as clearAgentRegistry,Se as clearAgentSessions,ce as contentFilePath,R as getActiveConfig,ne as getAdditionalRegionProfiles,ge as getAgentDefinition,X as getRegionProfile,W as isKnownRegion,ae as isSdkError,Ce as listAgentSessionsStandalone,pe as listAgents,ee as listExposedRegionNames,Z as listRegionNames,ue as metaFilePath,te as parseExposedRegionName,Q as registerRegionProfile,Y as requireRegionProfile,se as resetRegionRegistryForTests,oe as resolveForcedRegion,Ee as runAgentStandalone,Ie as runScheduledFunction,q as setActiveConfig,me as setAgentBaseDir,de as setAgentInstructions,re as setForcedRegion,G as setSdkConfig};
@@ -1,10 +1,25 @@
1
- import { P as PlatformContext } from '../types-CVW_-1wh.js';
1
+ import { P as PlatformContext } from '../types-BSbvztCi.js';
2
2
  import 'h3';
3
3
  import 'ky';
4
4
  import 'zod';
5
5
  import 'ai';
6
6
  import '@ai-sdk/provider';
7
7
 
8
+ /**
9
+ * Mock shape accepted by `runWithContext`: any subset of `PlatformContext`,
10
+ * except that `identity.user.email` / `identity.user.name` may be omitted
11
+ * (they default to `null`, as in a real context where the platform has no
12
+ * value). Extra keys on `identity.user` pass through untouched.
13
+ */
14
+ type MockContext = Omit<Partial<PlatformContext>, "identity"> & {
15
+ identity?: {
16
+ user: {
17
+ id: string;
18
+ email?: string | null;
19
+ name?: string | null;
20
+ };
21
+ } | null;
22
+ };
8
23
  /**
9
24
  * Run code within a mock PlatformContext — for unit testing shared code that
10
25
  * calls getContext(). Unset core fields throw on access via Proxy, as does
@@ -12,6 +27,6 @@ import '@ai-sdk/provider';
12
27
  * optional fields (request surface, trigger) return undefined, as in a real
13
28
  * execution of a kind that doesn't carry them.
14
29
  */
15
- declare function runWithContext<T>(partial: Partial<PlatformContext>, fn: () => T | Promise<T>): Promise<T>;
30
+ declare function runWithContext<T>(partial: MockContext, fn: () => T | Promise<T>): Promise<T>;
16
31
 
17
- export { runWithContext };
32
+ export { type MockContext, runWithContext };
@@ -1 +1 @@
1
- import{a as n}from"../chunk-WUCX7RZO.js";var f={http:!0,db:!0,kv:!0,files:!0,callFunctionAsync:!0,ai:!0,agent:!0,log:!0,config:!0,state:!0,executionId:!0,deploymentId:!0,traceId:!0,parentExecutionId:!0},d={input:!0,method:!0,path:!0,headers:!0,status:!0,error:!0,request:!0,userId:!0,identity:!0,trigger:!0};async function l(o,u){let i=new Proxy(o,{get(e,t,r){if(typeof t=="symbol"||t==="then"||t==="toJSON"||t in e)return Reflect.get(e,t,r);if(!(t in d))throw t in f?new Error(`Accessed unset context field "${String(t)}" in test. Provide it via runWithContext({ ${String(t)}: ... }, fn).`):new Error(`Accessed unknown context field "${String(t)}" in test \u2014 not a PlatformContext member.`)}});return n.run(i,u)}export{l as runWithContext};
1
+ import{a as l}from"../chunk-WUCX7RZO.js";var s={http:!0,db:!0,kv:!0,files:!0,callFunctionAsync:!0,ai:!0,agent:!0,log:!0,config:!0,state:!0,executionId:!0,deploymentId:!0,traceId:!0,parentExecutionId:!0},a={input:!0,method:!0,path:!0,headers:!0,status:!0,error:!0,request:!0,userId:!0,identity:!0,trigger:!0};function f(e){if(e===null||typeof e!="object")return e;let{user:n}=e;if(n===null||typeof n!="object")return e;let r=n;return{...e,user:{...r,email:r.email??null,name:r.name??null}}}async function c(e,n){let r=new Proxy(e,{get(o,t,u){if(typeof t=="symbol"||t==="then"||t==="toJSON")return Reflect.get(o,t,u);if(t in o){let i=Reflect.get(o,t,u);return t==="identity"?f(i):i}if(!(t in a))throw t in s?new Error(`Accessed unset context field "${String(t)}" in test. Provide it via runWithContext({ ${String(t)}: ... }, fn).`):new Error(`Accessed unknown context field "${String(t)}" in test \u2014 not a PlatformContext member.`)}});return l.run(r,n)}export{c as runWithContext};
@@ -538,14 +538,18 @@ interface TrayContext<T = Record<string, unknown>> extends ContextCore {
538
538
  request: H3Event;
539
539
  userId: string | null;
540
540
  /**
541
- * Minimal user identity context (spec 15). Production currently carries
542
- * only the user ID (invocation payload root in lambda; x-tray-user-id
543
- * header in dev) — richer fields (email, name, groups, roles) arrive with
544
- * the full identity feature. Null when no user is known.
541
+ * User identity context (spec 15). `id`, `email` and `name` are populated
542
+ * for HTTP executions by logged-in users and project API tokens; `email`
543
+ * and `name` are null when the platform did not supply them (for example
544
+ * bundles built before they were carried). Groups, roles and org details
545
+ * are still deferred. The whole object is null when no user is known
546
+ * (schedules, `ctx.callFunctionAsync` runs, anonymous callers).
545
547
  */
546
548
  identity: {
547
549
  user: {
548
550
  id: string;
551
+ email: string | null;
552
+ name: string | null;
549
553
  };
550
554
  } | null;
551
555
  }
@@ -596,6 +600,8 @@ interface PlatformContext extends ContextCore {
596
600
  identity?: {
597
601
  user: {
598
602
  id: string;
603
+ email: string | null;
604
+ name: string | null;
599
605
  };
600
606
  } | null;
601
607
  trigger?: ScheduleTrigger;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trayai/helix-sdk",
3
- "version": "1.13.2",
3
+ "version": "1.15.0",
4
4
  "description": "Helix SDK runtime — defineFunction, ctx, defineConfig, authed HTTP",
5
5
  "license": "Apache-2.0",
6
6
  "author": "trayio",
@@ -1 +0,0 @@
1
- var b="X-Helix-Project-Execution-Token",R="X-Tray-Token",q={mode:"dev",deploymentId:null},k={...q},p={};function te(e){let{internalJwt:r,helixExecutionJwt:t,devToken:n,...i}=e;"internalJwt"in e&&(p.internalJwt=r),"helixExecutionJwt"in e&&(p.helixExecutionJwt=t),"devToken"in e&&(p.devToken=n),k={...k,...i}}function ne(){return k}function S(){return p.internalJwt}function P(){return p.helixExecutionJwt}function I(){return p.devToken}var O=new Set(["us1","eu1","ap1","ap2"]),s=new Map,h={name:"us1",exposedName:"us1",displayName:"us1",hosts:{api:"https://api.tray.io",broker:"https://api.tray.io/private/v1/code",ingest:"https://api.tray.io/private/v1/helix/otlp",weaver:"https://weaver.tray.io",app:"https://app.tray.io",projectHost:"helix-app.ai",dashboard:"https://app.helix.tray.ai",auth:"https://auth.tray.io"},login:{storePrefix:"PROD",appUrl:"https://app.tray.io",cookieName:"prod_tray_lid",cookieDomain:"tray.io"}},v={name:"eu1",exposedName:"eu1",displayName:"eu1",hosts:{api:"https://api.eu1.tray.io",broker:"https://api.eu1.tray.io/private/v1/code",ingest:"https://api.eu1.tray.io/private/v1/helix/otlp",weaver:"https://weaver.eu1.tray.io",app:"https://app.eu1.tray.io",projectHost:"eu1.helix-app.ai",dashboard:"https://app.helix.eu1.tray.ai",auth:"https://auth.eu1.tray.io"},login:{storePrefix:"EU1",appUrl:"https://app.eu1.tray.io",cookieName:"prod_tray_lid_eu",cookieDomain:"tray.io"}},x={name:"ap1",exposedName:"ap1",displayName:"ap1",hosts:{api:"https://api.ap1.tray.io",broker:"https://api.ap1.tray.io/private/v1/code",ingest:"https://api.ap1.tray.io/private/v1/helix/otlp",weaver:"https://weaver.ap1.tray.io",app:"https://app.ap1.tray.io",projectHost:"ap1.helix-app.ai",dashboard:"https://app.helix.ap1.tray.ai",auth:"https://auth.ap1.tray.io"},login:{storePrefix:"AP1",appUrl:"https://app.ap1.tray.io",cookieName:"prod_tray_lid_ap",cookieDomain:"tray.io"}},E={name:"ap2",exposedName:"ap2",displayName:"ap2",hosts:{api:"https://api.ap2.tray.io",broker:"https://api.ap2.tray.io/private/v1/code",ingest:"https://api.ap2.tray.io/private/v1/helix/otlp",weaver:"https://weaver.ap2.tray.io",app:"https://app.ap2.tray.io",projectHost:"ap2.helix-app.ai",dashboard:"https://app.helix.ap2.tray.ai",auth:"https://auth.ap2.tray.io"},login:{storePrefix:"AP2",appUrl:"https://app.ap2.tray.io",cookieName:"prod_tray_lid_ap2",cookieDomain:"tray.io"}};s.set(h.name,h);s.set(v.name,v);s.set(x.name,x);s.set(E.name,E);var T=["api","broker","ingest","weaver","app","projectHost","dashboard"],N=["auth"],D=["storePrefix","appUrl","cookieName","cookieDomain"];function C(e){if(!e.name||typeof e.name!="string")throw new Error("RegionProfile.name must be a non-empty string");if(!e.exposedName||typeof e.exposedName!="string")throw new Error("RegionProfile.exposedName must be a non-empty string");if(!e.displayName||typeof e.displayName!="string")throw new Error("RegionProfile.displayName must be a non-empty string");if(!e.hosts||typeof e.hosts!="object")throw new Error("RegionProfile.hosts must be an object");if(!e.login||typeof e.login!="object")throw new Error("RegionProfile.login must be an object");for(let r of T)if(typeof e.hosts[r]!="string"||!e.hosts[r])throw new Error(`RegionProfile.hosts.${r} must be a non-empty string`);for(let r of N){let t=e.hosts[r];if(t!==void 0&&(typeof t!="string"||!t))throw new Error(`RegionProfile.hosts.${r} must be a non-empty string when set`)}for(let r of D)if(typeof e.login[r]!="string"||!e.login[r])throw new Error(`RegionProfile.login.${r} must be a non-empty string`)}function j(e,r){return e.name===r.name&&e.exposedName===r.exposedName&&e.displayName===r.displayName&&T.every(t=>e.hosts[t]===r.hosts[t])&&N.every(t=>e.hosts[t]===r.hosts[t])&&D.every(t=>e.login[t]===r.login[t])}function oe(e){C(e);let r=s.get(e.name);if(r){if(j(r,e))return;throw new Error(`RegionProfile.name "${e.name}" is already registered with different values`)}for(let t of s.values())if(t.exposedName===e.exposedName)throw new Error(`RegionProfile.exposedName "${e.exposedName}" is already used by "${t.name}"`);s.set(e.name,e)}function H(e){return s.has(e)}function se(e){return s.get(e)}function m(e){let r=s.get(e);if(!r)throw new Error(`Unknown region: ${e}`);return r}function ae(){return[...s.keys()]}function de(){return[...s.values()].map(e=>e.exposedName)}function F(e){for(let r of s.values())if(r.exposedName===e)return r.name}var f=Symbol.for("@trayai/helix-sdk.forcedEnvironment");function B(e){let r=globalThis;if(e===void 0||e.trim()===""){delete r[f];return}let t=e.trim(),n=F(t);if(n){r[f]=n;return}if(H(t)){r[f]=t;return}throw new Error(`Unknown region: ${t}`)}function le(){return globalThis[f]}function ue(){return[...s.values()].filter(e=>!O.has(e.name))}function ce(){B(void 0),s.clear();for(let e of[h,v,x,E])s.set(e.name,{...e,hosts:{...e.hosts},login:{...e.login}})}var u=class e extends Error{detail;constructor(r){super(L(r)),this.name="SdkError",this.detail=r}get kind(){return this.detail.kind}static unknownAlias(r,t){return new e({kind:"unknown_alias",alias:r,available:t})}static inputValidationFailed(r){return new e({kind:"input_validation_failed",fields:r})}static outputValidationFailed(r){return new e({kind:"output_validation_failed",fields:r})}static configLoadFailed(r){return new e({kind:"config_load_failed",cause:r})}static brokerError(r,t,n,i){return new e({kind:"broker_error",status:r,message:t,body:n,code:i})}static unsupportedBodyType(r){return new e({kind:"unsupported_body_type",actualType:r})}static unsupportedScheme(r){return new e({kind:"unsupported_scheme",scheme:r})}static missingExecutionCredentials(){return new e({kind:"missing_execution_credentials"})}static missingTrayToken(){return new e({kind:"missing_tray_token"})}static dbCallFailed(r,t){return new e({kind:"db_call_failed",message:r,cause:t})}static dbQueryFailed(r){return new e({kind:"db_query_failed",message:r})}static dbInvalidParameters(r){return new e({kind:"db_invalid_parameters",message:r})}static kvKeyInvalid(r){return new e({kind:"kv_key_invalid",message:r})}static kvValueInvalid(r){return new e({kind:"kv_value_invalid",message:r})}static kvValueTooLarge(r,t){return new e({kind:"kv_value_too_large",message:r,maxBytes:t})}static kvTtlInvalid(r){return new e({kind:"kv_ttl_invalid",message:r})}static kvNotAvailable(){return new e({kind:"kv_not_available"})}static kvCallFailed(r,t,n){return new e({kind:"kv_call_failed",status:r,message:t,body:n})}static kvRequiresProvisioning(){return new e({kind:"kv_requires_provisioning"})}static filesPathInvalid(r){return new e({kind:"files_path_invalid",message:r})}static filesValueInvalid(r){return new e({kind:"files_value_invalid",message:r})}static filesValueTooLarge(r,t){return new e({kind:"files_value_too_large",message:r,maxBytes:t})}static filesNotAvailable(){return new e({kind:"files_not_available"})}static filesCallFailed(r,t,n){return new e({kind:"files_call_failed",status:r,message:t,body:n})}static filesRequiresProvisioning(){return new e({kind:"files_requires_provisioning"})}static callFunctionPathInvalid(r){return new e({kind:"call_function_path_invalid",message:r})}static callFunctionCallFailed(r,t,n){return new e({kind:"call_function_call_failed",status:r,message:t,body:n})}static callFunctionRequiresProvisioning(){return new e({kind:"call_function_requires_provisioning"})}static callFunctionNotAvailable(){return new e({kind:"call_function_not_available"})}static callFunctionMissingExecutionJwt(){return new e({kind:"call_function_missing_execution_jwt"})}static aiUnsupportedService(r,t,n){return new e({kind:"ai_unsupported_service",alias:r,service:t,supported:n})}static aiModelIdRequired(r,t){return new e({kind:"ai_model_id_required",alias:r,operation:t})}static aiModelInstanceRequired(r){return new e({kind:"ai_model_instance_required",modelId:r})}static aiProviderNotConfigured(r,t){return new e({kind:"ai_provider_not_configured",alias:r,supported:t})}static aiProviderMisconfigured(r,t,n){return new e({kind:"ai_provider_misconfigured",alias:r,service:t,message:n})}static aiForeignModelRejected(){return new e({kind:"ai_foreign_model_rejected"})}static agentSessionsFailed(r){return new e({kind:"agent_sessions_failed",message:r})}};function ge(e){return e instanceof u}function L(e){switch(e.kind){case"unknown_alias":return`Unknown auth alias "${e.alias}". Available: ${e.available.join(", ")||"(none)"}`;case"input_validation_failed":return`Input validation failed for fields: ${e.fields.join(", ")}`;case"output_validation_failed":return`Output validation failed for fields: ${e.fields.join(", ")}`;case"config_load_failed":return`Config load failed: ${e.cause}`;case"broker_error":return e.code?`broker error: ${e.status} ${e.code}: ${e.message}`:`broker error: ${e.status} ${e.message}`;case"unsupported_body_type":return`unsupported body type: ${e.actualType}`;case"unsupported_scheme":return`unsupported scheme: ${e.scheme} (only https supported)`;case"missing_execution_credentials":return"missing execution credentials: at least one of internalJwt / helixExecutionJwt must be set before an authed broker/KV call";case"missing_tray_token":return"Not logged in. Run `helix login` to authenticate before making authed HTTP calls in dev.";case"db_call_failed":return`Database call failed: ${e.message}`;case"db_query_failed":return`Database query failed: ${e.message}`;case"db_invalid_parameters":return`Invalid database parameters: ${e.message}`;case"kv_key_invalid":return`Invalid KV key: ${e.message}`;case"kv_value_invalid":return e.message;case"kv_value_too_large":return e.message;case"kv_ttl_invalid":return e.message;case"kv_not_available":return"Key-value store is not available in this environment";case"kv_call_failed":return`KV platform error: ${e.status} ${e.message}`;case"kv_requires_provisioning":return"Key-value store requires a provisioned project (run helix project set)";case"files_path_invalid":return`Invalid file path: ${e.message}`;case"files_value_invalid":return e.message;case"files_value_too_large":return e.message;case"files_not_available":return"File storage is not available in this environment";case"files_call_failed":return`Files platform error: ${e.status} ${e.message}`;case"files_requires_provisioning":return"File storage requires a provisioned project (run helix project set)";case"call_function_path_invalid":return`Invalid function path: ${e.message}`;case"call_function_call_failed":return`Async function call failed: ${e.status} ${e.message}`;case"call_function_requires_provisioning":return"callFunctionAsync requires a provisioned project (run helix project set)";case"call_function_not_available":return"callFunctionAsync is not available: no running dev server was found";case"call_function_missing_execution_jwt":return"ctx.callFunctionAsync requires a helix project-execution JWT \u2014 a legacy internalJwt-only execution cannot call it";case"ai_unsupported_service":return`Authentication alias "${e.alias}" resolves to service "${e.service}", which ctx.ai does not support. Supported AI services: ${e.supported.join(", ")}`;case"ai_model_id_required":return`ctx.ai("${e.alias}").${e.operation} requires \`model\` as a string model id. To pass a model instance, use the top-level ctx.ai.${e.operation} instead.`;case"ai_model_instance_required":return`ctx.ai.* call functions require a model instance from ctx.ai(alias), got the string "${e.modelId}". Bare model ids would route outside the credentials broker and are not supported.`;case"ai_provider_not_configured":return`No AI provider configured for authentication alias "${e.alias}". Add \`aiProviders: { "${e.alias}": "<service>" }\` to helix.config.ts (supported services: ${e.supported.join(", ")}; bedrock needs the object form with region, openai-compatible the object form with baseUrl).`;case"ai_provider_misconfigured":return`aiProviders entry for authentication alias "${e.alias}" (service "${e.service}") is incomplete: ${e.message}`;case"ai_foreign_model_rejected":return"ctx.ai.* call functions require a model instance minted by ctx.ai(alias). A model built directly against a raw @ai-sdk/* provider carries its own transport and credentials, and would bypass the credentials broker, proxy policy, and metering.";case"agent_sessions_failed":return`Agent session store error: ${e.message}`}}import{z as g}from"zod";var A="x-helix-destination-url",U="x-helix-authentication-id",J="x-helix-deployment-id",_="x-execution-id",M="x-helix-broker-error",he="route_not_found",K=new Set([A,U,J,"authorization","x-tray-token","x-helix-project-execution-token","host","content-length","connection","transfer-encoding","te","upgrade","keep-alive","expect","proxy-authorization","proxy-connection","accept-encoding","x-request-id",_]);function V(e){let r=e.toLowerCase();return K.has(r)||r.startsWith("x-tray-internal-")}var w=g.object({error:g.object({code:g.string(),message:g.string(),issues:g.array(g.unknown()).optional()})});function ve(e,r){let t=`${m(e).hosts.api}/private/v1/helix/broker/http/raw`;return r==="dev"?`${t}/dev`:t}function xe(e){if(e.mode==="lambda"){let t=S(),n=P(),i=!!(t&&t.trim().length>0),o=!!(n&&n.trim().length>0);if(!i&&!o)throw u.missingExecutionCredentials();let a={};return i&&(a[R]=t),o&&(a[b]=n),{headers:a,deploymentId:e.deploymentId??null}}let r=I();if(!r)throw u.missingTrayToken();return{headers:{Authorization:`Bearer ${r}`},deploymentId:null}}function G(e){return typeof e=="string"||e instanceof ArrayBuffer||ArrayBuffer.isView(e)||typeof Blob<"u"&&e instanceof Blob||typeof FormData<"u"&&e instanceof FormData||e instanceof URLSearchParams||typeof ReadableStream<"u"&&e instanceof ReadableStream}function Ee(e){let r=new URL(e.url);if(r.protocol!=="https:")throw u.unsupportedScheme(r.protocol.replace(/:$/,""));if(e.query!==void 0)if(e.query instanceof URLSearchParams)for(let[l,d]of e.query.entries())r.searchParams.append(l,d);else for(let[l,d]of Object.entries(e.query))for(let $ of Array.isArray(d)?d:[d])r.searchParams.append(l,$);let t;e.headers===void 0?t=[]:e.headers instanceof Headers?t=Array.from(e.headers.entries()):Array.isArray(e.headers)?t=e.headers:t=Object.entries(e.headers);let n=t.filter(([l])=>!V(l)),i=e.body!==void 0&&e.body!==null,o,a,c=!1;return i&&(G(e.body)?(o=e.body,c=typeof ReadableStream<"u"&&e.body instanceof ReadableStream):(o=JSON.stringify(e.body),n.some(([d])=>d.toLowerCase()==="content-type")||(a="application/json"))),{authenticationId:e.authenticationId,method:e.method.toUpperCase(),destinationUrl:r.toString(),headers:n,body:o,isStreamBody:c,defaultContentType:a}}async function X(e,r){let t=await e.text(),n=t,i=t||r;try{n=JSON.parse(t);let o=w.safeParse(n);o.success&&(i=o.data.error.message)}catch{}return{status:e.status,code:r,message:i,body:n}}var Y=6e4;function z(e){return e.includes("json")}function W(e){return e.startsWith("text/")||e.includes("xml")||e.includes("urlencoded")||e.includes("javascript")||e.includes("ecmascript")}function Q(e,r){if(e.byteLength===0)return;let t=r.toLowerCase();if(z(t)){let n=new TextDecoder("utf-8").decode(e);try{return JSON.parse(n)}catch{return n}}return W(t)?new TextDecoder("utf-8").decode(e):e}function Z(e){let r={};for(let[t,n]of e.entries())r[t.toLowerCase()]=n;return r}async function we(e){let{request:r}=e,t=new Headers;for(let[l,d]of r.headers)t.append(l,d);r.defaultContentType&&!t.has("content-type")&&t.set("content-type",r.defaultContentType),t.set(A,r.destinationUrl),t.set(U,r.authenticationId);for(let[l,d]of Object.entries(e.credentialHeaders))t.set(l,d);e.executionId&&t.set(_,e.executionId);let n={method:r.method,headers:t,redirect:"manual",signal:AbortSignal.timeout(e.timeoutMs??Y)};r.body!==void 0&&(n.body=r.body,r.isStreamBody&&(n.duplex="half"));let i=await fetch(e.proxyUrl,n),o=i.headers.get(M);if(o!==null)return{kind:"brokerError",...await X(i,o)};let a=new Uint8Array(await i.arrayBuffer()),c=i.headers.get("content-type")??"";return{kind:"upstream",response:{status:i.status,headers:Z(i.headers),body:Q(a,c)}}}import{z as y}from"zod";var ee=3e4;function Te(e){let r=new URL(e);if(r.protocol!=="https:")throw u.unsupportedScheme(r.protocol.replace(/:$/,""))}function Ne(e,r){let t=`${m(e).hosts.api}/private/v1/helix/broker/s3/sign`;return r==="dev"?`${t}/dev`:t}var re=y.object({url:y.string(),method:y.string(),expiresAt:y.string()});async function De(e){let r=new Headers({"content-type":"application/json"});for(let[a,c]of Object.entries(e.credentialHeaders))r.set(a,c);e.executionId&&r.set(_,e.executionId);let t=await fetch(e.signUrl,{method:"POST",headers:r,body:JSON.stringify(e.body),redirect:"manual",signal:AbortSignal.timeout(e.timeoutMs??ee)}),n=await t.text(),i=n;try{i=JSON.parse(n)}catch{}if(t.ok){let a=re.safeParse(i);return a.success?{kind:"signed",result:a.data}:{kind:"brokerError",status:t.status,message:"malformed s3-sign response from credential broker",body:i}}let o=w.safeParse(i);return o.success?{kind:"brokerError",status:t.status,code:o.data.error.code,message:o.data.error.message,body:i}:{kind:"brokerError",status:t.status,message:n||`s3-sign request failed with status ${t.status}`,body:i}}export{b as a,R as b,te as c,ne as d,S as e,P as f,oe as g,H as h,se as i,m as j,ae as k,de as l,F as m,B as n,le as o,ue as p,ce as q,u as r,ge as s,A as t,U as u,J as v,_ as w,M as x,he as y,V as z,w as A,ve as B,xe as C,Ee as D,X as E,Y as F,we as G,Te as H,Ne as I,De as J};