@thaliq/sdk 1.0.0 → 1.1.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.
@@ -1,10 +1,19 @@
1
1
  import { Provider } from '../types/provider';
2
2
  import { ChatOptions, StreamOptions, AgentStream, RespondToActionOptions } from '../types/agent';
3
- import { ChatResponse } from '../types/responses';
3
+ import { ChatResponse, MessageFeedback } from '../types/responses';
4
4
  import { UserIdentity } from '../types/identity';
5
5
  import { ResolvedConfig, SDKEventMap } from '../types/config';
6
6
  import { TypedEventEmitter } from '../utils/event-emitter';
7
7
  import { ConversationManager } from './conversation-manager';
8
+ /** Options for submitting feedback */
9
+ export interface FeedbackOptions {
10
+ /** Conversation ID */
11
+ conversationId: string;
12
+ /** Message ID (from ResponseMetadata.messageId) */
13
+ messageId: string;
14
+ /** Feedback value */
15
+ feedback: MessageFeedback;
16
+ }
8
17
  export declare class AgentClient {
9
18
  private readonly config;
10
19
  private readonly provider;
@@ -38,6 +47,20 @@ export declare class AgentClient {
38
47
  * ```
39
48
  */
40
49
  respondToAction(options: RespondToActionOptions): AgentStream;
50
+ /**
51
+ * Submit feedback (thumbs up/down) for an assistant message.
52
+ *
53
+ * @example
54
+ * ```typescript
55
+ * const response = await thaliq.agent.chat('Hello!');
56
+ * await thaliq.agent.feedback({
57
+ * conversationId: response.conversationId,
58
+ * messageId: response.metadata.messageId!,
59
+ * feedback: 'positive',
60
+ * });
61
+ * ```
62
+ */
63
+ feedback(options: FeedbackOptions): Promise<void>;
41
64
  /** Build the ProviderRequest from message + options + identity */
42
65
  private buildRequest;
43
66
  /** Resolve all headers from config + identity */
package/index.d.ts CHANGED
@@ -34,8 +34,9 @@ export { ConversationManager } from './agent/conversation-manager';
34
34
  export type { ThaliqConfig, ResolvedConfig, RetryConfig, ResolvedRetryConfig, SDKEventMap, Logger, LogLevel, } from './types/config';
35
35
  export type { UserIdentity } from './types/identity';
36
36
  export type { AgentType, ChatOptions, StreamOptions, AgentStream, StreamStatus, RespondToActionOptions, } from './types/agent';
37
- export type { StreamEvent, MetaEvent, StatusEvent, ContentDeltaEvent, ToolStartEvent, ToolEndEvent, ActionEvent, ResponseCompletedEvent, ErrorEvent, KeepaliveEvent, } from './types/events';
38
- export type { ChatResponse, ResponseMetadata, Insight, InsightType, InsightSeverity, } from './types/responses';
37
+ export type { FeedbackOptions } from './agent/agent-client';
38
+ export type { StreamEvent, MetaEvent, StatusEvent, ContentDeltaEvent, ToolStartEvent, ToolEndEvent, ActionEvent, HandoffEvent, ResponseCompletedEvent, ErrorEvent, KeepaliveEvent, } from './types/events';
39
+ export type { ChatResponse, ResponseMetadata, MessageFeedback, Insight, InsightType, InsightSeverity, } from './types/responses';
39
40
  export type { ActionType, RejectBehavior, FieldType, ActionOption, ActionField, PendingAction, ActionResponse, } from './types/actions';
40
41
  export type { ConversationRef } from './types/conversations';
41
42
  export type { Provider, ProviderRequest, ResolvedHeaders, } from './types/provider';
package/package.json CHANGED
@@ -1,39 +1,39 @@
1
- {
2
- "name": "@thaliq/sdk",
3
- "version": "1.0.0",
4
- "description": "Headless, type-safe, provider-agnostic SDK for Thaliq AI agents",
5
- "type": "module",
6
- "main": "./thaliq-sdk.cjs.js",
7
- "module": "./thaliq-sdk.es.js",
8
- "types": "./index.d.ts",
9
- "exports": {
10
- ".": {
11
- "types": "./index.d.ts",
12
- "import": "./thaliq-sdk.es.js",
13
- "require": "./thaliq-sdk.cjs.js"
14
- }
15
- },
16
- "sideEffects": false,
17
- "license": "MIT",
18
- "author": "Thaliq <hello@thaliq.com> (https://thaliq.com)",
19
- "homepage": "https://docs.thaliq.com/sdk",
20
- "repository": {
21
- "type": "git",
22
- "url": "https://github.com/thaliq/sdk"
23
- },
24
- "engines": {
25
- "node": ">=18.0.0"
26
- },
27
- "keywords": [
28
- "thaliq",
29
- "ai",
30
- "agents",
31
- "sdk",
32
- "streaming",
33
- "sse",
34
- "llm",
35
- "ai-agents",
36
- "hitl",
37
- "human-in-the-loop"
38
- ]
39
- }
1
+ {
2
+ "name": "@thaliq/sdk",
3
+ "version": "1.1.0",
4
+ "description": "Headless, type-safe, provider-agnostic SDK for Thaliq AI agents",
5
+ "type": "module",
6
+ "main": "./thaliq-sdk.cjs",
7
+ "module": "./thaliq-sdk.es.js",
8
+ "types": "./index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./index.d.ts",
12
+ "import": "./thaliq-sdk.es.js",
13
+ "require": "./thaliq-sdk.cjs"
14
+ }
15
+ },
16
+ "sideEffects": false,
17
+ "license": "MIT",
18
+ "author": "Thaliq <hello@thaliq.com> (https://thaliq.com)",
19
+ "homepage": "https://docs.thaliq.com/sdk",
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "https://github.com/thaliq/sdk"
23
+ },
24
+ "engines": {
25
+ "node": ">=18.0.0"
26
+ },
27
+ "keywords": [
28
+ "thaliq",
29
+ "ai",
30
+ "agents",
31
+ "sdk",
32
+ "streaming",
33
+ "sse",
34
+ "llm",
35
+ "ai-agents",
36
+ "hitl",
37
+ "human-in-the-loop"
38
+ ]
39
+ }
package/thaliq-sdk.cjs ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class t extends Error{constructor(t,e,s){super(t),this.name="ThaliqError",this.code=e,this.status=s}}class e extends t{constructor(t,e=401){super(t,"AUTH_ERROR",e),this.name="AuthError"}}class s extends t{constructor(t,e=60){super(t,"RATE_LIMIT",429),this.name="RateLimitError",this.retryAfter=e}}class n extends t{constructor(t){super(t,"VALIDATION_ERROR",400),this.name="ValidationError"}}class r extends t{constructor(t){super(t,"SERVICE_ERROR",503),this.name="ServiceError"}}class o extends t{constructor(t){super(t,"STREAM_ERROR"),this.name="StreamError"}}class i extends t{constructor(t="Request timed out"){super(t,"TIMEOUT_ERROR"),this.name="TimeoutError"}}class a extends t{constructor(t="Connection failed"){super(t,"CONNECTION_ERROR"),this.name="ConnectionError"}}function c(o,i,a){switch(o){case 400:return new n(i);case 401:case 403:return new e(i,o);case 429:{const t=a?.get("retry-after");return new s(i,t?parseInt(t,10):60)}case 503:return new r(i);default:return new t(i,"UNKNOWN_ERROR",o)}}class h{constructor(t,e,s,n){this._conversationId=null,this._status="streaming",this._pendingAction=null,this._consumed=!1,this._source=t,this._abortController=e,this._onEvent=s,this._onComplete=n}get conversationId(){return this._conversationId}get status(){return this._status}get pendingAction(){return this._pendingAction}abort(){this._status="aborted",this._abortController.abort()}async*[Symbol.asyncIterator](){if(this._consumed)throw new o("AgentStream can only be consumed once");this._consumed=!0;try{for await(const t of this._source)"meta"===t.type&&(this._conversationId=t.conversationId),"response.completed"!==t.type||this._conversationId||(this._conversationId=t.conversationId),"action"===t.type&&(this._pendingAction=t.action,this._status="awaiting_action"),"handoff"===t.type&&(this._status="handoff"),"response.completed"===t.type&&(this._status="completed"),"error"===t.type&&(this._status="error"),this._onEvent&&this._onEvent(t),yield t;"streaming"===this._status&&(this._status=this._pendingAction?"awaiting_action":"completed")}finally{this._onComplete&&this._onComplete(this._conversationId,this._status)}}async finalResponse(){let t,e,s="",n="",r=[];for await(const a of this)switch(a.type){case"meta":n=a.conversationId;break;case"content.delta":s+=a.delta;break;case"action":e=a.action;break;case"response.completed":s=a.message,n=a.conversationId,r=a.insights,t=a.metadata;break;case"error":throw new o(a.message)}const i={message:s,conversationId:n,insights:r,metadata:t??{conversationId:n,model:"unknown",promptTokens:0,completionTokens:0,processingTimeMs:0,generatedAt:(new Date).toISOString()}};return e&&(i.action=e),i}async text(){let t="";for await(const e of this){if("content.delta"===e.type&&(t+=e.delta),"response.completed"===e.type)return e.message;if("error"===e.type)throw new o(e.message)}return t}}function l(o){return!(o instanceof t)||!(o instanceof e)&&(!(o instanceof n)&&(!(o instanceof s)&&(o instanceof r||(o instanceof a||(o instanceof i||!!(o.status&&o.status>=500))))))}function d(t,e,s){const n=e*Math.pow(2,t),r=Math.min(n,s),o=r*Math.random()*.5;return Math.floor(r+o)}function u(t){return new Promise(e=>setTimeout(e,t))}async function p(e,s){const{config:n,logger:r,onRetry:o,signal:i}=s;let a;for(let h=0;h<=n.maxRetries;h++)try{return await e()}catch(c){if(a=c,h>=n.maxRetries)break;if(!l(c))break;if(i?.aborted)break;const e=d(h,n.baseDelay,n.maxDelay);r.warn(`Retry ${h+1}/${n.maxRetries} after ${e}ms`,c instanceof Error?c.message:c),o&&c instanceof t&&o(h+1,c,e),await u(e)}throw a}class g{constructor(t,e,s,n,r){this.config=t,this.provider=e,this.getIdentity=s,this.emitter=n,this.conversationManager=r}async chat(t,e){const s=this.buildRequest(t,e),n=await p(()=>this.provider.chat(s),{config:this.config.retry,logger:this.config.logger,signal:e?.signal,onRetry:(t,e,s)=>{this.emitter.emit("retry",t,e,s)}});return n.conversationId&&this.conversationManager.setActive(n.conversationId),n}stream(e,s){const n=new AbortController,r=this.buildRequest(e,s,n.signal),o=this.provider.stream(r);this.emitter.emit("stream.start",s?.conversationId??null);return new h(o,n,e=>{if("meta"===e.type&&e.conversationId&&this.conversationManager.setActive(e.conversationId),"error"===e.type){const s=new t(e.message,"STREAM_ERROR");this.emitter.emit("error",s)}s?.onEvent&&s.onEvent(e)},t=>{this.emitter.emit("stream.end",t)})}respondToAction(t){return this.stream(t.originalMessage,{conversationId:t.conversationId,agentType:t.agentType,actionResponse:t.actionResponse,onEvent:t.onEvent,signal:t.signal})}async feedback(e){const s=this.getIdentity(),n=this.resolveHeaders(s),r=await fetch(`${this.config.baseUrl}/api/agent/feedback`,{method:"POST",headers:{"content-type":"application/json","x-api-key":n["x-api-key"],"x-integration-type":n["x-integration-type"],...n["x-user-id"]?{"x-user-id":n["x-user-id"]}:{},...n.authorization?{authorization:n.authorization}:{}},body:JSON.stringify({conversationId:e.conversationId,messageId:e.messageId,feedback:e.feedback})});if(!r.ok){const e=await r.text().catch(()=>`HTTP ${r.status}`);throw new t(e,"UNKNOWN_ERROR")}}buildRequest(t,e,s){const n=this.getIdentity(),r=e?.signal??s;return{message:t,conversationId:e?.conversationId,agentType:e?.agentType,actionResponse:e?.actionResponse,headers:this.resolveHeaders(n),signal:r,timeout:this.config.timeout}}resolveHeaders(t){const e={"x-api-key":this.config.apiKey,"x-integration-type":this.config.integrationType};t&&(t.userId&&(e["x-user-id"]=t.userId),t.participantId&&(e["x-participant-id"]=t.participantId),t.token&&(e.authorization=`Bearer ${t.token}`),t.mcpTokens&&Object.keys(t.mcpTokens).length>0&&(e["x-mcp-tokens"]=JSON.stringify(t.mcpTokens)));for(const[s,n]of Object.entries(this.config.defaultHeaders))e[s]=n;return e}}class m{constructor(){this._active=null,this._history=[]}create(){const t={id:"undefined"!=typeof crypto&&"function"==typeof crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,t=>{const e=16*Math.random()|0;return("x"===t?e:3&e|8).toString(16)}),createdAt:new Date};return this._history.push(t),t}get active(){return this._active}get history(){return this._history}setActive(t){const e=this._history.find(e=>e.id===t);if(e)this._active=e;else{const e={id:t,createdAt:new Date};this._history.push(e),this._active=e}}clear(){this._active=null,this._history.length=0}}class f{constructor(t){this.baseUrl=t.baseUrl.replace(/\/+$/,""),this.defaultTimeout=t.timeout,this.logger=t.logger}async json(t){const e=await this.rawFetch(t);if(!e.ok){const t=await e.text().catch(()=>"Unknown error");let s;try{const e=JSON.parse(t);s=e.message??e.error??t}catch{s=t}throw c(e.status,s,e.headers)}return e.json()}async stream(t){const e=await this.rawFetch(t);if(!e.ok){const t=await e.text().catch(()=>"Unknown error");let s;try{const e=JSON.parse(t);s=e.message??e.error??t}catch{s=t}throw c(e.status,s,e.headers)}return e}async rawFetch(t){const e=`${this.baseUrl}${t.path}`,s=t.timeout??this.defaultTimeout,n=new AbortController;let r;t.signal&&t.signal.addEventListener("abort",()=>n.abort(t.signal?.reason),{once:!0}),r=setTimeout(()=>{n.abort(new i(`Request timed out after ${s}ms`))},s);const o={"content-type":"application/json"};for(const[i,a]of Object.entries(t.headers))void 0!==a&&(o[i]=a);this.logger.debug(`${t.method} ${e}`);try{return await fetch(e,{method:t.method,headers:o,body:t.body?JSON.stringify(t.body):void 0,signal:n.signal})}catch(c){if(c instanceof i)throw c;if(c instanceof DOMException&&"AbortError"===c.name){if(n.signal.reason instanceof i)throw n.signal.reason;throw c}throw new a(c instanceof Error?c.message:"Connection failed")}finally{void 0!==r&&clearTimeout(r)}}}function y(t){let e="",s="",n="";const r=t.split("\n");for(const o of r)o.startsWith("event:")?e=o.slice(6).trim():o.startsWith("data:")?s=o.slice(5).trim():o.startsWith("id:")&&(n=o.slice(3).trim());return e||s?{event:e,data:s,id:n}:null}function x(t){const e=t.event;try{const s=t.data?JSON.parse(t.data):{};switch(e){case"meta":return{type:"meta",conversationId:s.conversationId};case"status":return{type:"status",text:s.text};case"content.delta":return{type:"content.delta",delta:s.delta};case"tool.start":return{type:"tool.start",tool:s.tool};case"tool.end":return{type:"tool.end",tool:s.tool,success:s.success};case"action":return{type:"action",action:s};case"handoff":return{type:"handoff",message:s.message,agentName:s.agentName,reason:s.reason};case"response.completed":return{type:"response.completed",message:s.message,conversationId:s.conversationId,insights:s.insights??[],metadata:s.metadata};case"error":return{type:"error",message:s.message};case"keepalive":return{type:"keepalive",ts:s.ts};default:return null}}catch{return null}}class v{constructor(t){this.name="thaliq-native",this.logger=t.logger,this.http=new f({baseUrl:t.baseUrl,timeout:t.timeout,logger:t.logger})}async chat(t){const e={message:t.message};return t.conversationId&&(e.conversationId=t.conversationId),t.agentType&&(e.agentType=t.agentType),t.actionResponse&&(e.actionResponse=t.actionResponse),this.http.json({method:"POST",path:"/api/agent/chat",headers:t.headers,body:e,signal:t.signal,timeout:t.timeout})}async*stream(t){const e=new URLSearchParams;e.set("q",t.message),t.conversationId&&e.set("conversationId",t.conversationId),t.agentType&&e.set("agentType",t.agentType),t.actionResponse&&e.set("actionResponse",JSON.stringify(t.actionResponse));const s=await this.http.stream({method:"GET",path:`/api/agent/stream?${e.toString()}`,headers:{...t.headers,accept:"text/event-stream"},signal:t.signal,timeout:t.timeout});if(!s.body)throw new o("Response body is null — streaming not supported");this.logger.debug("SSE stream connected"),yield*async function*(t){const e=t.getReader(),s=new TextDecoder;let n="";try{for(;;){const{done:t,value:r}=await e.read();if(t)break;n+=s.decode(r,{stream:!0});const o=n.split("\n\n");n=o.pop()??"";for(const e of o){const t=y(e);if(!t)continue;const s=x(t);s&&(yield s)}}if(n.trim()){const t=y(n);if(t){const e=x(t);e&&(yield e)}}}finally{e.releaseLock()}}(s.body)}}class w{constructor(){this._listeners=new Map}on(t,e){return this._listeners.has(t)||this._listeners.set(t,new Set),this._listeners.get(t).add(e),this}once(t,e){return e._once=!0,this.on(t,e)}off(t,e){const s=this._listeners.get(t);return s&&(s.delete(e),0===s.size&&this._listeners.delete(t)),this}emit(t,...e){const s=this._listeners.get(t);if(s){for(const t of s)t(...e),t._once&&s.delete(t);0===s.size&&this._listeners.delete(t)}}removeAllListeners(t){return t?this._listeners.delete(t):this._listeners.clear(),this}listenerCount(t){return this._listeners.get(t)?.size??0}}const _={debug:0,info:1,warn:2,error:3,silent:4};const R="https://api.thaliq.com";exports.ActionResponseBuilder=class{static accept(t){return{instructionId:t,accepted:!0}}static reject(t){return{instructionId:t,accepted:!1}}static select(t,e){return{instructionId:t,accepted:!0,selectedValue:e}}static submitForm(t,e){return{instructionId:t,accepted:!0,formValues:e}}},exports.AuthError=e,exports.ConnectionError=a,exports.ConversationManager=m,exports.RateLimitError=s,exports.ServiceError=r,exports.StreamError=o,exports.Thaliq=class{constructor(t){this.emitter=new w,this.identity=null,this.config=function(t){if(!t.apiKey)throw new n("apiKey is required");const e=t.logLevel??"warn",s=t.logger??function(t){const e=_[t];return{debug(t,...s){e<=_.debug&&console.debug(`[thaliq] ${t}`,...s)},info(t,...s){e<=_.info&&console.info(`[thaliq] ${t}`,...s)},warn(t,...s){e<=_.warn&&console.warn(`[thaliq] ${t}`,...s)},error(t,...s){e<=_.error&&console.error(`[thaliq] ${t}`,...s)}}}(e),r=t.maxRetries??t.retry?.maxRetries??2;return{apiKey:t.apiKey,baseUrl:(t.baseUrl??R).replace(/\/+$/,""),integrationType:t.integrationType??"sdk",timeout:t.timeout??3e4,maxRetries:r,retry:{maxRetries:r,baseDelay:t.retry?.baseDelay??500,maxDelay:t.retry?.maxDelay??1e4},logger:s,logLevel:e,defaultHeaders:t.defaultHeaders??{}}}(t),this.provider=t.provider??new v({baseUrl:this.config.baseUrl,timeout:this.config.timeout,logger:this.config.logger}),this.conversations=new m,this.agent=new g(this.config,this.provider,()=>this.identity,this.emitter,this.conversations)}on(t,e){return this.emitter.on(t,e),this}once(t,e){return this.emitter.once(t,e),this}off(t,e){return this.emitter.off(t,e),this}identify(t){if(!t.userId)throw new n("userId is required for identify()");this.identity=t,this.config.logger.info(`User identified: ${t.userId}`),this.emitter.emit("identify",t.userId)}reset(){this.identity=null,this.conversations.clear(),this.config.logger.info("SDK state reset"),this.emitter.emit("reset")}},exports.ThaliqError=t,exports.ThaliqNativeProvider=v,exports.TimeoutError=i,exports.TypedEventEmitter=w,exports.ValidationError=n,exports.calculateBackoff=d,exports.isRetryableError=l,exports.withRetry=p;
2
+ //# sourceMappingURL=thaliq-sdk.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thaliq-sdk.cjs","sources":["../../../libs/sdk/src/types/errors.ts","../../../libs/sdk/src/agent/agent-stream.ts","../../../libs/sdk/src/utils/retry.ts","../../../libs/sdk/src/agent/agent-client.ts","../../../libs/sdk/src/agent/conversation-manager.ts","../../../libs/sdk/src/utils/uuid.ts","../../../libs/sdk/src/providers/thaliq-native/http-client.ts","../../../libs/sdk/src/providers/thaliq-native/sse-parser.ts","../../../libs/sdk/src/providers/thaliq-native/thaliq-native.provider.ts","../../../libs/sdk/src/utils/event-emitter.ts","../../../libs/sdk/src/utils/logger.ts","../../../libs/sdk/src/client.ts","../../../libs/sdk/src/utils/action-response-builder.ts"],"sourcesContent":["/**\n * @thaliq/sdk - Error Types\n * @module types/errors\n */\n\n/**\n * SDK error codes used in `ThaliqError.code`.\n * Use these to programmatically distinguish error types.\n */\nexport type ErrorCode =\n | 'AUTH_ERROR'\n | 'RATE_LIMIT'\n | 'VALIDATION_ERROR'\n | 'SERVICE_ERROR'\n | 'STREAM_ERROR'\n | 'TIMEOUT_ERROR'\n | 'CONNECTION_ERROR'\n | 'UNKNOWN_ERROR';\n\n/** Base error class for all SDK errors */\nexport class ThaliqError extends Error {\n readonly code: ErrorCode;\n readonly status?: number;\n\n constructor(message: string, code: ErrorCode, status?: number) {\n super(message);\n this.name = 'ThaliqError';\n this.code = code;\n this.status = status;\n }\n}\n\n/** Authentication or authorization error (401/403) */\nexport class AuthError extends ThaliqError {\n constructor(message: string, status: number = 401) {\n super(message, 'AUTH_ERROR', status);\n this.name = 'AuthError';\n }\n}\n\n/** Rate limit exceeded (429) */\nexport class RateLimitError extends ThaliqError {\n readonly retryAfter: number;\n\n constructor(message: string, retryAfter: number = 60) {\n super(message, 'RATE_LIMIT', 429);\n this.name = 'RateLimitError';\n this.retryAfter = retryAfter;\n }\n}\n\n/** Request validation error (400) */\nexport class ValidationError extends ThaliqError {\n constructor(message: string) {\n super(message, 'VALIDATION_ERROR', 400);\n this.name = 'ValidationError';\n }\n}\n\n/** Service unavailable (503) */\nexport class ServiceError extends ThaliqError {\n constructor(message: string) {\n super(message, 'SERVICE_ERROR', 503);\n this.name = 'ServiceError';\n }\n}\n\n/** Error during SSE streaming */\nexport class StreamError extends ThaliqError {\n constructor(message: string) {\n super(message, 'STREAM_ERROR');\n this.name = 'StreamError';\n }\n}\n\n/** Request timeout */\nexport class TimeoutError extends ThaliqError {\n constructor(message: string = 'Request timed out') {\n super(message, 'TIMEOUT_ERROR');\n this.name = 'TimeoutError';\n }\n}\n\n/** Network/connection error */\nexport class ConnectionError extends ThaliqError {\n constructor(message: string = 'Connection failed') {\n super(message, 'CONNECTION_ERROR');\n this.name = 'ConnectionError';\n }\n}\n\n/**\n * Maps an HTTP status code to the appropriate ThaliqError subclass.\n * Used internally by the HTTP client; also useful for custom providers.\n */\nexport function mapHttpError(status: number, message: string, headers?: Headers): ThaliqError {\n switch (status) {\n case 400:\n return new ValidationError(message);\n case 401:\n case 403:\n return new AuthError(message, status);\n case 429: {\n const retryAfter = headers?.get('retry-after');\n return new RateLimitError(message, retryAfter ? parseInt(retryAfter, 10) : 60);\n }\n case 503:\n return new ServiceError(message);\n default:\n return new ThaliqError(message, 'UNKNOWN_ERROR', status);\n }\n}\n","/**\n * AgentStream — AsyncIterable wrapper over SSE events.\n *\n * Provides convenient access to the conversation ID, abort,\n * and methods to accumulate the final response or text.\n */\n\nimport type { AgentStream as IAgentStream, StreamStatus } from '../types/agent';\nimport type { StreamEvent } from '../types/events';\nimport type { ChatResponse } from '../types/responses';\nimport type { Insight, ResponseMetadata } from '../types/responses';\nimport type { PendingAction } from '../types/actions';\nimport { StreamError } from '../types/errors';\n\nexport class AgentStreamImpl implements IAgentStream {\n private _conversationId: string | null = null;\n private _status: StreamStatus = 'streaming';\n private _pendingAction: PendingAction | null = null;\n private readonly _source: AsyncIterable<StreamEvent>;\n private readonly _abortController: AbortController;\n private readonly _onEvent?: (event: StreamEvent) => void;\n private readonly _onComplete?: (conversationId: string | null, status: StreamStatus) => void;\n private _consumed = false;\n\n constructor(\n source: AsyncIterable<StreamEvent>,\n abortController: AbortController,\n onEvent?: (event: StreamEvent) => void,\n onComplete?: (conversationId: string | null, status: StreamStatus) => void,\n ) {\n this._source = source;\n this._abortController = abortController;\n this._onEvent = onEvent;\n this._onComplete = onComplete;\n }\n\n get conversationId(): string | null {\n return this._conversationId;\n }\n\n get status(): StreamStatus {\n return this._status;\n }\n\n get pendingAction(): PendingAction | null {\n return this._pendingAction;\n }\n\n abort(): void {\n this._status = 'aborted';\n this._abortController.abort();\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<StreamEvent> {\n if (this._consumed) {\n throw new StreamError('AgentStream can only be consumed once');\n }\n this._consumed = true;\n\n try {\n for await (const event of this._source) {\n // Track conversation ID from meta event\n if (event.type === 'meta') {\n this._conversationId = event.conversationId;\n }\n\n // Also track from response.completed\n if (event.type === 'response.completed' && !this._conversationId) {\n this._conversationId = event.conversationId;\n }\n\n // Track action events — stream is awaiting user response\n if (event.type === 'action') {\n this._pendingAction = event.action;\n this._status = 'awaiting_action';\n }\n\n // Track handoff — conversation escalated to human agent\n if (event.type === 'handoff') {\n this._status = 'handoff';\n }\n\n // Track completion\n if (event.type === 'response.completed') {\n this._status = 'completed';\n }\n\n // Track errors\n if (event.type === 'error') {\n this._status = 'error';\n }\n\n // Fire optional callback\n if (this._onEvent) {\n this._onEvent(event);\n }\n\n yield event;\n }\n\n // If stream ended naturally without explicit status, mark completed\n if (this._status === 'streaming') {\n this._status = this._pendingAction ? 'awaiting_action' : 'completed';\n }\n } finally {\n // Notify completion regardless of how stream ended\n if (this._onComplete) {\n this._onComplete(this._conversationId, this._status);\n }\n }\n }\n\n async finalResponse(): Promise<ChatResponse> {\n let message = '';\n let conversationId = '';\n let insights: Insight[] = [];\n let metadata: ResponseMetadata | undefined;\n let action: PendingAction | undefined;\n\n for await (const event of this) {\n switch (event.type) {\n case 'meta':\n conversationId = event.conversationId;\n break;\n case 'content.delta':\n message += event.delta;\n break;\n case 'action':\n action = event.action;\n break;\n case 'response.completed':\n message = event.message;\n conversationId = event.conversationId;\n insights = event.insights;\n metadata = event.metadata;\n break;\n case 'error':\n throw new StreamError(event.message);\n }\n }\n\n const response: ChatResponse = {\n message,\n conversationId,\n insights,\n metadata: metadata ?? {\n conversationId,\n model: 'unknown',\n promptTokens: 0,\n completionTokens: 0,\n processingTimeMs: 0,\n generatedAt: new Date().toISOString(),\n },\n };\n\n if (action) {\n response.action = action;\n }\n\n return response;\n }\n\n async text(): Promise<string> {\n let accumulated = '';\n\n for await (const event of this) {\n if (event.type === 'content.delta') {\n accumulated += event.delta;\n }\n if (event.type === 'response.completed') {\n return event.message;\n }\n if (event.type === 'error') {\n throw new StreamError(event.message);\n }\n }\n\n return accumulated;\n }\n}\n","/**\n * Retry logic with exponential backoff and jitter.\n *\n * Retries on server errors (500/502/503/504) and network errors.\n * Never retries on client errors (400/401/403/429).\n */\n\nimport type { ResolvedRetryConfig, Logger } from '../types/config';\nimport {\n ThaliqError,\n RateLimitError,\n AuthError,\n ValidationError,\n TimeoutError,\n ConnectionError,\n ServiceError,\n} from '../types/errors';\n\n/**\n * Check if an error is retryable.\n * Returns `true` for server errors (5xx), timeouts, and connection errors.\n * Returns `false` for auth errors (401/403), validation (400), and rate limits (429).\n */\nexport function isRetryableError(error: unknown): boolean {\n if (!(error instanceof ThaliqError)) {\n // Unknown errors (network failures, etc.) are retryable\n return true;\n }\n\n // Never retry client errors\n if (error instanceof AuthError) return false;\n if (error instanceof ValidationError) return false;\n if (error instanceof RateLimitError) return false;\n\n // Retry server errors and connection issues\n if (error instanceof ServiceError) return true;\n if (error instanceof ConnectionError) return true;\n if (error instanceof TimeoutError) return true;\n\n // Retry 5xx status codes\n if (error.status && error.status >= 500) return true;\n\n return false;\n}\n\n/**\n * Calculate the retry delay with exponential backoff and jitter.\n * Formula: `min(baseDelay * 2^attempt, maxDelay) + random(0..50%)`.\n */\nexport function calculateBackoff(\n attempt: number,\n baseDelay: number,\n maxDelay: number,\n): number {\n // Exponential: baseDelay * 2^attempt\n const exponential = baseDelay * Math.pow(2, attempt);\n // Clamp to maxDelay\n const clamped = Math.min(exponential, maxDelay);\n // Add jitter: random 0-50% of the delay\n const jitter = clamped * Math.random() * 0.5;\n return Math.floor(clamped + jitter);\n}\n\n/** Sleep for a given number of milliseconds */\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/** Options for the retry wrapper */\nexport interface RetryOptions {\n config: ResolvedRetryConfig;\n logger: Logger;\n /** Called before each retry attempt */\n onRetry?: (attempt: number, error: ThaliqError, delayMs: number) => void;\n /** AbortSignal to cancel retries */\n signal?: AbortSignal;\n}\n\n/**\n * Execute an async function with automatic retry on retryable errors.\n * Uses exponential backoff with jitter between attempts.\n *\n * @param fn - The async function to execute (and potentially retry)\n * @param options - Retry configuration, logger, and optional callbacks\n * @returns The result of `fn()` on success\n * @throws The last error after all retries are exhausted\n */\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n options: RetryOptions,\n): Promise<T> {\n const { config, logger, onRetry, signal } = options;\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= config.maxRetries; attempt++) {\n try {\n return await fn();\n } catch (error: unknown) {\n lastError = error;\n\n // Don't retry if we've exhausted attempts\n if (attempt >= config.maxRetries) break;\n\n // Don't retry non-retryable errors\n if (!isRetryableError(error)) break;\n\n // Don't retry if aborted\n if (signal?.aborted) break;\n\n const delayMs = calculateBackoff(attempt, config.baseDelay, config.maxDelay);\n\n logger.warn(\n `Retry ${attempt + 1}/${config.maxRetries} after ${delayMs}ms`,\n error instanceof Error ? error.message : error,\n );\n\n if (onRetry && error instanceof ThaliqError) {\n onRetry(attempt + 1, error, delayMs);\n }\n\n await sleep(delayMs);\n }\n }\n\n throw lastError;\n}\n","/**\n * AgentClient — main interface for interacting with agents.\n *\n * Accessed via `thaliq.agent.chat()` and `thaliq.agent.stream()`.\n * Includes automatic retry with exponential backoff for chat requests.\n */\n\nimport type { Provider, ProviderRequest, ResolvedHeaders } from '../types/provider';\nimport type { ChatOptions, StreamOptions, AgentStream, RespondToActionOptions, StreamStatus } from '../types/agent';\nimport type { ChatResponse, MessageFeedback } from '../types/responses';\nimport type { UserIdentity } from '../types/identity';\nimport type { ResolvedConfig, SDKEventMap } from '../types/config';\nimport type { TypedEventEmitter } from '../utils/event-emitter';\nimport type { ConversationManager } from './conversation-manager';\nimport { RateLimitError, ThaliqError } from '../types/errors';\nimport { AgentStreamImpl } from './agent-stream';\nimport { withRetry } from '../utils/retry';\n\n/** Options for submitting feedback */\nexport interface FeedbackOptions {\n /** Conversation ID */\n conversationId: string;\n /** Message ID (from ResponseMetadata.messageId) */\n messageId: string;\n /** Feedback value */\n feedback: MessageFeedback;\n}\n\nexport class AgentClient {\n private readonly config: ResolvedConfig;\n private readonly provider: Provider;\n private readonly getIdentity: () => UserIdentity | null;\n private readonly emitter: TypedEventEmitter<SDKEventMap>;\n private readonly conversationManager: ConversationManager;\n\n constructor(\n config: ResolvedConfig,\n provider: Provider,\n getIdentity: () => UserIdentity | null,\n emitter: TypedEventEmitter<SDKEventMap>,\n conversationManager: ConversationManager,\n ) {\n this.config = config;\n this.provider = provider;\n this.getIdentity = getIdentity;\n this.emitter = emitter;\n this.conversationManager = conversationManager;\n }\n\n /** Send a message and wait for the complete response (with automatic retry) */\n async chat(message: string, options?: ChatOptions): Promise<ChatResponse> {\n const request = this.buildRequest(message, options);\n\n const response = await withRetry(\n () => this.provider.chat(request),\n {\n config: this.config.retry,\n logger: this.config.logger,\n signal: options?.signal,\n onRetry: (attempt, error, delayMs) => {\n this.emitter.emit('retry', attempt, error, delayMs);\n },\n },\n );\n\n // Auto-track conversation\n if (response.conversationId) {\n this.conversationManager.setActive(response.conversationId);\n }\n\n return response;\n }\n\n /** Send a message with streaming — returns an AgentStream */\n stream(message: string, options?: StreamOptions): AgentStream {\n const abortController = new AbortController();\n const request = this.buildRequest(message, options, abortController.signal);\n\n // The provider returns an AsyncIterable<StreamEvent>\n const source = this.provider.stream(request);\n\n // Emit stream.start\n this.emitter.emit('stream.start', options?.conversationId ?? null);\n\n const stream = new AgentStreamImpl(\n source,\n abortController,\n (event) => {\n // Auto-track conversation from meta event\n if (event.type === 'meta' && event.conversationId) {\n this.conversationManager.setActive(event.conversationId);\n }\n\n // Emit error/rateLimit events\n if (event.type === 'error') {\n const err = new ThaliqError(event.message, 'STREAM_ERROR');\n this.emitter.emit('error', err);\n }\n\n // Forward to user callback\n if (options?.onEvent) {\n options.onEvent(event);\n }\n },\n // onComplete callback for stream.end event\n (conversationId) => {\n this.emitter.emit('stream.end', conversationId);\n },\n );\n\n return stream;\n }\n\n /**\n * Respond to a pending HITL action and resume the conversation.\n *\n * This is a convenience method that creates a new stream with the\n * action response, continuing the conversation where it left off.\n *\n * @example\n * ```typescript\n * const stream = thaliq.agent.stream('Transfer $500');\n * for await (const event of stream) { ... }\n *\n * if (stream.pendingAction) {\n * const resumed = thaliq.agent.respondToAction({\n * conversationId: stream.conversationId!,\n * originalMessage: 'Transfer $500',\n * actionResponse: ActionResponseBuilder.accept(stream.pendingAction.instructionId),\n * });\n * for await (const event of resumed) { ... }\n * }\n * ```\n */\n respondToAction(options: RespondToActionOptions): AgentStream {\n return this.stream(options.originalMessage, {\n conversationId: options.conversationId,\n agentType: options.agentType,\n actionResponse: options.actionResponse,\n onEvent: options.onEvent,\n signal: options.signal,\n });\n }\n\n /**\n * Submit feedback (thumbs up/down) for an assistant message.\n *\n * @example\n * ```typescript\n * const response = await thaliq.agent.chat('Hello!');\n * await thaliq.agent.feedback({\n * conversationId: response.conversationId,\n * messageId: response.metadata.messageId!,\n * feedback: 'positive',\n * });\n * ```\n */\n async feedback(options: FeedbackOptions): Promise<void> {\n const identity = this.getIdentity();\n const headers = this.resolveHeaders(identity);\n\n const response = await fetch(`${this.config.baseUrl}/api/agent/feedback`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n 'x-api-key': headers['x-api-key'],\n 'x-integration-type': headers['x-integration-type'],\n ...(headers['x-user-id'] ? { 'x-user-id': headers['x-user-id'] } : {}),\n ...(headers['authorization'] ? { authorization: headers['authorization'] } : {}),\n },\n body: JSON.stringify({\n conversationId: options.conversationId,\n messageId: options.messageId,\n feedback: options.feedback,\n }),\n });\n\n if (!response.ok) {\n const text = await response.text().catch(() => `HTTP ${response.status}`);\n throw new ThaliqError(text, 'UNKNOWN_ERROR');\n }\n }\n\n /** Build the ProviderRequest from message + options + identity */\n private buildRequest(\n message: string,\n options?: ChatOptions,\n abortSignal?: AbortSignal,\n ): ProviderRequest {\n const identity = this.getIdentity();\n const signal = options?.signal ?? abortSignal;\n\n return {\n message,\n conversationId: options?.conversationId,\n agentType: options?.agentType,\n actionResponse: options?.actionResponse,\n headers: this.resolveHeaders(identity),\n signal,\n timeout: this.config.timeout,\n };\n }\n\n /** Resolve all headers from config + identity */\n private resolveHeaders(identity: UserIdentity | null): ResolvedHeaders {\n const headers: ResolvedHeaders = {\n 'x-api-key': this.config.apiKey,\n 'x-integration-type': this.config.integrationType,\n };\n\n // Identity headers\n if (identity) {\n if (identity.userId) {\n headers['x-user-id'] = identity.userId;\n }\n if (identity.participantId) {\n headers['x-participant-id'] = identity.participantId;\n }\n if (identity.token) {\n headers['authorization'] = `Bearer ${identity.token}`;\n }\n if (identity.mcpTokens && Object.keys(identity.mcpTokens).length > 0) {\n headers['x-mcp-tokens'] = JSON.stringify(identity.mcpTokens);\n }\n }\n\n // Custom default headers\n for (const [key, value] of Object.entries(this.config.defaultHeaders)) {\n headers[key] = value;\n }\n\n return headers;\n }\n}\n","/**\n * ConversationManager — tracks active conversations and auto-assigns IDs.\n *\n * @example\n * ```typescript\n * const conv = thaliq.conversations.create();\n * console.log(conv.id); // UUID\n *\n * // After streaming, the active conversation is auto-tracked\n * const stream = thaliq.agent.stream('Hello', { conversationId: conv.id });\n * for await (const event of stream) { ... }\n *\n * console.log(thaliq.conversations.active); // conv.id\n * ```\n */\n\nimport type { ConversationRef } from '../types/conversations';\nimport { uuid } from '../utils/uuid';\n\nexport class ConversationManager {\n private _active: ConversationRef | null = null;\n private readonly _history: ConversationRef[] = [];\n\n /** Create a new conversation reference */\n create(): ConversationRef {\n const ref: ConversationRef = {\n id: uuid(),\n createdAt: new Date(),\n };\n this._history.push(ref);\n return ref;\n }\n\n /** Get the most recently active conversation */\n get active(): ConversationRef | null {\n return this._active;\n }\n\n /** Get all known conversation references (in-memory only) */\n get history(): readonly ConversationRef[] {\n return this._history;\n }\n\n /**\n * Set the active conversation by ID (called internally after stream completes).\n * If the ID matches an existing ref, that ref becomes active.\n * Otherwise a new ref is created.\n */\n setActive(conversationId: string): void {\n const existing = this._history.find(c => c.id === conversationId);\n if (existing) {\n this._active = existing;\n } else {\n const ref: ConversationRef = {\n id: conversationId,\n createdAt: new Date(),\n };\n this._history.push(ref);\n this._active = ref;\n }\n }\n\n /** Clear all state */\n clear(): void {\n this._active = null;\n this._history.length = 0;\n }\n}\n","/**\n * Generate a UUID v4 using crypto.randomUUID when available,\n * falling back to a manual implementation.\n */\nexport function uuid(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n\n // Fallback for environments without crypto.randomUUID\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n","/**\n * HTTP client wrapper for the Thaliq Native Provider.\n *\n * Handles fetch with timeout via AbortController,\n * error mapping from HTTP status codes, and response parsing.\n */\n\nimport {\n mapHttpError,\n TimeoutError,\n ConnectionError,\n} from '../../types/errors';\nimport type { Logger } from '../../types/config';\n\nexport interface HttpClientConfig {\n baseUrl: string;\n timeout: number;\n logger: Logger;\n}\n\nexport interface HttpRequestOptions {\n method: 'GET' | 'POST';\n path: string;\n headers: Record<string, string | undefined>;\n body?: unknown;\n signal?: AbortSignal;\n timeout: number;\n}\n\nexport class HttpClient {\n private readonly baseUrl: string;\n private readonly defaultTimeout: number;\n private readonly logger: Logger;\n\n constructor(config: HttpClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/+$/, '');\n this.defaultTimeout = config.timeout;\n this.logger = config.logger;\n }\n\n /** Execute a JSON request and return the parsed response */\n async json<T>(options: HttpRequestOptions): Promise<T> {\n const response = await this.rawFetch(options);\n\n if (!response.ok) {\n const body = await response.text().catch(() => 'Unknown error');\n let message: string;\n try {\n const parsed = JSON.parse(body);\n message = parsed.message ?? parsed.error ?? body;\n } catch {\n message = body;\n }\n throw mapHttpError(response.status, message, response.headers);\n }\n\n return response.json() as Promise<T>;\n }\n\n /** Execute a request and return the raw Response (for SSE streaming) */\n async stream(options: HttpRequestOptions): Promise<Response> {\n const response = await this.rawFetch(options);\n\n if (!response.ok) {\n const body = await response.text().catch(() => 'Unknown error');\n let message: string;\n try {\n const parsed = JSON.parse(body);\n message = parsed.message ?? parsed.error ?? body;\n } catch {\n message = body;\n }\n throw mapHttpError(response.status, message, response.headers);\n }\n\n return response;\n }\n\n /** Low-level fetch with timeout and error wrapping */\n private async rawFetch(options: HttpRequestOptions): Promise<Response> {\n const url = `${this.baseUrl}${options.path}`;\n const timeout = options.timeout ?? this.defaultTimeout;\n\n // Create a timeout controller that will abort if no external signal is provided\n const timeoutController = new AbortController();\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n // If the caller provided an AbortSignal, listen to it\n if (options.signal) {\n options.signal.addEventListener('abort', () => timeoutController.abort(options.signal?.reason), {\n once: true,\n });\n }\n\n timeoutId = setTimeout(() => {\n timeoutController.abort(new TimeoutError(`Request timed out after ${timeout}ms`));\n }, timeout);\n\n // Clean up headers: remove undefined values\n const headers: Record<string, string> = { 'content-type': 'application/json' };\n for (const [key, value] of Object.entries(options.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n\n this.logger.debug(`${options.method} ${url}`);\n\n try {\n const response = await fetch(url, {\n method: options.method,\n headers,\n body: options.body ? JSON.stringify(options.body) : undefined,\n signal: timeoutController.signal,\n });\n\n return response;\n } catch (error: unknown) {\n if (error instanceof TimeoutError) throw error;\n if (error instanceof DOMException && error.name === 'AbortError') {\n // Check if it was a timeout or user abort\n if (timeoutController.signal.reason instanceof TimeoutError) {\n throw timeoutController.signal.reason;\n }\n throw error;\n }\n throw new ConnectionError(\n error instanceof Error ? error.message : 'Connection failed',\n );\n } finally {\n if (timeoutId !== undefined) clearTimeout(timeoutId);\n }\n }\n}\n","/**\n * SSE (Server-Sent Events) parser.\n *\n * Converts a ReadableStream<Uint8Array> into an AsyncIterable of parsed SSE events.\n * Follows the SSE spec: each event is delimited by a blank line,\n * and fields are `event:`, `data:`, `id:`.\n */\n\nimport type { StreamEvent } from '../../types/events';\nimport type { PendingAction } from '../../types/actions';\n\ninterface RawSSEEvent {\n event: string;\n data: string;\n id: string;\n}\n\n/**\n * Parse a ReadableStream into SSE events.\n * Yields StreamEvent objects as they arrive.\n */\nexport async function* parseSSEStream(\n stream: ReadableStream<Uint8Array>,\n): AsyncIterable<StreamEvent> {\n const reader = stream.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n\n // Split on double newlines (SSE event delimiter)\n const parts = buffer.split('\\n\\n');\n // Keep the last part as buffer (may be incomplete)\n buffer = parts.pop() ?? '';\n\n for (const part of parts) {\n const raw = parseRawEvent(part);\n if (!raw) continue;\n\n const mapped = mapToStreamEvent(raw);\n if (mapped) yield mapped;\n }\n }\n\n // Process any remaining buffer\n if (buffer.trim()) {\n const raw = parseRawEvent(buffer);\n if (raw) {\n const mapped = mapToStreamEvent(raw);\n if (mapped) yield mapped;\n }\n }\n } finally {\n reader.releaseLock();\n }\n}\n\n/** Parse raw SSE text block into event/data/id fields */\nfunction parseRawEvent(block: string): RawSSEEvent | null {\n let event = '';\n let data = '';\n let id = '';\n\n const lines = block.split('\\n');\n for (const line of lines) {\n if (line.startsWith('event:')) {\n event = line.slice(6).trim();\n } else if (line.startsWith('data:')) {\n data = line.slice(5).trim();\n } else if (line.startsWith('id:')) {\n id = line.slice(3).trim();\n }\n // Lines starting with ':' are comments, ignored\n }\n\n if (!event && !data) return null;\n\n return { event, data, id };\n}\n\n/** Map a raw SSE event to a typed StreamEvent */\nfunction mapToStreamEvent(raw: RawSSEEvent): StreamEvent | null {\n const type = raw.event;\n\n try {\n const payload = raw.data ? JSON.parse(raw.data) : {};\n\n switch (type) {\n case 'meta':\n return {\n type: 'meta',\n conversationId: payload.conversationId,\n };\n\n case 'status':\n return {\n type: 'status',\n text: payload.text,\n };\n\n case 'content.delta':\n return {\n type: 'content.delta',\n delta: payload.delta,\n };\n\n case 'tool.start':\n return {\n type: 'tool.start',\n tool: payload.tool,\n };\n\n case 'tool.end':\n return {\n type: 'tool.end',\n tool: payload.tool,\n success: payload.success,\n };\n\n case 'action':\n return {\n type: 'action',\n action: payload as PendingAction,\n };\n\n case 'handoff':\n return {\n type: 'handoff',\n message: payload.message,\n agentName: payload.agentName,\n reason: payload.reason,\n };\n\n case 'response.completed':\n return {\n type: 'response.completed',\n message: payload.message,\n conversationId: payload.conversationId,\n insights: payload.insights ?? [],\n metadata: payload.metadata,\n };\n\n case 'error':\n return {\n type: 'error',\n message: payload.message,\n };\n\n case 'keepalive':\n return {\n type: 'keepalive',\n ts: payload.ts,\n };\n\n default:\n // Unknown event type — skip\n return null;\n }\n } catch {\n // Malformed JSON — skip\n return null;\n }\n}\n","/**\n * ThaliqNativeProvider — Default provider that communicates with the Thaliq API.\n *\n * - chat() → POST /api/agent/chat\n * - stream() → GET /api/agent/stream (SSE)\n */\n\nimport type { Provider, ProviderRequest } from '../../types/provider';\nimport type { ChatResponse } from '../../types/responses';\nimport type { StreamEvent } from '../../types/events';\nimport type { Logger } from '../../types/config';\nimport { StreamError } from '../../types/errors';\nimport { HttpClient } from './http-client';\nimport { parseSSEStream } from './sse-parser';\n\nexport interface ThaliqNativeProviderConfig {\n baseUrl: string;\n timeout: number;\n logger: Logger;\n}\n\nexport class ThaliqNativeProvider implements Provider {\n readonly name = 'thaliq-native';\n private readonly http: HttpClient;\n private readonly logger: Logger;\n\n constructor(config: ThaliqNativeProviderConfig) {\n this.logger = config.logger;\n this.http = new HttpClient({\n baseUrl: config.baseUrl,\n timeout: config.timeout,\n logger: config.logger,\n });\n }\n\n /** POST /api/agent/chat — non-streaming */\n async chat(request: ProviderRequest): Promise<ChatResponse> {\n const body: Record<string, unknown> = {\n message: request.message,\n };\n\n if (request.conversationId) body['conversationId'] = request.conversationId;\n if (request.agentType) body['agentType'] = request.agentType;\n if (request.actionResponse) body['actionResponse'] = request.actionResponse;\n\n return this.http.json<ChatResponse>({\n method: 'POST',\n path: '/api/agent/chat',\n headers: request.headers,\n body,\n signal: request.signal,\n timeout: request.timeout,\n });\n }\n\n /** GET /api/agent/stream — SSE streaming */\n async *stream(request: ProviderRequest): AsyncIterable<StreamEvent> {\n // Build query string\n const params = new URLSearchParams();\n params.set('q', request.message);\n if (request.conversationId) params.set('conversationId', request.conversationId);\n if (request.agentType) params.set('agentType', request.agentType);\n if (request.actionResponse) {\n params.set('actionResponse', JSON.stringify(request.actionResponse));\n }\n\n const response = await this.http.stream({\n method: 'GET',\n path: `/api/agent/stream?${params.toString()}`,\n headers: {\n ...request.headers,\n accept: 'text/event-stream',\n },\n signal: request.signal,\n timeout: request.timeout,\n });\n\n if (!response.body) {\n throw new StreamError('Response body is null — streaming not supported');\n }\n\n this.logger.debug('SSE stream connected');\n\n yield* parseSSEStream(response.body);\n }\n}\n","/**\n * Typed EventEmitter — zero-dependency, type-safe event system.\n *\n * @example\n * ```typescript\n * const emitter = new TypedEventEmitter<SDKEventMap>();\n * emitter.on('error', (err) => console.error(err));\n * emitter.once('identify', (userId) => console.log('Identified:', userId));\n * ```\n */\n\n/** Callback function type */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype Callback = (...args: any[]) => void;\n\n/** Typed listener with optional _once flag */\ntype Listener = Callback & { _once?: boolean };\n\nexport class TypedEventEmitter<T extends { [K in keyof T]: Callback }> {\n private readonly _listeners = new Map<keyof T, Set<Listener>>();\n\n /** Register a listener for an event */\n on<K extends keyof T>(event: K, listener: T[K]): this {\n if (!this._listeners.has(event)) {\n this._listeners.set(event, new Set());\n }\n this._listeners.get(event)!.add(listener as Listener);\n return this;\n }\n\n /** Register a one-time listener */\n once<K extends keyof T>(event: K, listener: T[K]): this {\n const wrapped = listener as Listener;\n wrapped._once = true;\n return this.on(event, listener);\n }\n\n /** Remove a listener */\n off<K extends keyof T>(event: K, listener: T[K]): this {\n const set = this._listeners.get(event);\n if (set) {\n set.delete(listener as Listener);\n if (set.size === 0) {\n this._listeners.delete(event);\n }\n }\n return this;\n }\n\n /** Emit an event to all registered listeners */\n emit<K extends keyof T>(event: K, ...args: Parameters<T[K]>): void {\n const set = this._listeners.get(event);\n if (!set) return;\n\n for (const listener of set) {\n listener(...args);\n if (listener._once) {\n set.delete(listener);\n }\n }\n\n if (set.size === 0) {\n this._listeners.delete(event);\n }\n }\n\n /** Remove all listeners for an event, or all listeners if no event specified */\n removeAllListeners(event?: keyof T): this {\n if (event) {\n this._listeners.delete(event);\n } else {\n this._listeners.clear();\n }\n return this;\n }\n\n /** Get the count of listeners for a specific event */\n listenerCount(event: keyof T): number {\n return this._listeners.get(event)?.size ?? 0;\n }\n}\n","/**\n * Default console-based logger with level filtering.\n */\n\nimport type { Logger, LogLevel } from '../types/config';\n\nconst LEVEL_ORDER: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n silent: 4,\n};\n\nexport function createDefaultLogger(minLevel: LogLevel): Logger {\n const min = LEVEL_ORDER[minLevel];\n\n return {\n debug(message: string, ...args: unknown[]) {\n if (min <= LEVEL_ORDER.debug) console.debug(`[thaliq] ${message}`, ...args);\n },\n info(message: string, ...args: unknown[]) {\n if (min <= LEVEL_ORDER.info) console.info(`[thaliq] ${message}`, ...args);\n },\n warn(message: string, ...args: unknown[]) {\n if (min <= LEVEL_ORDER.warn) console.warn(`[thaliq] ${message}`, ...args);\n },\n error(message: string, ...args: unknown[]) {\n if (min <= LEVEL_ORDER.error) console.error(`[thaliq] ${message}`, ...args);\n },\n };\n}\n","/**\n * Thaliq — Main SDK client class.\n *\n * @example\n * ```typescript\n * import { Thaliq } from '@thaliq/sdk';\n *\n * const thaliq = new Thaliq({ apiKey: 'tq_live_xxx' });\n *\n * // Events\n * thaliq.on('error', (err) => console.error(err));\n * thaliq.on('retry', (attempt, err, delay) => console.warn(`Retry #${attempt}`));\n *\n * // Identify user (B2B)\n * thaliq.identify({ userId: 'usr_123', email: 'user@company.com' });\n *\n * // Chat\n * const response = await thaliq.agent.chat('Hello!');\n *\n * // Stream\n * const stream = thaliq.agent.stream('Analyze Q4 sales');\n * for await (const event of stream) {\n * if (event.type === 'content.delta') process.stdout.write(event.delta);\n * }\n *\n * // Conversations are auto-tracked\n * console.log(thaliq.conversations.active);\n * ```\n */\n\nimport type { ThaliqConfig, ResolvedConfig, SDKEventMap } from './types/config';\nimport type { UserIdentity } from './types/identity';\nimport type { Provider } from './types/provider';\nimport { ValidationError } from './types/errors';\nimport { AgentClient } from './agent/agent-client';\nimport { ConversationManager } from './agent/conversation-manager';\nimport { ThaliqNativeProvider } from './providers/thaliq-native';\nimport { TypedEventEmitter } from './utils/event-emitter';\nimport { createDefaultLogger } from './utils/logger';\n\nconst DEFAULT_BASE_URL = 'https://api.thaliq.com';\nconst DEFAULT_TIMEOUT = 30_000;\nconst DEFAULT_MAX_RETRIES = 2;\nconst DEFAULT_BASE_DELAY = 500;\nconst DEFAULT_MAX_DELAY = 10_000;\n\nexport class Thaliq {\n private readonly config: ResolvedConfig;\n private readonly provider: Provider;\n private readonly emitter = new TypedEventEmitter<SDKEventMap>();\n private identity: UserIdentity | null = null;\n\n /** Agent client — use `thaliq.agent.chat()` and `thaliq.agent.stream()` */\n readonly agent: AgentClient;\n\n /** Conversations manager — create, track, and list conversations */\n readonly conversations: ConversationManager;\n\n constructor(userConfig: ThaliqConfig) {\n this.config = resolveConfig(userConfig);\n this.provider = userConfig.provider ?? new ThaliqNativeProvider({\n baseUrl: this.config.baseUrl,\n timeout: this.config.timeout,\n logger: this.config.logger,\n });\n\n this.conversations = new ConversationManager();\n\n this.agent = new AgentClient(\n this.config,\n this.provider,\n () => this.identity,\n this.emitter,\n this.conversations,\n );\n }\n\n /** Register an event listener */\n on<K extends keyof SDKEventMap>(event: K, listener: SDKEventMap[K]): this {\n this.emitter.on(event, listener);\n return this;\n }\n\n /** Register a one-time event listener */\n once<K extends keyof SDKEventMap>(event: K, listener: SDKEventMap[K]): this {\n this.emitter.once(event, listener);\n return this;\n }\n\n /** Remove an event listener */\n off<K extends keyof SDKEventMap>(event: K, listener: SDKEventMap[K]): this {\n this.emitter.off(event, listener);\n return this;\n }\n\n /** Set the user identity for subsequent requests */\n identify(user: UserIdentity): void {\n if (!user.userId) {\n throw new ValidationError('userId is required for identify()');\n }\n this.identity = user;\n this.config.logger.info(`User identified: ${user.userId}`);\n this.emitter.emit('identify', user.userId);\n }\n\n /** Clear user identity and local state */\n reset(): void {\n this.identity = null;\n this.conversations.clear();\n this.config.logger.info('SDK state reset');\n this.emitter.emit('reset');\n }\n}\n\n/** Merge user config with defaults */\nfunction resolveConfig(config: ThaliqConfig): ResolvedConfig {\n if (!config.apiKey) {\n throw new ValidationError('apiKey is required');\n }\n\n const logLevel = config.logLevel ?? 'warn';\n const logger = config.logger ?? createDefaultLogger(logLevel);\n const maxRetries = config.maxRetries ?? config.retry?.maxRetries ?? DEFAULT_MAX_RETRIES;\n\n return {\n apiKey: config.apiKey,\n baseUrl: (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, ''),\n integrationType: config.integrationType ?? 'sdk',\n timeout: config.timeout ?? DEFAULT_TIMEOUT,\n maxRetries,\n retry: {\n maxRetries,\n baseDelay: config.retry?.baseDelay ?? DEFAULT_BASE_DELAY,\n maxDelay: config.retry?.maxDelay ?? DEFAULT_MAX_DELAY,\n },\n logger,\n logLevel,\n defaultHeaders: config.defaultHeaders ?? {},\n };\n}\n","/**\n * ActionResponseBuilder — helpers for constructing ActionResponse objects.\n *\n * Provides static factory methods for each HITL action type,\n * so developers don't need to manually build ActionResponse objects.\n *\n * @example\n * ```typescript\n * import { ActionResponseBuilder } from '@thaliq/sdk';\n *\n * // Accept a consent/confirm action\n * const accept = ActionResponseBuilder.accept('inst_123');\n *\n * // Reject an action\n * const reject = ActionResponseBuilder.reject('inst_123');\n *\n * // Select an option\n * const select = ActionResponseBuilder.select('inst_123', 'option_a');\n *\n * // Submit a form\n * const form = ActionResponseBuilder.submitForm('inst_123', {\n * amount: '500',\n * currency: 'USD',\n * });\n * ```\n */\n\nimport type { ActionResponse } from '../types/actions';\n\nexport class ActionResponseBuilder {\n /**\n * Accept a consent or confirm action.\n *\n * @param instructionId - The instruction ID from `pendingAction.instructionId`\n */\n static accept(instructionId: string): ActionResponse {\n return { instructionId, accepted: true };\n }\n\n /**\n * Reject a consent or confirm action.\n *\n * @param instructionId - The instruction ID from `pendingAction.instructionId`\n */\n static reject(instructionId: string): ActionResponse {\n return { instructionId, accepted: false };\n }\n\n /**\n * Select an option from a select action.\n *\n * @param instructionId - The instruction ID from `pendingAction.instructionId`\n * @param value - The selected option value\n */\n static select(instructionId: string, value: string): ActionResponse {\n return { instructionId, accepted: true, selectedValue: value };\n }\n\n /**\n * Submit form values for a form action.\n *\n * @param instructionId - The instruction ID from `pendingAction.instructionId`\n * @param values - Key-value map of form field names to values\n */\n static submitForm(instructionId: string, values: Record<string, string>): ActionResponse {\n return { instructionId, accepted: true, formValues: values };\n }\n}\n"],"names":["ThaliqError","Error","constructor","message","code","status","super","this","name","AuthError","RateLimitError","retryAfter","ValidationError","ServiceError","StreamError","TimeoutError","ConnectionError","mapHttpError","headers","get","parseInt","AgentStreamImpl","source","abortController","onEvent","onComplete","_conversationId","_status","_pendingAction","_consumed","_source","_abortController","_onEvent","_onComplete","conversationId","pendingAction","abort","Symbol","asyncIterator","event","type","action","finalResponse","metadata","insights","delta","response","model","promptTokens","completionTokens","processingTimeMs","generatedAt","Date","toISOString","text","accumulated","isRetryableError","error","calculateBackoff","attempt","baseDelay","maxDelay","exponential","Math","pow","clamped","min","jitter","random","floor","sleep","ms","Promise","resolve","setTimeout","async","withRetry","fn","options","config","logger","onRetry","signal","lastError","maxRetries","aborted","delayMs","warn","AgentClient","provider","getIdentity","emitter","conversationManager","chat","request","buildRequest","retry","emit","setActive","stream","AbortController","err","respondToAction","originalMessage","agentType","actionResponse","feedback","identity","resolveHeaders","fetch","baseUrl","method","authorization","body","JSON","stringify","messageId","ok","catch","abortSignal","timeout","apiKey","integrationType","userId","participantId","token","mcpTokens","Object","keys","length","key","value","entries","defaultHeaders","ConversationManager","_active","_history","create","ref","id","crypto","randomUUID","replace","c","r","toString","createdAt","push","active","history","existing","find","clear","HttpClient","defaultTimeout","json","rawFetch","parsed","parse","url","path","timeoutController","timeoutId","addEventListener","reason","once","debug","DOMException","clearTimeout","parseRawEvent","block","data","lines","split","line","startsWith","slice","trim","mapToStreamEvent","raw","payload","tool","success","agentName","ts","ThaliqNativeProvider","http","params","URLSearchParams","set","accept","reader","getReader","decoder","TextDecoder","buffer","done","read","decode","parts","pop","part","mapped","releaseLock","parseSSEStream","TypedEventEmitter","_listeners","Map","on","listener","has","Set","add","_once","off","delete","size","args","removeAllListeners","listenerCount","LEVEL_ORDER","info","silent","DEFAULT_BASE_URL","instructionId","accepted","reject","select","selectedValue","submitForm","values","formValues","userConfig","logLevel","minLevel","console","createDefaultLogger","resolveConfig","conversations","agent","identify","user","reset"],"mappings":"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"}
package/thaliq-sdk.es.js CHANGED
@@ -1,2 +1,2 @@
1
- class t extends Error{constructor(t,e,s){super(t),this.name="ThaliqError",this.code=e,this.status=s}}class e extends t{constructor(t,e=401){super(t,"AUTH_ERROR",e),this.name="AuthError"}}class s extends t{constructor(t,e=60){super(t,"RATE_LIMIT",429),this.name="RateLimitError",this.retryAfter=e}}class n extends t{constructor(t){super(t,"VALIDATION_ERROR",400),this.name="ValidationError"}}class r extends t{constructor(t){super(t,"SERVICE_ERROR",503),this.name="ServiceError"}}class o extends t{constructor(t){super(t,"STREAM_ERROR"),this.name="StreamError"}}class i extends t{constructor(t="Request timed out"){super(t,"TIMEOUT_ERROR"),this.name="TimeoutError"}}class a extends t{constructor(t="Connection failed"){super(t,"CONNECTION_ERROR"),this.name="ConnectionError"}}function c(o,i,a){switch(o){case 400:return new n(i);case 401:case 403:return new e(i,o);case 429:{const t=a?.get("retry-after");return new s(i,t?parseInt(t,10):60)}case 503:return new r(i);default:return new t(i,"UNKNOWN_ERROR",o)}}class l{constructor(t,e,s,n){this._conversationId=null,this._status="streaming",this._pendingAction=null,this._consumed=!1,this._source=t,this._abortController=e,this._onEvent=s,this._onComplete=n}get conversationId(){return this._conversationId}get status(){return this._status}get pendingAction(){return this._pendingAction}abort(){this._status="aborted",this._abortController.abort()}async*[Symbol.asyncIterator](){if(this._consumed)throw new o("AgentStream can only be consumed once");this._consumed=!0;try{for await(const t of this._source)"meta"===t.type&&(this._conversationId=t.conversationId),"response.completed"!==t.type||this._conversationId||(this._conversationId=t.conversationId),"action"===t.type&&(this._pendingAction=t.action,this._status="awaiting_action"),"response.completed"===t.type&&(this._status="completed"),"error"===t.type&&(this._status="error"),this._onEvent&&this._onEvent(t),yield t;"streaming"===this._status&&(this._status=this._pendingAction?"awaiting_action":"completed")}finally{this._onComplete&&this._onComplete(this._conversationId,this._status)}}async finalResponse(){let t,e,s="",n="",r=[];for await(const a of this)switch(a.type){case"meta":n=a.conversationId;break;case"content.delta":s+=a.delta;break;case"action":e=a.action;break;case"response.completed":s=a.message,n=a.conversationId,r=a.insights,t=a.metadata;break;case"error":throw new o(a.message)}const i={message:s,conversationId:n,insights:r,metadata:t??{conversationId:n,model:"unknown",promptTokens:0,completionTokens:0,processingTimeMs:0,generatedAt:/* @__PURE__ */(new Date).toISOString()}};return e&&(i.action=e),i}async text(){let t="";for await(const e of this){if("content.delta"===e.type&&(t+=e.delta),"response.completed"===e.type)return e.message;if("error"===e.type)throw new o(e.message)}return t}}function h(o){return!(o instanceof t)||!(o instanceof e)&&(!(o instanceof n)&&(!(o instanceof s)&&(o instanceof r||(o instanceof a||(o instanceof i||!!(o.status&&o.status>=500))))))}function d(t,e,s){const n=e*Math.pow(2,t),r=Math.min(n,s),o=r*Math.random()*.5;return Math.floor(r+o)}function u(t){return new Promise(e=>setTimeout(e,t))}async function g(e,s){const{config:n,logger:r,onRetry:o,signal:i}=s;let a;for(let l=0;l<=n.maxRetries;l++)try{return await e()}catch(c){if(a=c,l>=n.maxRetries)break;if(!h(c))break;if(i?.aborted)break;const e=d(l,n.baseDelay,n.maxDelay);r.warn(`Retry ${l+1}/${n.maxRetries} after ${e}ms`,c instanceof Error?c.message:c),o&&c instanceof t&&o(l+1,c,e),await u(e)}throw a}class m{constructor(t,e,s,n,r){this.config=t,this.provider=e,this.getIdentity=s,this.emitter=n,this.conversationManager=r}async chat(t,e){const s=this.buildRequest(t,e),n=await g(()=>this.provider.chat(s),{config:this.config.retry,logger:this.config.logger,signal:e?.signal,onRetry:(t,e,s)=>{this.emitter.emit("retry",t,e,s)}});return n.conversationId&&this.conversationManager.setActive(n.conversationId),n}stream(e,s){const n=new AbortController,r=this.buildRequest(e,s,n.signal),o=this.provider.stream(r);this.emitter.emit("stream.start",s?.conversationId??null);return new l(o,n,e=>{if("meta"===e.type&&e.conversationId&&this.conversationManager.setActive(e.conversationId),"error"===e.type){const s=new t(e.message,"STREAM_ERROR");this.emitter.emit("error",s)}s?.onEvent&&s.onEvent(e)},t=>{this.emitter.emit("stream.end",t)})}respondToAction(t){return this.stream(t.originalMessage,{conversationId:t.conversationId,agentType:t.agentType,actionResponse:t.actionResponse,onEvent:t.onEvent,signal:t.signal})}buildRequest(t,e,s){const n=this.getIdentity(),r=e?.signal??s;return{message:t,conversationId:e?.conversationId,agentType:e?.agentType,actionResponse:e?.actionResponse,headers:this.resolveHeaders(n),signal:r,timeout:this.config.timeout}}resolveHeaders(t){const e={"x-api-key":this.config.apiKey,"x-integration-type":this.config.integrationType};t&&(t.userId&&(e["x-user-id"]=t.userId),t.participantId&&(e["x-participant-id"]=t.participantId),t.token&&(e.authorization=`Bearer ${t.token}`),t.mcpTokens&&Object.keys(t.mcpTokens).length>0&&(e["x-mcp-tokens"]=JSON.stringify(t.mcpTokens)));for(const[s,n]of Object.entries(this.config.defaultHeaders))e[s]=n;return e}}class p{constructor(){this._active=null,this._history=[]}create(){const t={id:"undefined"!=typeof crypto&&"function"==typeof crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,t=>{const e=16*Math.random()|0;return("x"===t?e:3&e|8).toString(16)}),createdAt:/* @__PURE__ */new Date};return this._history.push(t),t}get active(){return this._active}get history(){return this._history}setActive(t){const e=this._history.find(e=>e.id===t);if(e)this._active=e;else{const e={id:t,createdAt:/* @__PURE__ */new Date};this._history.push(e),this._active=e}}clear(){this._active=null,this._history.length=0}}class f{constructor(t){this.baseUrl=t.baseUrl.replace(/\/+$/,""),this.defaultTimeout=t.timeout,this.logger=t.logger}async json(t){const e=await this.rawFetch(t);if(!e.ok){const t=await e.text().catch(()=>"Unknown error");let s;try{const e=JSON.parse(t);s=e.message??e.error??t}catch{s=t}throw c(e.status,s,e.headers)}return e.json()}async stream(t){const e=await this.rawFetch(t);if(!e.ok){const t=await e.text().catch(()=>"Unknown error");let s;try{const e=JSON.parse(t);s=e.message??e.error??t}catch{s=t}throw c(e.status,s,e.headers)}return e}async rawFetch(t){const e=`${this.baseUrl}${t.path}`,s=t.timeout??this.defaultTimeout,n=new AbortController;let r;t.signal&&t.signal.addEventListener("abort",()=>n.abort(t.signal?.reason),{once:!0}),r=setTimeout(()=>{n.abort(new i(`Request timed out after ${s}ms`))},s);const o={"content-type":"application/json"};for(const[i,a]of Object.entries(t.headers))void 0!==a&&(o[i]=a);this.logger.debug(`${t.method} ${e}`);try{return await fetch(e,{method:t.method,headers:o,body:t.body?JSON.stringify(t.body):void 0,signal:n.signal})}catch(c){if(c instanceof i)throw c;if(c instanceof DOMException&&"AbortError"===c.name){if(n.signal.reason instanceof i)throw n.signal.reason;throw c}throw new a(c instanceof Error?c.message:"Connection failed")}finally{void 0!==r&&clearTimeout(r)}}}function y(t){let e="",s="",n="";const r=t.split("\n");for(const o of r)o.startsWith("event:")?e=o.slice(6).trim():o.startsWith("data:")?s=o.slice(5).trim():o.startsWith("id:")&&(n=o.slice(3).trim());return e||s?{event:e,data:s,id:n}:null}function v(t){const e=t.event;try{const s=t.data?JSON.parse(t.data):{};switch(e){case"meta":return{type:"meta",conversationId:s.conversationId};case"status":return{type:"status",text:s.text};case"content.delta":return{type:"content.delta",delta:s.delta};case"tool.start":return{type:"tool.start",tool:s.tool};case"tool.end":return{type:"tool.end",tool:s.tool,success:s.success};case"action":return{type:"action",action:s};case"response.completed":return{type:"response.completed",message:s.message,conversationId:s.conversationId,insights:s.insights??[],metadata:s.metadata};case"error":return{type:"error",message:s.message};case"keepalive":return{type:"keepalive",ts:s.ts};default:return null}}catch{return null}}class w{constructor(t){this.name="thaliq-native",this.logger=t.logger,this.http=new f({baseUrl:t.baseUrl,timeout:t.timeout,logger:t.logger})}async chat(t){const e={message:t.message};return t.conversationId&&(e.conversationId=t.conversationId),t.agentType&&(e.agentType=t.agentType),t.actionResponse&&(e.actionResponse=t.actionResponse),this.http.json({method:"POST",path:"/api/agent/chat",headers:t.headers,body:e,signal:t.signal,timeout:t.timeout})}async*stream(t){const e=new URLSearchParams;e.set("q",t.message),t.conversationId&&e.set("conversationId",t.conversationId),t.agentType&&e.set("agentType",t.agentType),t.actionResponse&&e.set("actionResponse",JSON.stringify(t.actionResponse));const s=await this.http.stream({method:"GET",path:`/api/agent/stream?${e.toString()}`,headers:{...t.headers,accept:"text/event-stream"},signal:t.signal,timeout:t.timeout});if(!s.body)throw new o("Response body is null — streaming not supported");this.logger.debug("SSE stream connected"),yield*async function*(t){const e=t.getReader(),s=new TextDecoder;let n="";try{for(;;){const{done:t,value:r}=await e.read();if(t)break;n+=s.decode(r,{stream:!0});const o=n.split("\n\n");n=o.pop()??"";for(const e of o){const t=y(e);if(!t)continue;const s=v(t);s&&(yield s)}}if(n.trim()){const t=y(n);if(t){const e=v(t);e&&(yield e)}}}finally{e.releaseLock()}}(s.body)}}class _{constructor(){this._listeners=/* @__PURE__ */new Map}on(t,e){return this._listeners.has(t)||this._listeners.set(t,/* @__PURE__ */new Set),this._listeners.get(t).add(e),this}once(t,e){return e._once=!0,this.on(t,e)}off(t,e){const s=this._listeners.get(t);return s&&(s.delete(e),0===s.size&&this._listeners.delete(t)),this}emit(t,...e){const s=this._listeners.get(t);if(s){for(const t of s)t(...e),t._once&&s.delete(t);0===s.size&&this._listeners.delete(t)}}removeAllListeners(t){return t?this._listeners.delete(t):this._listeners.clear(),this}listenerCount(t){return this._listeners.get(t)?.size??0}}const x={debug:0,info:1,warn:2,error:3,silent:4};const I="https://api.thaliq.com";class R{constructor(t){this.emitter=new _,this.identity=null,this.config=function(t){if(!t.apiKey)throw new n("apiKey is required");const e=t.logLevel??"warn",s=t.logger??function(t){const e=x[t];return{debug(t,...s){e<=x.debug&&console.debug(`[thaliq] ${t}`,...s)},info(t,...s){e<=x.info&&console.info(`[thaliq] ${t}`,...s)},warn(t,...s){e<=x.warn&&console.warn(`[thaliq] ${t}`,...s)},error(t,...s){e<=x.error&&console.error(`[thaliq] ${t}`,...s)}}}(e),r=t.maxRetries??t.retry?.maxRetries??2;return{apiKey:t.apiKey,baseUrl:(t.baseUrl??I).replace(/\/+$/,""),integrationType:t.integrationType??"sdk",timeout:t.timeout??3e4,maxRetries:r,retry:{maxRetries:r,baseDelay:t.retry?.baseDelay??500,maxDelay:t.retry?.maxDelay??1e4},logger:s,logLevel:e,defaultHeaders:t.defaultHeaders??{}}}(t),this.provider=t.provider??new w({baseUrl:this.config.baseUrl,timeout:this.config.timeout,logger:this.config.logger}),this.conversations=new p,this.agent=new m(this.config,this.provider,()=>this.identity,this.emitter,this.conversations)}on(t,e){return this.emitter.on(t,e),this}once(t,e){return this.emitter.once(t,e),this}off(t,e){return this.emitter.off(t,e),this}identify(t){if(!t.userId)throw new n("userId is required for identify()");this.identity=t,this.config.logger.info(`User identified: ${t.userId}`),this.emitter.emit("identify",t.userId)}reset(){this.identity=null,this.conversations.clear(),this.config.logger.info("SDK state reset"),this.emitter.emit("reset")}}class b{static accept(t){return{instructionId:t,accepted:!0}}static reject(t){return{instructionId:t,accepted:!1}}static select(t,e){return{instructionId:t,accepted:!0,selectedValue:e}}static submitForm(t,e){return{instructionId:t,accepted:!0,formValues:e}}}export{b as ActionResponseBuilder,e as AuthError,a as ConnectionError,p as ConversationManager,s as RateLimitError,r as ServiceError,o as StreamError,R as Thaliq,t as ThaliqError,w as ThaliqNativeProvider,i as TimeoutError,_ as TypedEventEmitter,n as ValidationError,d as calculateBackoff,h as isRetryableError,g as withRetry};
1
+ class t extends Error{constructor(t,e,s){super(t),this.name="ThaliqError",this.code=e,this.status=s}}class e extends t{constructor(t,e=401){super(t,"AUTH_ERROR",e),this.name="AuthError"}}class s extends t{constructor(t,e=60){super(t,"RATE_LIMIT",429),this.name="RateLimitError",this.retryAfter=e}}class n extends t{constructor(t){super(t,"VALIDATION_ERROR",400),this.name="ValidationError"}}class r extends t{constructor(t){super(t,"SERVICE_ERROR",503),this.name="ServiceError"}}class i extends t{constructor(t){super(t,"STREAM_ERROR"),this.name="StreamError"}}class o extends t{constructor(t="Request timed out"){super(t,"TIMEOUT_ERROR"),this.name="TimeoutError"}}class a extends t{constructor(t="Connection failed"){super(t,"CONNECTION_ERROR"),this.name="ConnectionError"}}function c(i,o,a){switch(i){case 400:return new n(o);case 401:case 403:return new e(o,i);case 429:{const t=a?.get("retry-after");return new s(o,t?parseInt(t,10):60)}case 503:return new r(o);default:return new t(o,"UNKNOWN_ERROR",i)}}class h{constructor(t,e,s,n){this._conversationId=null,this._status="streaming",this._pendingAction=null,this._consumed=!1,this._source=t,this._abortController=e,this._onEvent=s,this._onComplete=n}get conversationId(){return this._conversationId}get status(){return this._status}get pendingAction(){return this._pendingAction}abort(){this._status="aborted",this._abortController.abort()}async*[Symbol.asyncIterator](){if(this._consumed)throw new i("AgentStream can only be consumed once");this._consumed=!0;try{for await(const t of this._source)"meta"===t.type&&(this._conversationId=t.conversationId),"response.completed"!==t.type||this._conversationId||(this._conversationId=t.conversationId),"action"===t.type&&(this._pendingAction=t.action,this._status="awaiting_action"),"handoff"===t.type&&(this._status="handoff"),"response.completed"===t.type&&(this._status="completed"),"error"===t.type&&(this._status="error"),this._onEvent&&this._onEvent(t),yield t;"streaming"===this._status&&(this._status=this._pendingAction?"awaiting_action":"completed")}finally{this._onComplete&&this._onComplete(this._conversationId,this._status)}}async finalResponse(){let t,e,s="",n="",r=[];for await(const a of this)switch(a.type){case"meta":n=a.conversationId;break;case"content.delta":s+=a.delta;break;case"action":e=a.action;break;case"response.completed":s=a.message,n=a.conversationId,r=a.insights,t=a.metadata;break;case"error":throw new i(a.message)}const o={message:s,conversationId:n,insights:r,metadata:t??{conversationId:n,model:"unknown",promptTokens:0,completionTokens:0,processingTimeMs:0,generatedAt:/* @__PURE__ */(new Date).toISOString()}};return e&&(o.action=e),o}async text(){let t="";for await(const e of this){if("content.delta"===e.type&&(t+=e.delta),"response.completed"===e.type)return e.message;if("error"===e.type)throw new i(e.message)}return t}}function l(i){return!(i instanceof t)||!(i instanceof e)&&(!(i instanceof n)&&(!(i instanceof s)&&(i instanceof r||(i instanceof a||(i instanceof o||!!(i.status&&i.status>=500))))))}function d(t,e,s){const n=e*Math.pow(2,t),r=Math.min(n,s),i=r*Math.random()*.5;return Math.floor(r+i)}function u(t){return new Promise(e=>setTimeout(e,t))}async function g(e,s){const{config:n,logger:r,onRetry:i,signal:o}=s;let a;for(let h=0;h<=n.maxRetries;h++)try{return await e()}catch(c){if(a=c,h>=n.maxRetries)break;if(!l(c))break;if(o?.aborted)break;const e=d(h,n.baseDelay,n.maxDelay);r.warn(`Retry ${h+1}/${n.maxRetries} after ${e}ms`,c instanceof Error?c.message:c),i&&c instanceof t&&i(h+1,c,e),await u(e)}throw a}class m{constructor(t,e,s,n,r){this.config=t,this.provider=e,this.getIdentity=s,this.emitter=n,this.conversationManager=r}async chat(t,e){const s=this.buildRequest(t,e),n=await g(()=>this.provider.chat(s),{config:this.config.retry,logger:this.config.logger,signal:e?.signal,onRetry:(t,e,s)=>{this.emitter.emit("retry",t,e,s)}});return n.conversationId&&this.conversationManager.setActive(n.conversationId),n}stream(e,s){const n=new AbortController,r=this.buildRequest(e,s,n.signal),i=this.provider.stream(r);this.emitter.emit("stream.start",s?.conversationId??null);return new h(i,n,e=>{if("meta"===e.type&&e.conversationId&&this.conversationManager.setActive(e.conversationId),"error"===e.type){const s=new t(e.message,"STREAM_ERROR");this.emitter.emit("error",s)}s?.onEvent&&s.onEvent(e)},t=>{this.emitter.emit("stream.end",t)})}respondToAction(t){return this.stream(t.originalMessage,{conversationId:t.conversationId,agentType:t.agentType,actionResponse:t.actionResponse,onEvent:t.onEvent,signal:t.signal})}async feedback(e){const s=this.getIdentity(),n=this.resolveHeaders(s),r=await fetch(`${this.config.baseUrl}/api/agent/feedback`,{method:"POST",headers:{"content-type":"application/json","x-api-key":n["x-api-key"],"x-integration-type":n["x-integration-type"],...n["x-user-id"]?{"x-user-id":n["x-user-id"]}:{},...n.authorization?{authorization:n.authorization}:{}},body:JSON.stringify({conversationId:e.conversationId,messageId:e.messageId,feedback:e.feedback})});if(!r.ok){const e=await r.text().catch(()=>`HTTP ${r.status}`);throw new t(e,"UNKNOWN_ERROR")}}buildRequest(t,e,s){const n=this.getIdentity(),r=e?.signal??s;return{message:t,conversationId:e?.conversationId,agentType:e?.agentType,actionResponse:e?.actionResponse,headers:this.resolveHeaders(n),signal:r,timeout:this.config.timeout}}resolveHeaders(t){const e={"x-api-key":this.config.apiKey,"x-integration-type":this.config.integrationType};t&&(t.userId&&(e["x-user-id"]=t.userId),t.participantId&&(e["x-participant-id"]=t.participantId),t.token&&(e.authorization=`Bearer ${t.token}`),t.mcpTokens&&Object.keys(t.mcpTokens).length>0&&(e["x-mcp-tokens"]=JSON.stringify(t.mcpTokens)));for(const[s,n]of Object.entries(this.config.defaultHeaders))e[s]=n;return e}}class p{constructor(){this._active=null,this._history=[]}create(){const t={id:"undefined"!=typeof crypto&&"function"==typeof crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,t=>{const e=16*Math.random()|0;return("x"===t?e:3&e|8).toString(16)}),createdAt:/* @__PURE__ */new Date};return this._history.push(t),t}get active(){return this._active}get history(){return this._history}setActive(t){const e=this._history.find(e=>e.id===t);if(e)this._active=e;else{const e={id:t,createdAt:/* @__PURE__ */new Date};this._history.push(e),this._active=e}}clear(){this._active=null,this._history.length=0}}class f{constructor(t){this.baseUrl=t.baseUrl.replace(/\/+$/,""),this.defaultTimeout=t.timeout,this.logger=t.logger}async json(t){const e=await this.rawFetch(t);if(!e.ok){const t=await e.text().catch(()=>"Unknown error");let s;try{const e=JSON.parse(t);s=e.message??e.error??t}catch{s=t}throw c(e.status,s,e.headers)}return e.json()}async stream(t){const e=await this.rawFetch(t);if(!e.ok){const t=await e.text().catch(()=>"Unknown error");let s;try{const e=JSON.parse(t);s=e.message??e.error??t}catch{s=t}throw c(e.status,s,e.headers)}return e}async rawFetch(t){const e=`${this.baseUrl}${t.path}`,s=t.timeout??this.defaultTimeout,n=new AbortController;let r;t.signal&&t.signal.addEventListener("abort",()=>n.abort(t.signal?.reason),{once:!0}),r=setTimeout(()=>{n.abort(new o(`Request timed out after ${s}ms`))},s);const i={"content-type":"application/json"};for(const[o,a]of Object.entries(t.headers))void 0!==a&&(i[o]=a);this.logger.debug(`${t.method} ${e}`);try{return await fetch(e,{method:t.method,headers:i,body:t.body?JSON.stringify(t.body):void 0,signal:n.signal})}catch(c){if(c instanceof o)throw c;if(c instanceof DOMException&&"AbortError"===c.name){if(n.signal.reason instanceof o)throw n.signal.reason;throw c}throw new a(c instanceof Error?c.message:"Connection failed")}finally{void 0!==r&&clearTimeout(r)}}}function y(t){let e="",s="",n="";const r=t.split("\n");for(const i of r)i.startsWith("event:")?e=i.slice(6).trim():i.startsWith("data:")?s=i.slice(5).trim():i.startsWith("id:")&&(n=i.slice(3).trim());return e||s?{event:e,data:s,id:n}:null}function v(t){const e=t.event;try{const s=t.data?JSON.parse(t.data):{};switch(e){case"meta":return{type:"meta",conversationId:s.conversationId};case"status":return{type:"status",text:s.text};case"content.delta":return{type:"content.delta",delta:s.delta};case"tool.start":return{type:"tool.start",tool:s.tool};case"tool.end":return{type:"tool.end",tool:s.tool,success:s.success};case"action":return{type:"action",action:s};case"handoff":return{type:"handoff",message:s.message,agentName:s.agentName,reason:s.reason};case"response.completed":return{type:"response.completed",message:s.message,conversationId:s.conversationId,insights:s.insights??[],metadata:s.metadata};case"error":return{type:"error",message:s.message};case"keepalive":return{type:"keepalive",ts:s.ts};default:return null}}catch{return null}}class w{constructor(t){this.name="thaliq-native",this.logger=t.logger,this.http=new f({baseUrl:t.baseUrl,timeout:t.timeout,logger:t.logger})}async chat(t){const e={message:t.message};return t.conversationId&&(e.conversationId=t.conversationId),t.agentType&&(e.agentType=t.agentType),t.actionResponse&&(e.actionResponse=t.actionResponse),this.http.json({method:"POST",path:"/api/agent/chat",headers:t.headers,body:e,signal:t.signal,timeout:t.timeout})}async*stream(t){const e=new URLSearchParams;e.set("q",t.message),t.conversationId&&e.set("conversationId",t.conversationId),t.agentType&&e.set("agentType",t.agentType),t.actionResponse&&e.set("actionResponse",JSON.stringify(t.actionResponse));const s=await this.http.stream({method:"GET",path:`/api/agent/stream?${e.toString()}`,headers:{...t.headers,accept:"text/event-stream"},signal:t.signal,timeout:t.timeout});if(!s.body)throw new i("Response body is null — streaming not supported");this.logger.debug("SSE stream connected"),yield*async function*(t){const e=t.getReader(),s=new TextDecoder;let n="";try{for(;;){const{done:t,value:r}=await e.read();if(t)break;n+=s.decode(r,{stream:!0});const i=n.split("\n\n");n=i.pop()??"";for(const e of i){const t=y(e);if(!t)continue;const s=v(t);s&&(yield s)}}if(n.trim()){const t=y(n);if(t){const e=v(t);e&&(yield e)}}}finally{e.releaseLock()}}(s.body)}}class x{constructor(){this._listeners=/* @__PURE__ */new Map}on(t,e){return this._listeners.has(t)||this._listeners.set(t,/* @__PURE__ */new Set),this._listeners.get(t).add(e),this}once(t,e){return e._once=!0,this.on(t,e)}off(t,e){const s=this._listeners.get(t);return s&&(s.delete(e),0===s.size&&this._listeners.delete(t)),this}emit(t,...e){const s=this._listeners.get(t);if(s){for(const t of s)t(...e),t._once&&s.delete(t);0===s.size&&this._listeners.delete(t)}}removeAllListeners(t){return t?this._listeners.delete(t):this._listeners.clear(),this}listenerCount(t){return this._listeners.get(t)?.size??0}}const _={debug:0,info:1,warn:2,error:3,silent:4};const I="https://api.thaliq.com";class R{constructor(t){this.emitter=new x,this.identity=null,this.config=function(t){if(!t.apiKey)throw new n("apiKey is required");const e=t.logLevel??"warn",s=t.logger??function(t){const e=_[t];return{debug(t,...s){e<=_.debug&&console.debug(`[thaliq] ${t}`,...s)},info(t,...s){e<=_.info&&console.info(`[thaliq] ${t}`,...s)},warn(t,...s){e<=_.warn&&console.warn(`[thaliq] ${t}`,...s)},error(t,...s){e<=_.error&&console.error(`[thaliq] ${t}`,...s)}}}(e),r=t.maxRetries??t.retry?.maxRetries??2;return{apiKey:t.apiKey,baseUrl:(t.baseUrl??I).replace(/\/+$/,""),integrationType:t.integrationType??"sdk",timeout:t.timeout??3e4,maxRetries:r,retry:{maxRetries:r,baseDelay:t.retry?.baseDelay??500,maxDelay:t.retry?.maxDelay??1e4},logger:s,logLevel:e,defaultHeaders:t.defaultHeaders??{}}}(t),this.provider=t.provider??new w({baseUrl:this.config.baseUrl,timeout:this.config.timeout,logger:this.config.logger}),this.conversations=new p,this.agent=new m(this.config,this.provider,()=>this.identity,this.emitter,this.conversations)}on(t,e){return this.emitter.on(t,e),this}once(t,e){return this.emitter.once(t,e),this}off(t,e){return this.emitter.off(t,e),this}identify(t){if(!t.userId)throw new n("userId is required for identify()");this.identity=t,this.config.logger.info(`User identified: ${t.userId}`),this.emitter.emit("identify",t.userId)}reset(){this.identity=null,this.conversations.clear(),this.config.logger.info("SDK state reset"),this.emitter.emit("reset")}}class b{static accept(t){return{instructionId:t,accepted:!0}}static reject(t){return{instructionId:t,accepted:!1}}static select(t,e){return{instructionId:t,accepted:!0,selectedValue:e}}static submitForm(t,e){return{instructionId:t,accepted:!0,formValues:e}}}export{b as ActionResponseBuilder,e as AuthError,a as ConnectionError,p as ConversationManager,s as RateLimitError,r as ServiceError,i as StreamError,R as Thaliq,t as ThaliqError,w as ThaliqNativeProvider,o as TimeoutError,x as TypedEventEmitter,n as ValidationError,d as calculateBackoff,l as isRetryableError,g as withRetry};
2
2
  //# sourceMappingURL=thaliq-sdk.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"thaliq-sdk.es.js","sources":["../../../libs/sdk/src/types/errors.ts","../../../libs/sdk/src/agent/agent-stream.ts","../../../libs/sdk/src/utils/retry.ts","../../../libs/sdk/src/agent/agent-client.ts","../../../libs/sdk/src/agent/conversation-manager.ts","../../../libs/sdk/src/utils/uuid.ts","../../../libs/sdk/src/providers/thaliq-native/http-client.ts","../../../libs/sdk/src/providers/thaliq-native/sse-parser.ts","../../../libs/sdk/src/providers/thaliq-native/thaliq-native.provider.ts","../../../libs/sdk/src/utils/event-emitter.ts","../../../libs/sdk/src/utils/logger.ts","../../../libs/sdk/src/client.ts","../../../libs/sdk/src/utils/action-response-builder.ts"],"sourcesContent":["/**\n * @thaliq/sdk - Error Types\n * @module types/errors\n */\n\n/**\n * SDK error codes used in `ThaliqError.code`.\n * Use these to programmatically distinguish error types.\n */\nexport type ErrorCode =\n | 'AUTH_ERROR'\n | 'RATE_LIMIT'\n | 'VALIDATION_ERROR'\n | 'SERVICE_ERROR'\n | 'STREAM_ERROR'\n | 'TIMEOUT_ERROR'\n | 'CONNECTION_ERROR'\n | 'UNKNOWN_ERROR';\n\n/** Base error class for all SDK errors */\nexport class ThaliqError extends Error {\n readonly code: ErrorCode;\n readonly status?: number;\n\n constructor(message: string, code: ErrorCode, status?: number) {\n super(message);\n this.name = 'ThaliqError';\n this.code = code;\n this.status = status;\n }\n}\n\n/** Authentication or authorization error (401/403) */\nexport class AuthError extends ThaliqError {\n constructor(message: string, status: number = 401) {\n super(message, 'AUTH_ERROR', status);\n this.name = 'AuthError';\n }\n}\n\n/** Rate limit exceeded (429) */\nexport class RateLimitError extends ThaliqError {\n readonly retryAfter: number;\n\n constructor(message: string, retryAfter: number = 60) {\n super(message, 'RATE_LIMIT', 429);\n this.name = 'RateLimitError';\n this.retryAfter = retryAfter;\n }\n}\n\n/** Request validation error (400) */\nexport class ValidationError extends ThaliqError {\n constructor(message: string) {\n super(message, 'VALIDATION_ERROR', 400);\n this.name = 'ValidationError';\n }\n}\n\n/** Service unavailable (503) */\nexport class ServiceError extends ThaliqError {\n constructor(message: string) {\n super(message, 'SERVICE_ERROR', 503);\n this.name = 'ServiceError';\n }\n}\n\n/** Error during SSE streaming */\nexport class StreamError extends ThaliqError {\n constructor(message: string) {\n super(message, 'STREAM_ERROR');\n this.name = 'StreamError';\n }\n}\n\n/** Request timeout */\nexport class TimeoutError extends ThaliqError {\n constructor(message: string = 'Request timed out') {\n super(message, 'TIMEOUT_ERROR');\n this.name = 'TimeoutError';\n }\n}\n\n/** Network/connection error */\nexport class ConnectionError extends ThaliqError {\n constructor(message: string = 'Connection failed') {\n super(message, 'CONNECTION_ERROR');\n this.name = 'ConnectionError';\n }\n}\n\n/**\n * Maps an HTTP status code to the appropriate ThaliqError subclass.\n * Used internally by the HTTP client; also useful for custom providers.\n */\nexport function mapHttpError(status: number, message: string, headers?: Headers): ThaliqError {\n switch (status) {\n case 400:\n return new ValidationError(message);\n case 401:\n case 403:\n return new AuthError(message, status);\n case 429: {\n const retryAfter = headers?.get('retry-after');\n return new RateLimitError(message, retryAfter ? parseInt(retryAfter, 10) : 60);\n }\n case 503:\n return new ServiceError(message);\n default:\n return new ThaliqError(message, 'UNKNOWN_ERROR', status);\n }\n}\n","/**\n * AgentStream — AsyncIterable wrapper over SSE events.\n *\n * Provides convenient access to the conversation ID, abort,\n * and methods to accumulate the final response or text.\n */\n\nimport type { AgentStream as IAgentStream, StreamStatus } from '../types/agent';\nimport type { StreamEvent } from '../types/events';\nimport type { ChatResponse } from '../types/responses';\nimport type { Insight, ResponseMetadata } from '../types/responses';\nimport type { PendingAction } from '../types/actions';\nimport { StreamError } from '../types/errors';\n\nexport class AgentStreamImpl implements IAgentStream {\n private _conversationId: string | null = null;\n private _status: StreamStatus = 'streaming';\n private _pendingAction: PendingAction | null = null;\n private readonly _source: AsyncIterable<StreamEvent>;\n private readonly _abortController: AbortController;\n private readonly _onEvent?: (event: StreamEvent) => void;\n private readonly _onComplete?: (conversationId: string | null, status: StreamStatus) => void;\n private _consumed = false;\n\n constructor(\n source: AsyncIterable<StreamEvent>,\n abortController: AbortController,\n onEvent?: (event: StreamEvent) => void,\n onComplete?: (conversationId: string | null, status: StreamStatus) => void,\n ) {\n this._source = source;\n this._abortController = abortController;\n this._onEvent = onEvent;\n this._onComplete = onComplete;\n }\n\n get conversationId(): string | null {\n return this._conversationId;\n }\n\n get status(): StreamStatus {\n return this._status;\n }\n\n get pendingAction(): PendingAction | null {\n return this._pendingAction;\n }\n\n abort(): void {\n this._status = 'aborted';\n this._abortController.abort();\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<StreamEvent> {\n if (this._consumed) {\n throw new StreamError('AgentStream can only be consumed once');\n }\n this._consumed = true;\n\n try {\n for await (const event of this._source) {\n // Track conversation ID from meta event\n if (event.type === 'meta') {\n this._conversationId = event.conversationId;\n }\n\n // Also track from response.completed\n if (event.type === 'response.completed' && !this._conversationId) {\n this._conversationId = event.conversationId;\n }\n\n // Track action events — stream is awaiting user response\n if (event.type === 'action') {\n this._pendingAction = event.action;\n this._status = 'awaiting_action';\n }\n\n // Track completion\n if (event.type === 'response.completed') {\n this._status = 'completed';\n }\n\n // Track errors\n if (event.type === 'error') {\n this._status = 'error';\n }\n\n // Fire optional callback\n if (this._onEvent) {\n this._onEvent(event);\n }\n\n yield event;\n }\n\n // If stream ended naturally without explicit status, mark completed\n if (this._status === 'streaming') {\n this._status = this._pendingAction ? 'awaiting_action' : 'completed';\n }\n } finally {\n // Notify completion regardless of how stream ended\n if (this._onComplete) {\n this._onComplete(this._conversationId, this._status);\n }\n }\n }\n\n async finalResponse(): Promise<ChatResponse> {\n let message = '';\n let conversationId = '';\n let insights: Insight[] = [];\n let metadata: ResponseMetadata | undefined;\n let action: PendingAction | undefined;\n\n for await (const event of this) {\n switch (event.type) {\n case 'meta':\n conversationId = event.conversationId;\n break;\n case 'content.delta':\n message += event.delta;\n break;\n case 'action':\n action = event.action;\n break;\n case 'response.completed':\n message = event.message;\n conversationId = event.conversationId;\n insights = event.insights;\n metadata = event.metadata;\n break;\n case 'error':\n throw new StreamError(event.message);\n }\n }\n\n const response: ChatResponse = {\n message,\n conversationId,\n insights,\n metadata: metadata ?? {\n conversationId,\n model: 'unknown',\n promptTokens: 0,\n completionTokens: 0,\n processingTimeMs: 0,\n generatedAt: new Date().toISOString(),\n },\n };\n\n if (action) {\n response.action = action;\n }\n\n return response;\n }\n\n async text(): Promise<string> {\n let accumulated = '';\n\n for await (const event of this) {\n if (event.type === 'content.delta') {\n accumulated += event.delta;\n }\n if (event.type === 'response.completed') {\n return event.message;\n }\n if (event.type === 'error') {\n throw new StreamError(event.message);\n }\n }\n\n return accumulated;\n }\n}\n","/**\n * Retry logic with exponential backoff and jitter.\n *\n * Retries on server errors (500/502/503/504) and network errors.\n * Never retries on client errors (400/401/403/429).\n */\n\nimport type { ResolvedRetryConfig, Logger } from '../types/config';\nimport {\n ThaliqError,\n RateLimitError,\n AuthError,\n ValidationError,\n TimeoutError,\n ConnectionError,\n ServiceError,\n} from '../types/errors';\n\n/**\n * Check if an error is retryable.\n * Returns `true` for server errors (5xx), timeouts, and connection errors.\n * Returns `false` for auth errors (401/403), validation (400), and rate limits (429).\n */\nexport function isRetryableError(error: unknown): boolean {\n if (!(error instanceof ThaliqError)) {\n // Unknown errors (network failures, etc.) are retryable\n return true;\n }\n\n // Never retry client errors\n if (error instanceof AuthError) return false;\n if (error instanceof ValidationError) return false;\n if (error instanceof RateLimitError) return false;\n\n // Retry server errors and connection issues\n if (error instanceof ServiceError) return true;\n if (error instanceof ConnectionError) return true;\n if (error instanceof TimeoutError) return true;\n\n // Retry 5xx status codes\n if (error.status && error.status >= 500) return true;\n\n return false;\n}\n\n/**\n * Calculate the retry delay with exponential backoff and jitter.\n * Formula: `min(baseDelay * 2^attempt, maxDelay) + random(0..50%)`.\n */\nexport function calculateBackoff(\n attempt: number,\n baseDelay: number,\n maxDelay: number,\n): number {\n // Exponential: baseDelay * 2^attempt\n const exponential = baseDelay * Math.pow(2, attempt);\n // Clamp to maxDelay\n const clamped = Math.min(exponential, maxDelay);\n // Add jitter: random 0-50% of the delay\n const jitter = clamped * Math.random() * 0.5;\n return Math.floor(clamped + jitter);\n}\n\n/** Sleep for a given number of milliseconds */\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/** Options for the retry wrapper */\nexport interface RetryOptions {\n config: ResolvedRetryConfig;\n logger: Logger;\n /** Called before each retry attempt */\n onRetry?: (attempt: number, error: ThaliqError, delayMs: number) => void;\n /** AbortSignal to cancel retries */\n signal?: AbortSignal;\n}\n\n/**\n * Execute an async function with automatic retry on retryable errors.\n * Uses exponential backoff with jitter between attempts.\n *\n * @param fn - The async function to execute (and potentially retry)\n * @param options - Retry configuration, logger, and optional callbacks\n * @returns The result of `fn()` on success\n * @throws The last error after all retries are exhausted\n */\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n options: RetryOptions,\n): Promise<T> {\n const { config, logger, onRetry, signal } = options;\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= config.maxRetries; attempt++) {\n try {\n return await fn();\n } catch (error: unknown) {\n lastError = error;\n\n // Don't retry if we've exhausted attempts\n if (attempt >= config.maxRetries) break;\n\n // Don't retry non-retryable errors\n if (!isRetryableError(error)) break;\n\n // Don't retry if aborted\n if (signal?.aborted) break;\n\n const delayMs = calculateBackoff(attempt, config.baseDelay, config.maxDelay);\n\n logger.warn(\n `Retry ${attempt + 1}/${config.maxRetries} after ${delayMs}ms`,\n error instanceof Error ? error.message : error,\n );\n\n if (onRetry && error instanceof ThaliqError) {\n onRetry(attempt + 1, error, delayMs);\n }\n\n await sleep(delayMs);\n }\n }\n\n throw lastError;\n}\n","/**\n * AgentClient — main interface for interacting with agents.\n *\n * Accessed via `thaliq.agent.chat()` and `thaliq.agent.stream()`.\n * Includes automatic retry with exponential backoff for chat requests.\n */\n\nimport type { Provider, ProviderRequest, ResolvedHeaders } from '../types/provider';\nimport type { ChatOptions, StreamOptions, AgentStream, RespondToActionOptions, StreamStatus } from '../types/agent';\nimport type { ChatResponse } from '../types/responses';\nimport type { UserIdentity } from '../types/identity';\nimport type { ResolvedConfig, SDKEventMap } from '../types/config';\nimport type { TypedEventEmitter } from '../utils/event-emitter';\nimport type { ConversationManager } from './conversation-manager';\nimport { RateLimitError, ThaliqError } from '../types/errors';\nimport { AgentStreamImpl } from './agent-stream';\nimport { withRetry } from '../utils/retry';\n\nexport class AgentClient {\n private readonly config: ResolvedConfig;\n private readonly provider: Provider;\n private readonly getIdentity: () => UserIdentity | null;\n private readonly emitter: TypedEventEmitter<SDKEventMap>;\n private readonly conversationManager: ConversationManager;\n\n constructor(\n config: ResolvedConfig,\n provider: Provider,\n getIdentity: () => UserIdentity | null,\n emitter: TypedEventEmitter<SDKEventMap>,\n conversationManager: ConversationManager,\n ) {\n this.config = config;\n this.provider = provider;\n this.getIdentity = getIdentity;\n this.emitter = emitter;\n this.conversationManager = conversationManager;\n }\n\n /** Send a message and wait for the complete response (with automatic retry) */\n async chat(message: string, options?: ChatOptions): Promise<ChatResponse> {\n const request = this.buildRequest(message, options);\n\n const response = await withRetry(\n () => this.provider.chat(request),\n {\n config: this.config.retry,\n logger: this.config.logger,\n signal: options?.signal,\n onRetry: (attempt, error, delayMs) => {\n this.emitter.emit('retry', attempt, error, delayMs);\n },\n },\n );\n\n // Auto-track conversation\n if (response.conversationId) {\n this.conversationManager.setActive(response.conversationId);\n }\n\n return response;\n }\n\n /** Send a message with streaming — returns an AgentStream */\n stream(message: string, options?: StreamOptions): AgentStream {\n const abortController = new AbortController();\n const request = this.buildRequest(message, options, abortController.signal);\n\n // The provider returns an AsyncIterable<StreamEvent>\n const source = this.provider.stream(request);\n\n // Emit stream.start\n this.emitter.emit('stream.start', options?.conversationId ?? null);\n\n const stream = new AgentStreamImpl(\n source,\n abortController,\n (event) => {\n // Auto-track conversation from meta event\n if (event.type === 'meta' && event.conversationId) {\n this.conversationManager.setActive(event.conversationId);\n }\n\n // Emit error/rateLimit events\n if (event.type === 'error') {\n const err = new ThaliqError(event.message, 'STREAM_ERROR');\n this.emitter.emit('error', err);\n }\n\n // Forward to user callback\n if (options?.onEvent) {\n options.onEvent(event);\n }\n },\n // onComplete callback for stream.end event\n (conversationId) => {\n this.emitter.emit('stream.end', conversationId);\n },\n );\n\n return stream;\n }\n\n /**\n * Respond to a pending HITL action and resume the conversation.\n *\n * This is a convenience method that creates a new stream with the\n * action response, continuing the conversation where it left off.\n *\n * @example\n * ```typescript\n * const stream = thaliq.agent.stream('Transfer $500');\n * for await (const event of stream) { ... }\n *\n * if (stream.pendingAction) {\n * const resumed = thaliq.agent.respondToAction({\n * conversationId: stream.conversationId!,\n * originalMessage: 'Transfer $500',\n * actionResponse: ActionResponseBuilder.accept(stream.pendingAction.instructionId),\n * });\n * for await (const event of resumed) { ... }\n * }\n * ```\n */\n respondToAction(options: RespondToActionOptions): AgentStream {\n return this.stream(options.originalMessage, {\n conversationId: options.conversationId,\n agentType: options.agentType,\n actionResponse: options.actionResponse,\n onEvent: options.onEvent,\n signal: options.signal,\n });\n }\n\n /** Build the ProviderRequest from message + options + identity */\n private buildRequest(\n message: string,\n options?: ChatOptions,\n abortSignal?: AbortSignal,\n ): ProviderRequest {\n const identity = this.getIdentity();\n const signal = options?.signal ?? abortSignal;\n\n return {\n message,\n conversationId: options?.conversationId,\n agentType: options?.agentType,\n actionResponse: options?.actionResponse,\n headers: this.resolveHeaders(identity),\n signal,\n timeout: this.config.timeout,\n };\n }\n\n /** Resolve all headers from config + identity */\n private resolveHeaders(identity: UserIdentity | null): ResolvedHeaders {\n const headers: ResolvedHeaders = {\n 'x-api-key': this.config.apiKey,\n 'x-integration-type': this.config.integrationType,\n };\n\n // Identity headers\n if (identity) {\n if (identity.userId) {\n headers['x-user-id'] = identity.userId;\n }\n if (identity.participantId) {\n headers['x-participant-id'] = identity.participantId;\n }\n if (identity.token) {\n headers['authorization'] = `Bearer ${identity.token}`;\n }\n if (identity.mcpTokens && Object.keys(identity.mcpTokens).length > 0) {\n headers['x-mcp-tokens'] = JSON.stringify(identity.mcpTokens);\n }\n }\n\n // Custom default headers\n for (const [key, value] of Object.entries(this.config.defaultHeaders)) {\n headers[key] = value;\n }\n\n return headers;\n }\n}\n","/**\n * ConversationManager — tracks active conversations and auto-assigns IDs.\n *\n * @example\n * ```typescript\n * const conv = thaliq.conversations.create();\n * console.log(conv.id); // UUID\n *\n * // After streaming, the active conversation is auto-tracked\n * const stream = thaliq.agent.stream('Hello', { conversationId: conv.id });\n * for await (const event of stream) { ... }\n *\n * console.log(thaliq.conversations.active); // conv.id\n * ```\n */\n\nimport type { ConversationRef } from '../types/conversations';\nimport { uuid } from '../utils/uuid';\n\nexport class ConversationManager {\n private _active: ConversationRef | null = null;\n private readonly _history: ConversationRef[] = [];\n\n /** Create a new conversation reference */\n create(): ConversationRef {\n const ref: ConversationRef = {\n id: uuid(),\n createdAt: new Date(),\n };\n this._history.push(ref);\n return ref;\n }\n\n /** Get the most recently active conversation */\n get active(): ConversationRef | null {\n return this._active;\n }\n\n /** Get all known conversation references (in-memory only) */\n get history(): readonly ConversationRef[] {\n return this._history;\n }\n\n /**\n * Set the active conversation by ID (called internally after stream completes).\n * If the ID matches an existing ref, that ref becomes active.\n * Otherwise a new ref is created.\n */\n setActive(conversationId: string): void {\n const existing = this._history.find(c => c.id === conversationId);\n if (existing) {\n this._active = existing;\n } else {\n const ref: ConversationRef = {\n id: conversationId,\n createdAt: new Date(),\n };\n this._history.push(ref);\n this._active = ref;\n }\n }\n\n /** Clear all state */\n clear(): void {\n this._active = null;\n this._history.length = 0;\n }\n}\n","/**\n * Generate a UUID v4 using crypto.randomUUID when available,\n * falling back to a manual implementation.\n */\nexport function uuid(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n\n // Fallback for environments without crypto.randomUUID\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n","/**\n * HTTP client wrapper for the Thaliq Native Provider.\n *\n * Handles fetch with timeout via AbortController,\n * error mapping from HTTP status codes, and response parsing.\n */\n\nimport {\n mapHttpError,\n TimeoutError,\n ConnectionError,\n} from '../../types/errors';\nimport type { Logger } from '../../types/config';\n\nexport interface HttpClientConfig {\n baseUrl: string;\n timeout: number;\n logger: Logger;\n}\n\nexport interface HttpRequestOptions {\n method: 'GET' | 'POST';\n path: string;\n headers: Record<string, string | undefined>;\n body?: unknown;\n signal?: AbortSignal;\n timeout: number;\n}\n\nexport class HttpClient {\n private readonly baseUrl: string;\n private readonly defaultTimeout: number;\n private readonly logger: Logger;\n\n constructor(config: HttpClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/+$/, '');\n this.defaultTimeout = config.timeout;\n this.logger = config.logger;\n }\n\n /** Execute a JSON request and return the parsed response */\n async json<T>(options: HttpRequestOptions): Promise<T> {\n const response = await this.rawFetch(options);\n\n if (!response.ok) {\n const body = await response.text().catch(() => 'Unknown error');\n let message: string;\n try {\n const parsed = JSON.parse(body);\n message = parsed.message ?? parsed.error ?? body;\n } catch {\n message = body;\n }\n throw mapHttpError(response.status, message, response.headers);\n }\n\n return response.json() as Promise<T>;\n }\n\n /** Execute a request and return the raw Response (for SSE streaming) */\n async stream(options: HttpRequestOptions): Promise<Response> {\n const response = await this.rawFetch(options);\n\n if (!response.ok) {\n const body = await response.text().catch(() => 'Unknown error');\n let message: string;\n try {\n const parsed = JSON.parse(body);\n message = parsed.message ?? parsed.error ?? body;\n } catch {\n message = body;\n }\n throw mapHttpError(response.status, message, response.headers);\n }\n\n return response;\n }\n\n /** Low-level fetch with timeout and error wrapping */\n private async rawFetch(options: HttpRequestOptions): Promise<Response> {\n const url = `${this.baseUrl}${options.path}`;\n const timeout = options.timeout ?? this.defaultTimeout;\n\n // Create a timeout controller that will abort if no external signal is provided\n const timeoutController = new AbortController();\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n // If the caller provided an AbortSignal, listen to it\n if (options.signal) {\n options.signal.addEventListener('abort', () => timeoutController.abort(options.signal?.reason), {\n once: true,\n });\n }\n\n timeoutId = setTimeout(() => {\n timeoutController.abort(new TimeoutError(`Request timed out after ${timeout}ms`));\n }, timeout);\n\n // Clean up headers: remove undefined values\n const headers: Record<string, string> = { 'content-type': 'application/json' };\n for (const [key, value] of Object.entries(options.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n\n this.logger.debug(`${options.method} ${url}`);\n\n try {\n const response = await fetch(url, {\n method: options.method,\n headers,\n body: options.body ? JSON.stringify(options.body) : undefined,\n signal: timeoutController.signal,\n });\n\n return response;\n } catch (error: unknown) {\n if (error instanceof TimeoutError) throw error;\n if (error instanceof DOMException && error.name === 'AbortError') {\n // Check if it was a timeout or user abort\n if (timeoutController.signal.reason instanceof TimeoutError) {\n throw timeoutController.signal.reason;\n }\n throw error;\n }\n throw new ConnectionError(\n error instanceof Error ? error.message : 'Connection failed',\n );\n } finally {\n if (timeoutId !== undefined) clearTimeout(timeoutId);\n }\n }\n}\n","/**\n * SSE (Server-Sent Events) parser.\n *\n * Converts a ReadableStream<Uint8Array> into an AsyncIterable of parsed SSE events.\n * Follows the SSE spec: each event is delimited by a blank line,\n * and fields are `event:`, `data:`, `id:`.\n */\n\nimport type { StreamEvent } from '../../types/events';\nimport type { PendingAction } from '../../types/actions';\n\ninterface RawSSEEvent {\n event: string;\n data: string;\n id: string;\n}\n\n/**\n * Parse a ReadableStream into SSE events.\n * Yields StreamEvent objects as they arrive.\n */\nexport async function* parseSSEStream(\n stream: ReadableStream<Uint8Array>,\n): AsyncIterable<StreamEvent> {\n const reader = stream.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n\n // Split on double newlines (SSE event delimiter)\n const parts = buffer.split('\\n\\n');\n // Keep the last part as buffer (may be incomplete)\n buffer = parts.pop() ?? '';\n\n for (const part of parts) {\n const raw = parseRawEvent(part);\n if (!raw) continue;\n\n const mapped = mapToStreamEvent(raw);\n if (mapped) yield mapped;\n }\n }\n\n // Process any remaining buffer\n if (buffer.trim()) {\n const raw = parseRawEvent(buffer);\n if (raw) {\n const mapped = mapToStreamEvent(raw);\n if (mapped) yield mapped;\n }\n }\n } finally {\n reader.releaseLock();\n }\n}\n\n/** Parse raw SSE text block into event/data/id fields */\nfunction parseRawEvent(block: string): RawSSEEvent | null {\n let event = '';\n let data = '';\n let id = '';\n\n const lines = block.split('\\n');\n for (const line of lines) {\n if (line.startsWith('event:')) {\n event = line.slice(6).trim();\n } else if (line.startsWith('data:')) {\n data = line.slice(5).trim();\n } else if (line.startsWith('id:')) {\n id = line.slice(3).trim();\n }\n // Lines starting with ':' are comments, ignored\n }\n\n if (!event && !data) return null;\n\n return { event, data, id };\n}\n\n/** Map a raw SSE event to a typed StreamEvent */\nfunction mapToStreamEvent(raw: RawSSEEvent): StreamEvent | null {\n const type = raw.event;\n\n try {\n const payload = raw.data ? JSON.parse(raw.data) : {};\n\n switch (type) {\n case 'meta':\n return {\n type: 'meta',\n conversationId: payload.conversationId,\n };\n\n case 'status':\n return {\n type: 'status',\n text: payload.text,\n };\n\n case 'content.delta':\n return {\n type: 'content.delta',\n delta: payload.delta,\n };\n\n case 'tool.start':\n return {\n type: 'tool.start',\n tool: payload.tool,\n };\n\n case 'tool.end':\n return {\n type: 'tool.end',\n tool: payload.tool,\n success: payload.success,\n };\n\n case 'action':\n return {\n type: 'action',\n action: payload as PendingAction,\n };\n\n case 'response.completed':\n return {\n type: 'response.completed',\n message: payload.message,\n conversationId: payload.conversationId,\n insights: payload.insights ?? [],\n metadata: payload.metadata,\n };\n\n case 'error':\n return {\n type: 'error',\n message: payload.message,\n };\n\n case 'keepalive':\n return {\n type: 'keepalive',\n ts: payload.ts,\n };\n\n default:\n // Unknown event type — skip\n return null;\n }\n } catch {\n // Malformed JSON — skip\n return null;\n }\n}\n","/**\n * ThaliqNativeProvider — Default provider that communicates with the Thaliq API.\n *\n * - chat() → POST /api/agent/chat\n * - stream() → GET /api/agent/stream (SSE)\n */\n\nimport type { Provider, ProviderRequest } from '../../types/provider';\nimport type { ChatResponse } from '../../types/responses';\nimport type { StreamEvent } from '../../types/events';\nimport type { Logger } from '../../types/config';\nimport { StreamError } from '../../types/errors';\nimport { HttpClient } from './http-client';\nimport { parseSSEStream } from './sse-parser';\n\nexport interface ThaliqNativeProviderConfig {\n baseUrl: string;\n timeout: number;\n logger: Logger;\n}\n\nexport class ThaliqNativeProvider implements Provider {\n readonly name = 'thaliq-native';\n private readonly http: HttpClient;\n private readonly logger: Logger;\n\n constructor(config: ThaliqNativeProviderConfig) {\n this.logger = config.logger;\n this.http = new HttpClient({\n baseUrl: config.baseUrl,\n timeout: config.timeout,\n logger: config.logger,\n });\n }\n\n /** POST /api/agent/chat — non-streaming */\n async chat(request: ProviderRequest): Promise<ChatResponse> {\n const body: Record<string, unknown> = {\n message: request.message,\n };\n\n if (request.conversationId) body['conversationId'] = request.conversationId;\n if (request.agentType) body['agentType'] = request.agentType;\n if (request.actionResponse) body['actionResponse'] = request.actionResponse;\n\n return this.http.json<ChatResponse>({\n method: 'POST',\n path: '/api/agent/chat',\n headers: request.headers,\n body,\n signal: request.signal,\n timeout: request.timeout,\n });\n }\n\n /** GET /api/agent/stream — SSE streaming */\n async *stream(request: ProviderRequest): AsyncIterable<StreamEvent> {\n // Build query string\n const params = new URLSearchParams();\n params.set('q', request.message);\n if (request.conversationId) params.set('conversationId', request.conversationId);\n if (request.agentType) params.set('agentType', request.agentType);\n if (request.actionResponse) {\n params.set('actionResponse', JSON.stringify(request.actionResponse));\n }\n\n const response = await this.http.stream({\n method: 'GET',\n path: `/api/agent/stream?${params.toString()}`,\n headers: {\n ...request.headers,\n accept: 'text/event-stream',\n },\n signal: request.signal,\n timeout: request.timeout,\n });\n\n if (!response.body) {\n throw new StreamError('Response body is null — streaming not supported');\n }\n\n this.logger.debug('SSE stream connected');\n\n yield* parseSSEStream(response.body);\n }\n}\n","/**\n * Typed EventEmitter — zero-dependency, type-safe event system.\n *\n * @example\n * ```typescript\n * const emitter = new TypedEventEmitter<SDKEventMap>();\n * emitter.on('error', (err) => console.error(err));\n * emitter.once('identify', (userId) => console.log('Identified:', userId));\n * ```\n */\n\n/** Callback function type */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype Callback = (...args: any[]) => void;\n\n/** Typed listener with optional _once flag */\ntype Listener = Callback & { _once?: boolean };\n\nexport class TypedEventEmitter<T extends { [K in keyof T]: Callback }> {\n private readonly _listeners = new Map<keyof T, Set<Listener>>();\n\n /** Register a listener for an event */\n on<K extends keyof T>(event: K, listener: T[K]): this {\n if (!this._listeners.has(event)) {\n this._listeners.set(event, new Set());\n }\n this._listeners.get(event)!.add(listener as Listener);\n return this;\n }\n\n /** Register a one-time listener */\n once<K extends keyof T>(event: K, listener: T[K]): this {\n const wrapped = listener as Listener;\n wrapped._once = true;\n return this.on(event, listener);\n }\n\n /** Remove a listener */\n off<K extends keyof T>(event: K, listener: T[K]): this {\n const set = this._listeners.get(event);\n if (set) {\n set.delete(listener as Listener);\n if (set.size === 0) {\n this._listeners.delete(event);\n }\n }\n return this;\n }\n\n /** Emit an event to all registered listeners */\n emit<K extends keyof T>(event: K, ...args: Parameters<T[K]>): void {\n const set = this._listeners.get(event);\n if (!set) return;\n\n for (const listener of set) {\n listener(...args);\n if (listener._once) {\n set.delete(listener);\n }\n }\n\n if (set.size === 0) {\n this._listeners.delete(event);\n }\n }\n\n /** Remove all listeners for an event, or all listeners if no event specified */\n removeAllListeners(event?: keyof T): this {\n if (event) {\n this._listeners.delete(event);\n } else {\n this._listeners.clear();\n }\n return this;\n }\n\n /** Get the count of listeners for a specific event */\n listenerCount(event: keyof T): number {\n return this._listeners.get(event)?.size ?? 0;\n }\n}\n","/**\n * Default console-based logger with level filtering.\n */\n\nimport type { Logger, LogLevel } from '../types/config';\n\nconst LEVEL_ORDER: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n silent: 4,\n};\n\nexport function createDefaultLogger(minLevel: LogLevel): Logger {\n const min = LEVEL_ORDER[minLevel];\n\n return {\n debug(message: string, ...args: unknown[]) {\n if (min <= LEVEL_ORDER.debug) console.debug(`[thaliq] ${message}`, ...args);\n },\n info(message: string, ...args: unknown[]) {\n if (min <= LEVEL_ORDER.info) console.info(`[thaliq] ${message}`, ...args);\n },\n warn(message: string, ...args: unknown[]) {\n if (min <= LEVEL_ORDER.warn) console.warn(`[thaliq] ${message}`, ...args);\n },\n error(message: string, ...args: unknown[]) {\n if (min <= LEVEL_ORDER.error) console.error(`[thaliq] ${message}`, ...args);\n },\n };\n}\n","/**\n * Thaliq — Main SDK client class.\n *\n * @example\n * ```typescript\n * import { Thaliq } from '@thaliq/sdk';\n *\n * const thaliq = new Thaliq({ apiKey: 'tq_live_xxx' });\n *\n * // Events\n * thaliq.on('error', (err) => console.error(err));\n * thaliq.on('retry', (attempt, err, delay) => console.warn(`Retry #${attempt}`));\n *\n * // Identify user (B2B)\n * thaliq.identify({ userId: 'usr_123', email: 'user@company.com' });\n *\n * // Chat\n * const response = await thaliq.agent.chat('Hello!');\n *\n * // Stream\n * const stream = thaliq.agent.stream('Analyze Q4 sales');\n * for await (const event of stream) {\n * if (event.type === 'content.delta') process.stdout.write(event.delta);\n * }\n *\n * // Conversations are auto-tracked\n * console.log(thaliq.conversations.active);\n * ```\n */\n\nimport type { ThaliqConfig, ResolvedConfig, SDKEventMap } from './types/config';\nimport type { UserIdentity } from './types/identity';\nimport type { Provider } from './types/provider';\nimport { ValidationError } from './types/errors';\nimport { AgentClient } from './agent/agent-client';\nimport { ConversationManager } from './agent/conversation-manager';\nimport { ThaliqNativeProvider } from './providers/thaliq-native';\nimport { TypedEventEmitter } from './utils/event-emitter';\nimport { createDefaultLogger } from './utils/logger';\n\nconst DEFAULT_BASE_URL = 'https://api.thaliq.com';\nconst DEFAULT_TIMEOUT = 30_000;\nconst DEFAULT_MAX_RETRIES = 2;\nconst DEFAULT_BASE_DELAY = 500;\nconst DEFAULT_MAX_DELAY = 10_000;\n\nexport class Thaliq {\n private readonly config: ResolvedConfig;\n private readonly provider: Provider;\n private readonly emitter = new TypedEventEmitter<SDKEventMap>();\n private identity: UserIdentity | null = null;\n\n /** Agent client — use `thaliq.agent.chat()` and `thaliq.agent.stream()` */\n readonly agent: AgentClient;\n\n /** Conversations manager — create, track, and list conversations */\n readonly conversations: ConversationManager;\n\n constructor(userConfig: ThaliqConfig) {\n this.config = resolveConfig(userConfig);\n this.provider = userConfig.provider ?? new ThaliqNativeProvider({\n baseUrl: this.config.baseUrl,\n timeout: this.config.timeout,\n logger: this.config.logger,\n });\n\n this.conversations = new ConversationManager();\n\n this.agent = new AgentClient(\n this.config,\n this.provider,\n () => this.identity,\n this.emitter,\n this.conversations,\n );\n }\n\n /** Register an event listener */\n on<K extends keyof SDKEventMap>(event: K, listener: SDKEventMap[K]): this {\n this.emitter.on(event, listener);\n return this;\n }\n\n /** Register a one-time event listener */\n once<K extends keyof SDKEventMap>(event: K, listener: SDKEventMap[K]): this {\n this.emitter.once(event, listener);\n return this;\n }\n\n /** Remove an event listener */\n off<K extends keyof SDKEventMap>(event: K, listener: SDKEventMap[K]): this {\n this.emitter.off(event, listener);\n return this;\n }\n\n /** Set the user identity for subsequent requests */\n identify(user: UserIdentity): void {\n if (!user.userId) {\n throw new ValidationError('userId is required for identify()');\n }\n this.identity = user;\n this.config.logger.info(`User identified: ${user.userId}`);\n this.emitter.emit('identify', user.userId);\n }\n\n /** Clear user identity and local state */\n reset(): void {\n this.identity = null;\n this.conversations.clear();\n this.config.logger.info('SDK state reset');\n this.emitter.emit('reset');\n }\n}\n\n/** Merge user config with defaults */\nfunction resolveConfig(config: ThaliqConfig): ResolvedConfig {\n if (!config.apiKey) {\n throw new ValidationError('apiKey is required');\n }\n\n const logLevel = config.logLevel ?? 'warn';\n const logger = config.logger ?? createDefaultLogger(logLevel);\n const maxRetries = config.maxRetries ?? config.retry?.maxRetries ?? DEFAULT_MAX_RETRIES;\n\n return {\n apiKey: config.apiKey,\n baseUrl: (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, ''),\n integrationType: config.integrationType ?? 'sdk',\n timeout: config.timeout ?? DEFAULT_TIMEOUT,\n maxRetries,\n retry: {\n maxRetries,\n baseDelay: config.retry?.baseDelay ?? DEFAULT_BASE_DELAY,\n maxDelay: config.retry?.maxDelay ?? DEFAULT_MAX_DELAY,\n },\n logger,\n logLevel,\n defaultHeaders: config.defaultHeaders ?? {},\n };\n}\n","/**\n * ActionResponseBuilder — helpers for constructing ActionResponse objects.\n *\n * Provides static factory methods for each HITL action type,\n * so developers don't need to manually build ActionResponse objects.\n *\n * @example\n * ```typescript\n * import { ActionResponseBuilder } from '@thaliq/sdk';\n *\n * // Accept a consent/confirm action\n * const accept = ActionResponseBuilder.accept('inst_123');\n *\n * // Reject an action\n * const reject = ActionResponseBuilder.reject('inst_123');\n *\n * // Select an option\n * const select = ActionResponseBuilder.select('inst_123', 'option_a');\n *\n * // Submit a form\n * const form = ActionResponseBuilder.submitForm('inst_123', {\n * amount: '500',\n * currency: 'USD',\n * });\n * ```\n */\n\nimport type { ActionResponse } from '../types/actions';\n\nexport class ActionResponseBuilder {\n /**\n * Accept a consent or confirm action.\n *\n * @param instructionId - The instruction ID from `pendingAction.instructionId`\n */\n static accept(instructionId: string): ActionResponse {\n return { instructionId, accepted: true };\n }\n\n /**\n * Reject a consent or confirm action.\n *\n * @param instructionId - The instruction ID from `pendingAction.instructionId`\n */\n static reject(instructionId: string): ActionResponse {\n return { instructionId, accepted: false };\n }\n\n /**\n * Select an option from a select action.\n *\n * @param instructionId - The instruction ID from `pendingAction.instructionId`\n * @param value - The selected option value\n */\n static select(instructionId: string, value: string): ActionResponse {\n return { instructionId, accepted: true, selectedValue: value };\n }\n\n /**\n * Submit form values for a form action.\n *\n * @param instructionId - The instruction ID from `pendingAction.instructionId`\n * @param values - Key-value map of form field names to values\n */\n static submitForm(instructionId: string, values: Record<string, string>): ActionResponse {\n return { instructionId, accepted: true, formValues: values };\n }\n}\n"],"names":["ThaliqError","Error","constructor","message","code","status","super","this","name","AuthError","RateLimitError","retryAfter","ValidationError","ServiceError","StreamError","TimeoutError","ConnectionError","mapHttpError","headers","get","parseInt","AgentStreamImpl","source","abortController","onEvent","onComplete","_conversationId","_status","_pendingAction","_consumed","_source","_abortController","_onEvent","_onComplete","conversationId","pendingAction","abort","Symbol","asyncIterator","event","type","action","finalResponse","metadata","insights","delta","response","model","promptTokens","completionTokens","processingTimeMs","generatedAt","Date","toISOString","text","accumulated","isRetryableError","error","calculateBackoff","attempt","baseDelay","maxDelay","exponential","Math","pow","clamped","min","jitter","random","floor","sleep","ms","Promise","resolve","setTimeout","async","withRetry","fn","options","config","logger","onRetry","signal","lastError","maxRetries","aborted","delayMs","warn","AgentClient","provider","getIdentity","emitter","conversationManager","chat","request","buildRequest","retry","emit","setActive","stream","AbortController","err","respondToAction","originalMessage","agentType","actionResponse","abortSignal","identity","resolveHeaders","timeout","apiKey","integrationType","userId","participantId","token","mcpTokens","Object","keys","length","JSON","stringify","key","value","entries","defaultHeaders","ConversationManager","_active","_history","create","ref","id","crypto","randomUUID","replace","c","r","toString","createdAt","push","active","history","existing","find","clear","HttpClient","baseUrl","defaultTimeout","json","rawFetch","ok","body","catch","parsed","parse","url","path","timeoutController","timeoutId","addEventListener","reason","once","debug","method","fetch","DOMException","clearTimeout","parseRawEvent","block","data","lines","split","line","startsWith","slice","trim","mapToStreamEvent","raw","payload","tool","success","ts","ThaliqNativeProvider","http","params","URLSearchParams","set","accept","reader","getReader","decoder","TextDecoder","buffer","done","read","decode","parts","pop","part","mapped","releaseLock","parseSSEStream","TypedEventEmitter","_listeners","Map","on","listener","has","Set","add","_once","off","delete","size","args","removeAllListeners","listenerCount","LEVEL_ORDER","info","silent","DEFAULT_BASE_URL","Thaliq","userConfig","logLevel","minLevel","console","createDefaultLogger","resolveConfig","conversations","agent","identify","user","reset","ActionResponseBuilder","instructionId","accepted","reject","select","selectedValue","submitForm","values","formValues"],"mappings":"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"}
1
+ {"version":3,"file":"thaliq-sdk.es.js","sources":["../../../libs/sdk/src/types/errors.ts","../../../libs/sdk/src/agent/agent-stream.ts","../../../libs/sdk/src/utils/retry.ts","../../../libs/sdk/src/agent/agent-client.ts","../../../libs/sdk/src/agent/conversation-manager.ts","../../../libs/sdk/src/utils/uuid.ts","../../../libs/sdk/src/providers/thaliq-native/http-client.ts","../../../libs/sdk/src/providers/thaliq-native/sse-parser.ts","../../../libs/sdk/src/providers/thaliq-native/thaliq-native.provider.ts","../../../libs/sdk/src/utils/event-emitter.ts","../../../libs/sdk/src/utils/logger.ts","../../../libs/sdk/src/client.ts","../../../libs/sdk/src/utils/action-response-builder.ts"],"sourcesContent":["/**\n * @thaliq/sdk - Error Types\n * @module types/errors\n */\n\n/**\n * SDK error codes used in `ThaliqError.code`.\n * Use these to programmatically distinguish error types.\n */\nexport type ErrorCode =\n | 'AUTH_ERROR'\n | 'RATE_LIMIT'\n | 'VALIDATION_ERROR'\n | 'SERVICE_ERROR'\n | 'STREAM_ERROR'\n | 'TIMEOUT_ERROR'\n | 'CONNECTION_ERROR'\n | 'UNKNOWN_ERROR';\n\n/** Base error class for all SDK errors */\nexport class ThaliqError extends Error {\n readonly code: ErrorCode;\n readonly status?: number;\n\n constructor(message: string, code: ErrorCode, status?: number) {\n super(message);\n this.name = 'ThaliqError';\n this.code = code;\n this.status = status;\n }\n}\n\n/** Authentication or authorization error (401/403) */\nexport class AuthError extends ThaliqError {\n constructor(message: string, status: number = 401) {\n super(message, 'AUTH_ERROR', status);\n this.name = 'AuthError';\n }\n}\n\n/** Rate limit exceeded (429) */\nexport class RateLimitError extends ThaliqError {\n readonly retryAfter: number;\n\n constructor(message: string, retryAfter: number = 60) {\n super(message, 'RATE_LIMIT', 429);\n this.name = 'RateLimitError';\n this.retryAfter = retryAfter;\n }\n}\n\n/** Request validation error (400) */\nexport class ValidationError extends ThaliqError {\n constructor(message: string) {\n super(message, 'VALIDATION_ERROR', 400);\n this.name = 'ValidationError';\n }\n}\n\n/** Service unavailable (503) */\nexport class ServiceError extends ThaliqError {\n constructor(message: string) {\n super(message, 'SERVICE_ERROR', 503);\n this.name = 'ServiceError';\n }\n}\n\n/** Error during SSE streaming */\nexport class StreamError extends ThaliqError {\n constructor(message: string) {\n super(message, 'STREAM_ERROR');\n this.name = 'StreamError';\n }\n}\n\n/** Request timeout */\nexport class TimeoutError extends ThaliqError {\n constructor(message: string = 'Request timed out') {\n super(message, 'TIMEOUT_ERROR');\n this.name = 'TimeoutError';\n }\n}\n\n/** Network/connection error */\nexport class ConnectionError extends ThaliqError {\n constructor(message: string = 'Connection failed') {\n super(message, 'CONNECTION_ERROR');\n this.name = 'ConnectionError';\n }\n}\n\n/**\n * Maps an HTTP status code to the appropriate ThaliqError subclass.\n * Used internally by the HTTP client; also useful for custom providers.\n */\nexport function mapHttpError(status: number, message: string, headers?: Headers): ThaliqError {\n switch (status) {\n case 400:\n return new ValidationError(message);\n case 401:\n case 403:\n return new AuthError(message, status);\n case 429: {\n const retryAfter = headers?.get('retry-after');\n return new RateLimitError(message, retryAfter ? parseInt(retryAfter, 10) : 60);\n }\n case 503:\n return new ServiceError(message);\n default:\n return new ThaliqError(message, 'UNKNOWN_ERROR', status);\n }\n}\n","/**\n * AgentStream — AsyncIterable wrapper over SSE events.\n *\n * Provides convenient access to the conversation ID, abort,\n * and methods to accumulate the final response or text.\n */\n\nimport type { AgentStream as IAgentStream, StreamStatus } from '../types/agent';\nimport type { StreamEvent } from '../types/events';\nimport type { ChatResponse } from '../types/responses';\nimport type { Insight, ResponseMetadata } from '../types/responses';\nimport type { PendingAction } from '../types/actions';\nimport { StreamError } from '../types/errors';\n\nexport class AgentStreamImpl implements IAgentStream {\n private _conversationId: string | null = null;\n private _status: StreamStatus = 'streaming';\n private _pendingAction: PendingAction | null = null;\n private readonly _source: AsyncIterable<StreamEvent>;\n private readonly _abortController: AbortController;\n private readonly _onEvent?: (event: StreamEvent) => void;\n private readonly _onComplete?: (conversationId: string | null, status: StreamStatus) => void;\n private _consumed = false;\n\n constructor(\n source: AsyncIterable<StreamEvent>,\n abortController: AbortController,\n onEvent?: (event: StreamEvent) => void,\n onComplete?: (conversationId: string | null, status: StreamStatus) => void,\n ) {\n this._source = source;\n this._abortController = abortController;\n this._onEvent = onEvent;\n this._onComplete = onComplete;\n }\n\n get conversationId(): string | null {\n return this._conversationId;\n }\n\n get status(): StreamStatus {\n return this._status;\n }\n\n get pendingAction(): PendingAction | null {\n return this._pendingAction;\n }\n\n abort(): void {\n this._status = 'aborted';\n this._abortController.abort();\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<StreamEvent> {\n if (this._consumed) {\n throw new StreamError('AgentStream can only be consumed once');\n }\n this._consumed = true;\n\n try {\n for await (const event of this._source) {\n // Track conversation ID from meta event\n if (event.type === 'meta') {\n this._conversationId = event.conversationId;\n }\n\n // Also track from response.completed\n if (event.type === 'response.completed' && !this._conversationId) {\n this._conversationId = event.conversationId;\n }\n\n // Track action events — stream is awaiting user response\n if (event.type === 'action') {\n this._pendingAction = event.action;\n this._status = 'awaiting_action';\n }\n\n // Track handoff — conversation escalated to human agent\n if (event.type === 'handoff') {\n this._status = 'handoff';\n }\n\n // Track completion\n if (event.type === 'response.completed') {\n this._status = 'completed';\n }\n\n // Track errors\n if (event.type === 'error') {\n this._status = 'error';\n }\n\n // Fire optional callback\n if (this._onEvent) {\n this._onEvent(event);\n }\n\n yield event;\n }\n\n // If stream ended naturally without explicit status, mark completed\n if (this._status === 'streaming') {\n this._status = this._pendingAction ? 'awaiting_action' : 'completed';\n }\n } finally {\n // Notify completion regardless of how stream ended\n if (this._onComplete) {\n this._onComplete(this._conversationId, this._status);\n }\n }\n }\n\n async finalResponse(): Promise<ChatResponse> {\n let message = '';\n let conversationId = '';\n let insights: Insight[] = [];\n let metadata: ResponseMetadata | undefined;\n let action: PendingAction | undefined;\n\n for await (const event of this) {\n switch (event.type) {\n case 'meta':\n conversationId = event.conversationId;\n break;\n case 'content.delta':\n message += event.delta;\n break;\n case 'action':\n action = event.action;\n break;\n case 'response.completed':\n message = event.message;\n conversationId = event.conversationId;\n insights = event.insights;\n metadata = event.metadata;\n break;\n case 'error':\n throw new StreamError(event.message);\n }\n }\n\n const response: ChatResponse = {\n message,\n conversationId,\n insights,\n metadata: metadata ?? {\n conversationId,\n model: 'unknown',\n promptTokens: 0,\n completionTokens: 0,\n processingTimeMs: 0,\n generatedAt: new Date().toISOString(),\n },\n };\n\n if (action) {\n response.action = action;\n }\n\n return response;\n }\n\n async text(): Promise<string> {\n let accumulated = '';\n\n for await (const event of this) {\n if (event.type === 'content.delta') {\n accumulated += event.delta;\n }\n if (event.type === 'response.completed') {\n return event.message;\n }\n if (event.type === 'error') {\n throw new StreamError(event.message);\n }\n }\n\n return accumulated;\n }\n}\n","/**\n * Retry logic with exponential backoff and jitter.\n *\n * Retries on server errors (500/502/503/504) and network errors.\n * Never retries on client errors (400/401/403/429).\n */\n\nimport type { ResolvedRetryConfig, Logger } from '../types/config';\nimport {\n ThaliqError,\n RateLimitError,\n AuthError,\n ValidationError,\n TimeoutError,\n ConnectionError,\n ServiceError,\n} from '../types/errors';\n\n/**\n * Check if an error is retryable.\n * Returns `true` for server errors (5xx), timeouts, and connection errors.\n * Returns `false` for auth errors (401/403), validation (400), and rate limits (429).\n */\nexport function isRetryableError(error: unknown): boolean {\n if (!(error instanceof ThaliqError)) {\n // Unknown errors (network failures, etc.) are retryable\n return true;\n }\n\n // Never retry client errors\n if (error instanceof AuthError) return false;\n if (error instanceof ValidationError) return false;\n if (error instanceof RateLimitError) return false;\n\n // Retry server errors and connection issues\n if (error instanceof ServiceError) return true;\n if (error instanceof ConnectionError) return true;\n if (error instanceof TimeoutError) return true;\n\n // Retry 5xx status codes\n if (error.status && error.status >= 500) return true;\n\n return false;\n}\n\n/**\n * Calculate the retry delay with exponential backoff and jitter.\n * Formula: `min(baseDelay * 2^attempt, maxDelay) + random(0..50%)`.\n */\nexport function calculateBackoff(\n attempt: number,\n baseDelay: number,\n maxDelay: number,\n): number {\n // Exponential: baseDelay * 2^attempt\n const exponential = baseDelay * Math.pow(2, attempt);\n // Clamp to maxDelay\n const clamped = Math.min(exponential, maxDelay);\n // Add jitter: random 0-50% of the delay\n const jitter = clamped * Math.random() * 0.5;\n return Math.floor(clamped + jitter);\n}\n\n/** Sleep for a given number of milliseconds */\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/** Options for the retry wrapper */\nexport interface RetryOptions {\n config: ResolvedRetryConfig;\n logger: Logger;\n /** Called before each retry attempt */\n onRetry?: (attempt: number, error: ThaliqError, delayMs: number) => void;\n /** AbortSignal to cancel retries */\n signal?: AbortSignal;\n}\n\n/**\n * Execute an async function with automatic retry on retryable errors.\n * Uses exponential backoff with jitter between attempts.\n *\n * @param fn - The async function to execute (and potentially retry)\n * @param options - Retry configuration, logger, and optional callbacks\n * @returns The result of `fn()` on success\n * @throws The last error after all retries are exhausted\n */\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n options: RetryOptions,\n): Promise<T> {\n const { config, logger, onRetry, signal } = options;\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= config.maxRetries; attempt++) {\n try {\n return await fn();\n } catch (error: unknown) {\n lastError = error;\n\n // Don't retry if we've exhausted attempts\n if (attempt >= config.maxRetries) break;\n\n // Don't retry non-retryable errors\n if (!isRetryableError(error)) break;\n\n // Don't retry if aborted\n if (signal?.aborted) break;\n\n const delayMs = calculateBackoff(attempt, config.baseDelay, config.maxDelay);\n\n logger.warn(\n `Retry ${attempt + 1}/${config.maxRetries} after ${delayMs}ms`,\n error instanceof Error ? error.message : error,\n );\n\n if (onRetry && error instanceof ThaliqError) {\n onRetry(attempt + 1, error, delayMs);\n }\n\n await sleep(delayMs);\n }\n }\n\n throw lastError;\n}\n","/**\n * AgentClient — main interface for interacting with agents.\n *\n * Accessed via `thaliq.agent.chat()` and `thaliq.agent.stream()`.\n * Includes automatic retry with exponential backoff for chat requests.\n */\n\nimport type { Provider, ProviderRequest, ResolvedHeaders } from '../types/provider';\nimport type { ChatOptions, StreamOptions, AgentStream, RespondToActionOptions, StreamStatus } from '../types/agent';\nimport type { ChatResponse, MessageFeedback } from '../types/responses';\nimport type { UserIdentity } from '../types/identity';\nimport type { ResolvedConfig, SDKEventMap } from '../types/config';\nimport type { TypedEventEmitter } from '../utils/event-emitter';\nimport type { ConversationManager } from './conversation-manager';\nimport { RateLimitError, ThaliqError } from '../types/errors';\nimport { AgentStreamImpl } from './agent-stream';\nimport { withRetry } from '../utils/retry';\n\n/** Options for submitting feedback */\nexport interface FeedbackOptions {\n /** Conversation ID */\n conversationId: string;\n /** Message ID (from ResponseMetadata.messageId) */\n messageId: string;\n /** Feedback value */\n feedback: MessageFeedback;\n}\n\nexport class AgentClient {\n private readonly config: ResolvedConfig;\n private readonly provider: Provider;\n private readonly getIdentity: () => UserIdentity | null;\n private readonly emitter: TypedEventEmitter<SDKEventMap>;\n private readonly conversationManager: ConversationManager;\n\n constructor(\n config: ResolvedConfig,\n provider: Provider,\n getIdentity: () => UserIdentity | null,\n emitter: TypedEventEmitter<SDKEventMap>,\n conversationManager: ConversationManager,\n ) {\n this.config = config;\n this.provider = provider;\n this.getIdentity = getIdentity;\n this.emitter = emitter;\n this.conversationManager = conversationManager;\n }\n\n /** Send a message and wait for the complete response (with automatic retry) */\n async chat(message: string, options?: ChatOptions): Promise<ChatResponse> {\n const request = this.buildRequest(message, options);\n\n const response = await withRetry(\n () => this.provider.chat(request),\n {\n config: this.config.retry,\n logger: this.config.logger,\n signal: options?.signal,\n onRetry: (attempt, error, delayMs) => {\n this.emitter.emit('retry', attempt, error, delayMs);\n },\n },\n );\n\n // Auto-track conversation\n if (response.conversationId) {\n this.conversationManager.setActive(response.conversationId);\n }\n\n return response;\n }\n\n /** Send a message with streaming — returns an AgentStream */\n stream(message: string, options?: StreamOptions): AgentStream {\n const abortController = new AbortController();\n const request = this.buildRequest(message, options, abortController.signal);\n\n // The provider returns an AsyncIterable<StreamEvent>\n const source = this.provider.stream(request);\n\n // Emit stream.start\n this.emitter.emit('stream.start', options?.conversationId ?? null);\n\n const stream = new AgentStreamImpl(\n source,\n abortController,\n (event) => {\n // Auto-track conversation from meta event\n if (event.type === 'meta' && event.conversationId) {\n this.conversationManager.setActive(event.conversationId);\n }\n\n // Emit error/rateLimit events\n if (event.type === 'error') {\n const err = new ThaliqError(event.message, 'STREAM_ERROR');\n this.emitter.emit('error', err);\n }\n\n // Forward to user callback\n if (options?.onEvent) {\n options.onEvent(event);\n }\n },\n // onComplete callback for stream.end event\n (conversationId) => {\n this.emitter.emit('stream.end', conversationId);\n },\n );\n\n return stream;\n }\n\n /**\n * Respond to a pending HITL action and resume the conversation.\n *\n * This is a convenience method that creates a new stream with the\n * action response, continuing the conversation where it left off.\n *\n * @example\n * ```typescript\n * const stream = thaliq.agent.stream('Transfer $500');\n * for await (const event of stream) { ... }\n *\n * if (stream.pendingAction) {\n * const resumed = thaliq.agent.respondToAction({\n * conversationId: stream.conversationId!,\n * originalMessage: 'Transfer $500',\n * actionResponse: ActionResponseBuilder.accept(stream.pendingAction.instructionId),\n * });\n * for await (const event of resumed) { ... }\n * }\n * ```\n */\n respondToAction(options: RespondToActionOptions): AgentStream {\n return this.stream(options.originalMessage, {\n conversationId: options.conversationId,\n agentType: options.agentType,\n actionResponse: options.actionResponse,\n onEvent: options.onEvent,\n signal: options.signal,\n });\n }\n\n /**\n * Submit feedback (thumbs up/down) for an assistant message.\n *\n * @example\n * ```typescript\n * const response = await thaliq.agent.chat('Hello!');\n * await thaliq.agent.feedback({\n * conversationId: response.conversationId,\n * messageId: response.metadata.messageId!,\n * feedback: 'positive',\n * });\n * ```\n */\n async feedback(options: FeedbackOptions): Promise<void> {\n const identity = this.getIdentity();\n const headers = this.resolveHeaders(identity);\n\n const response = await fetch(`${this.config.baseUrl}/api/agent/feedback`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n 'x-api-key': headers['x-api-key'],\n 'x-integration-type': headers['x-integration-type'],\n ...(headers['x-user-id'] ? { 'x-user-id': headers['x-user-id'] } : {}),\n ...(headers['authorization'] ? { authorization: headers['authorization'] } : {}),\n },\n body: JSON.stringify({\n conversationId: options.conversationId,\n messageId: options.messageId,\n feedback: options.feedback,\n }),\n });\n\n if (!response.ok) {\n const text = await response.text().catch(() => `HTTP ${response.status}`);\n throw new ThaliqError(text, 'UNKNOWN_ERROR');\n }\n }\n\n /** Build the ProviderRequest from message + options + identity */\n private buildRequest(\n message: string,\n options?: ChatOptions,\n abortSignal?: AbortSignal,\n ): ProviderRequest {\n const identity = this.getIdentity();\n const signal = options?.signal ?? abortSignal;\n\n return {\n message,\n conversationId: options?.conversationId,\n agentType: options?.agentType,\n actionResponse: options?.actionResponse,\n headers: this.resolveHeaders(identity),\n signal,\n timeout: this.config.timeout,\n };\n }\n\n /** Resolve all headers from config + identity */\n private resolveHeaders(identity: UserIdentity | null): ResolvedHeaders {\n const headers: ResolvedHeaders = {\n 'x-api-key': this.config.apiKey,\n 'x-integration-type': this.config.integrationType,\n };\n\n // Identity headers\n if (identity) {\n if (identity.userId) {\n headers['x-user-id'] = identity.userId;\n }\n if (identity.participantId) {\n headers['x-participant-id'] = identity.participantId;\n }\n if (identity.token) {\n headers['authorization'] = `Bearer ${identity.token}`;\n }\n if (identity.mcpTokens && Object.keys(identity.mcpTokens).length > 0) {\n headers['x-mcp-tokens'] = JSON.stringify(identity.mcpTokens);\n }\n }\n\n // Custom default headers\n for (const [key, value] of Object.entries(this.config.defaultHeaders)) {\n headers[key] = value;\n }\n\n return headers;\n }\n}\n","/**\n * ConversationManager — tracks active conversations and auto-assigns IDs.\n *\n * @example\n * ```typescript\n * const conv = thaliq.conversations.create();\n * console.log(conv.id); // UUID\n *\n * // After streaming, the active conversation is auto-tracked\n * const stream = thaliq.agent.stream('Hello', { conversationId: conv.id });\n * for await (const event of stream) { ... }\n *\n * console.log(thaliq.conversations.active); // conv.id\n * ```\n */\n\nimport type { ConversationRef } from '../types/conversations';\nimport { uuid } from '../utils/uuid';\n\nexport class ConversationManager {\n private _active: ConversationRef | null = null;\n private readonly _history: ConversationRef[] = [];\n\n /** Create a new conversation reference */\n create(): ConversationRef {\n const ref: ConversationRef = {\n id: uuid(),\n createdAt: new Date(),\n };\n this._history.push(ref);\n return ref;\n }\n\n /** Get the most recently active conversation */\n get active(): ConversationRef | null {\n return this._active;\n }\n\n /** Get all known conversation references (in-memory only) */\n get history(): readonly ConversationRef[] {\n return this._history;\n }\n\n /**\n * Set the active conversation by ID (called internally after stream completes).\n * If the ID matches an existing ref, that ref becomes active.\n * Otherwise a new ref is created.\n */\n setActive(conversationId: string): void {\n const existing = this._history.find(c => c.id === conversationId);\n if (existing) {\n this._active = existing;\n } else {\n const ref: ConversationRef = {\n id: conversationId,\n createdAt: new Date(),\n };\n this._history.push(ref);\n this._active = ref;\n }\n }\n\n /** Clear all state */\n clear(): void {\n this._active = null;\n this._history.length = 0;\n }\n}\n","/**\n * Generate a UUID v4 using crypto.randomUUID when available,\n * falling back to a manual implementation.\n */\nexport function uuid(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n\n // Fallback for environments without crypto.randomUUID\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n","/**\n * HTTP client wrapper for the Thaliq Native Provider.\n *\n * Handles fetch with timeout via AbortController,\n * error mapping from HTTP status codes, and response parsing.\n */\n\nimport {\n mapHttpError,\n TimeoutError,\n ConnectionError,\n} from '../../types/errors';\nimport type { Logger } from '../../types/config';\n\nexport interface HttpClientConfig {\n baseUrl: string;\n timeout: number;\n logger: Logger;\n}\n\nexport interface HttpRequestOptions {\n method: 'GET' | 'POST';\n path: string;\n headers: Record<string, string | undefined>;\n body?: unknown;\n signal?: AbortSignal;\n timeout: number;\n}\n\nexport class HttpClient {\n private readonly baseUrl: string;\n private readonly defaultTimeout: number;\n private readonly logger: Logger;\n\n constructor(config: HttpClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/+$/, '');\n this.defaultTimeout = config.timeout;\n this.logger = config.logger;\n }\n\n /** Execute a JSON request and return the parsed response */\n async json<T>(options: HttpRequestOptions): Promise<T> {\n const response = await this.rawFetch(options);\n\n if (!response.ok) {\n const body = await response.text().catch(() => 'Unknown error');\n let message: string;\n try {\n const parsed = JSON.parse(body);\n message = parsed.message ?? parsed.error ?? body;\n } catch {\n message = body;\n }\n throw mapHttpError(response.status, message, response.headers);\n }\n\n return response.json() as Promise<T>;\n }\n\n /** Execute a request and return the raw Response (for SSE streaming) */\n async stream(options: HttpRequestOptions): Promise<Response> {\n const response = await this.rawFetch(options);\n\n if (!response.ok) {\n const body = await response.text().catch(() => 'Unknown error');\n let message: string;\n try {\n const parsed = JSON.parse(body);\n message = parsed.message ?? parsed.error ?? body;\n } catch {\n message = body;\n }\n throw mapHttpError(response.status, message, response.headers);\n }\n\n return response;\n }\n\n /** Low-level fetch with timeout and error wrapping */\n private async rawFetch(options: HttpRequestOptions): Promise<Response> {\n const url = `${this.baseUrl}${options.path}`;\n const timeout = options.timeout ?? this.defaultTimeout;\n\n // Create a timeout controller that will abort if no external signal is provided\n const timeoutController = new AbortController();\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n // If the caller provided an AbortSignal, listen to it\n if (options.signal) {\n options.signal.addEventListener('abort', () => timeoutController.abort(options.signal?.reason), {\n once: true,\n });\n }\n\n timeoutId = setTimeout(() => {\n timeoutController.abort(new TimeoutError(`Request timed out after ${timeout}ms`));\n }, timeout);\n\n // Clean up headers: remove undefined values\n const headers: Record<string, string> = { 'content-type': 'application/json' };\n for (const [key, value] of Object.entries(options.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n\n this.logger.debug(`${options.method} ${url}`);\n\n try {\n const response = await fetch(url, {\n method: options.method,\n headers,\n body: options.body ? JSON.stringify(options.body) : undefined,\n signal: timeoutController.signal,\n });\n\n return response;\n } catch (error: unknown) {\n if (error instanceof TimeoutError) throw error;\n if (error instanceof DOMException && error.name === 'AbortError') {\n // Check if it was a timeout or user abort\n if (timeoutController.signal.reason instanceof TimeoutError) {\n throw timeoutController.signal.reason;\n }\n throw error;\n }\n throw new ConnectionError(\n error instanceof Error ? error.message : 'Connection failed',\n );\n } finally {\n if (timeoutId !== undefined) clearTimeout(timeoutId);\n }\n }\n}\n","/**\n * SSE (Server-Sent Events) parser.\n *\n * Converts a ReadableStream<Uint8Array> into an AsyncIterable of parsed SSE events.\n * Follows the SSE spec: each event is delimited by a blank line,\n * and fields are `event:`, `data:`, `id:`.\n */\n\nimport type { StreamEvent } from '../../types/events';\nimport type { PendingAction } from '../../types/actions';\n\ninterface RawSSEEvent {\n event: string;\n data: string;\n id: string;\n}\n\n/**\n * Parse a ReadableStream into SSE events.\n * Yields StreamEvent objects as they arrive.\n */\nexport async function* parseSSEStream(\n stream: ReadableStream<Uint8Array>,\n): AsyncIterable<StreamEvent> {\n const reader = stream.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n\n // Split on double newlines (SSE event delimiter)\n const parts = buffer.split('\\n\\n');\n // Keep the last part as buffer (may be incomplete)\n buffer = parts.pop() ?? '';\n\n for (const part of parts) {\n const raw = parseRawEvent(part);\n if (!raw) continue;\n\n const mapped = mapToStreamEvent(raw);\n if (mapped) yield mapped;\n }\n }\n\n // Process any remaining buffer\n if (buffer.trim()) {\n const raw = parseRawEvent(buffer);\n if (raw) {\n const mapped = mapToStreamEvent(raw);\n if (mapped) yield mapped;\n }\n }\n } finally {\n reader.releaseLock();\n }\n}\n\n/** Parse raw SSE text block into event/data/id fields */\nfunction parseRawEvent(block: string): RawSSEEvent | null {\n let event = '';\n let data = '';\n let id = '';\n\n const lines = block.split('\\n');\n for (const line of lines) {\n if (line.startsWith('event:')) {\n event = line.slice(6).trim();\n } else if (line.startsWith('data:')) {\n data = line.slice(5).trim();\n } else if (line.startsWith('id:')) {\n id = line.slice(3).trim();\n }\n // Lines starting with ':' are comments, ignored\n }\n\n if (!event && !data) return null;\n\n return { event, data, id };\n}\n\n/** Map a raw SSE event to a typed StreamEvent */\nfunction mapToStreamEvent(raw: RawSSEEvent): StreamEvent | null {\n const type = raw.event;\n\n try {\n const payload = raw.data ? JSON.parse(raw.data) : {};\n\n switch (type) {\n case 'meta':\n return {\n type: 'meta',\n conversationId: payload.conversationId,\n };\n\n case 'status':\n return {\n type: 'status',\n text: payload.text,\n };\n\n case 'content.delta':\n return {\n type: 'content.delta',\n delta: payload.delta,\n };\n\n case 'tool.start':\n return {\n type: 'tool.start',\n tool: payload.tool,\n };\n\n case 'tool.end':\n return {\n type: 'tool.end',\n tool: payload.tool,\n success: payload.success,\n };\n\n case 'action':\n return {\n type: 'action',\n action: payload as PendingAction,\n };\n\n case 'handoff':\n return {\n type: 'handoff',\n message: payload.message,\n agentName: payload.agentName,\n reason: payload.reason,\n };\n\n case 'response.completed':\n return {\n type: 'response.completed',\n message: payload.message,\n conversationId: payload.conversationId,\n insights: payload.insights ?? [],\n metadata: payload.metadata,\n };\n\n case 'error':\n return {\n type: 'error',\n message: payload.message,\n };\n\n case 'keepalive':\n return {\n type: 'keepalive',\n ts: payload.ts,\n };\n\n default:\n // Unknown event type — skip\n return null;\n }\n } catch {\n // Malformed JSON — skip\n return null;\n }\n}\n","/**\n * ThaliqNativeProvider — Default provider that communicates with the Thaliq API.\n *\n * - chat() → POST /api/agent/chat\n * - stream() → GET /api/agent/stream (SSE)\n */\n\nimport type { Provider, ProviderRequest } from '../../types/provider';\nimport type { ChatResponse } from '../../types/responses';\nimport type { StreamEvent } from '../../types/events';\nimport type { Logger } from '../../types/config';\nimport { StreamError } from '../../types/errors';\nimport { HttpClient } from './http-client';\nimport { parseSSEStream } from './sse-parser';\n\nexport interface ThaliqNativeProviderConfig {\n baseUrl: string;\n timeout: number;\n logger: Logger;\n}\n\nexport class ThaliqNativeProvider implements Provider {\n readonly name = 'thaliq-native';\n private readonly http: HttpClient;\n private readonly logger: Logger;\n\n constructor(config: ThaliqNativeProviderConfig) {\n this.logger = config.logger;\n this.http = new HttpClient({\n baseUrl: config.baseUrl,\n timeout: config.timeout,\n logger: config.logger,\n });\n }\n\n /** POST /api/agent/chat — non-streaming */\n async chat(request: ProviderRequest): Promise<ChatResponse> {\n const body: Record<string, unknown> = {\n message: request.message,\n };\n\n if (request.conversationId) body['conversationId'] = request.conversationId;\n if (request.agentType) body['agentType'] = request.agentType;\n if (request.actionResponse) body['actionResponse'] = request.actionResponse;\n\n return this.http.json<ChatResponse>({\n method: 'POST',\n path: '/api/agent/chat',\n headers: request.headers,\n body,\n signal: request.signal,\n timeout: request.timeout,\n });\n }\n\n /** GET /api/agent/stream — SSE streaming */\n async *stream(request: ProviderRequest): AsyncIterable<StreamEvent> {\n // Build query string\n const params = new URLSearchParams();\n params.set('q', request.message);\n if (request.conversationId) params.set('conversationId', request.conversationId);\n if (request.agentType) params.set('agentType', request.agentType);\n if (request.actionResponse) {\n params.set('actionResponse', JSON.stringify(request.actionResponse));\n }\n\n const response = await this.http.stream({\n method: 'GET',\n path: `/api/agent/stream?${params.toString()}`,\n headers: {\n ...request.headers,\n accept: 'text/event-stream',\n },\n signal: request.signal,\n timeout: request.timeout,\n });\n\n if (!response.body) {\n throw new StreamError('Response body is null — streaming not supported');\n }\n\n this.logger.debug('SSE stream connected');\n\n yield* parseSSEStream(response.body);\n }\n}\n","/**\n * Typed EventEmitter — zero-dependency, type-safe event system.\n *\n * @example\n * ```typescript\n * const emitter = new TypedEventEmitter<SDKEventMap>();\n * emitter.on('error', (err) => console.error(err));\n * emitter.once('identify', (userId) => console.log('Identified:', userId));\n * ```\n */\n\n/** Callback function type */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype Callback = (...args: any[]) => void;\n\n/** Typed listener with optional _once flag */\ntype Listener = Callback & { _once?: boolean };\n\nexport class TypedEventEmitter<T extends { [K in keyof T]: Callback }> {\n private readonly _listeners = new Map<keyof T, Set<Listener>>();\n\n /** Register a listener for an event */\n on<K extends keyof T>(event: K, listener: T[K]): this {\n if (!this._listeners.has(event)) {\n this._listeners.set(event, new Set());\n }\n this._listeners.get(event)!.add(listener as Listener);\n return this;\n }\n\n /** Register a one-time listener */\n once<K extends keyof T>(event: K, listener: T[K]): this {\n const wrapped = listener as Listener;\n wrapped._once = true;\n return this.on(event, listener);\n }\n\n /** Remove a listener */\n off<K extends keyof T>(event: K, listener: T[K]): this {\n const set = this._listeners.get(event);\n if (set) {\n set.delete(listener as Listener);\n if (set.size === 0) {\n this._listeners.delete(event);\n }\n }\n return this;\n }\n\n /** Emit an event to all registered listeners */\n emit<K extends keyof T>(event: K, ...args: Parameters<T[K]>): void {\n const set = this._listeners.get(event);\n if (!set) return;\n\n for (const listener of set) {\n listener(...args);\n if (listener._once) {\n set.delete(listener);\n }\n }\n\n if (set.size === 0) {\n this._listeners.delete(event);\n }\n }\n\n /** Remove all listeners for an event, or all listeners if no event specified */\n removeAllListeners(event?: keyof T): this {\n if (event) {\n this._listeners.delete(event);\n } else {\n this._listeners.clear();\n }\n return this;\n }\n\n /** Get the count of listeners for a specific event */\n listenerCount(event: keyof T): number {\n return this._listeners.get(event)?.size ?? 0;\n }\n}\n","/**\n * Default console-based logger with level filtering.\n */\n\nimport type { Logger, LogLevel } from '../types/config';\n\nconst LEVEL_ORDER: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n silent: 4,\n};\n\nexport function createDefaultLogger(minLevel: LogLevel): Logger {\n const min = LEVEL_ORDER[minLevel];\n\n return {\n debug(message: string, ...args: unknown[]) {\n if (min <= LEVEL_ORDER.debug) console.debug(`[thaliq] ${message}`, ...args);\n },\n info(message: string, ...args: unknown[]) {\n if (min <= LEVEL_ORDER.info) console.info(`[thaliq] ${message}`, ...args);\n },\n warn(message: string, ...args: unknown[]) {\n if (min <= LEVEL_ORDER.warn) console.warn(`[thaliq] ${message}`, ...args);\n },\n error(message: string, ...args: unknown[]) {\n if (min <= LEVEL_ORDER.error) console.error(`[thaliq] ${message}`, ...args);\n },\n };\n}\n","/**\n * Thaliq — Main SDK client class.\n *\n * @example\n * ```typescript\n * import { Thaliq } from '@thaliq/sdk';\n *\n * const thaliq = new Thaliq({ apiKey: 'tq_live_xxx' });\n *\n * // Events\n * thaliq.on('error', (err) => console.error(err));\n * thaliq.on('retry', (attempt, err, delay) => console.warn(`Retry #${attempt}`));\n *\n * // Identify user (B2B)\n * thaliq.identify({ userId: 'usr_123', email: 'user@company.com' });\n *\n * // Chat\n * const response = await thaliq.agent.chat('Hello!');\n *\n * // Stream\n * const stream = thaliq.agent.stream('Analyze Q4 sales');\n * for await (const event of stream) {\n * if (event.type === 'content.delta') process.stdout.write(event.delta);\n * }\n *\n * // Conversations are auto-tracked\n * console.log(thaliq.conversations.active);\n * ```\n */\n\nimport type { ThaliqConfig, ResolvedConfig, SDKEventMap } from './types/config';\nimport type { UserIdentity } from './types/identity';\nimport type { Provider } from './types/provider';\nimport { ValidationError } from './types/errors';\nimport { AgentClient } from './agent/agent-client';\nimport { ConversationManager } from './agent/conversation-manager';\nimport { ThaliqNativeProvider } from './providers/thaliq-native';\nimport { TypedEventEmitter } from './utils/event-emitter';\nimport { createDefaultLogger } from './utils/logger';\n\nconst DEFAULT_BASE_URL = 'https://api.thaliq.com';\nconst DEFAULT_TIMEOUT = 30_000;\nconst DEFAULT_MAX_RETRIES = 2;\nconst DEFAULT_BASE_DELAY = 500;\nconst DEFAULT_MAX_DELAY = 10_000;\n\nexport class Thaliq {\n private readonly config: ResolvedConfig;\n private readonly provider: Provider;\n private readonly emitter = new TypedEventEmitter<SDKEventMap>();\n private identity: UserIdentity | null = null;\n\n /** Agent client — use `thaliq.agent.chat()` and `thaliq.agent.stream()` */\n readonly agent: AgentClient;\n\n /** Conversations manager — create, track, and list conversations */\n readonly conversations: ConversationManager;\n\n constructor(userConfig: ThaliqConfig) {\n this.config = resolveConfig(userConfig);\n this.provider = userConfig.provider ?? new ThaliqNativeProvider({\n baseUrl: this.config.baseUrl,\n timeout: this.config.timeout,\n logger: this.config.logger,\n });\n\n this.conversations = new ConversationManager();\n\n this.agent = new AgentClient(\n this.config,\n this.provider,\n () => this.identity,\n this.emitter,\n this.conversations,\n );\n }\n\n /** Register an event listener */\n on<K extends keyof SDKEventMap>(event: K, listener: SDKEventMap[K]): this {\n this.emitter.on(event, listener);\n return this;\n }\n\n /** Register a one-time event listener */\n once<K extends keyof SDKEventMap>(event: K, listener: SDKEventMap[K]): this {\n this.emitter.once(event, listener);\n return this;\n }\n\n /** Remove an event listener */\n off<K extends keyof SDKEventMap>(event: K, listener: SDKEventMap[K]): this {\n this.emitter.off(event, listener);\n return this;\n }\n\n /** Set the user identity for subsequent requests */\n identify(user: UserIdentity): void {\n if (!user.userId) {\n throw new ValidationError('userId is required for identify()');\n }\n this.identity = user;\n this.config.logger.info(`User identified: ${user.userId}`);\n this.emitter.emit('identify', user.userId);\n }\n\n /** Clear user identity and local state */\n reset(): void {\n this.identity = null;\n this.conversations.clear();\n this.config.logger.info('SDK state reset');\n this.emitter.emit('reset');\n }\n}\n\n/** Merge user config with defaults */\nfunction resolveConfig(config: ThaliqConfig): ResolvedConfig {\n if (!config.apiKey) {\n throw new ValidationError('apiKey is required');\n }\n\n const logLevel = config.logLevel ?? 'warn';\n const logger = config.logger ?? createDefaultLogger(logLevel);\n const maxRetries = config.maxRetries ?? config.retry?.maxRetries ?? DEFAULT_MAX_RETRIES;\n\n return {\n apiKey: config.apiKey,\n baseUrl: (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, ''),\n integrationType: config.integrationType ?? 'sdk',\n timeout: config.timeout ?? DEFAULT_TIMEOUT,\n maxRetries,\n retry: {\n maxRetries,\n baseDelay: config.retry?.baseDelay ?? DEFAULT_BASE_DELAY,\n maxDelay: config.retry?.maxDelay ?? DEFAULT_MAX_DELAY,\n },\n logger,\n logLevel,\n defaultHeaders: config.defaultHeaders ?? {},\n };\n}\n","/**\n * ActionResponseBuilder — helpers for constructing ActionResponse objects.\n *\n * Provides static factory methods for each HITL action type,\n * so developers don't need to manually build ActionResponse objects.\n *\n * @example\n * ```typescript\n * import { ActionResponseBuilder } from '@thaliq/sdk';\n *\n * // Accept a consent/confirm action\n * const accept = ActionResponseBuilder.accept('inst_123');\n *\n * // Reject an action\n * const reject = ActionResponseBuilder.reject('inst_123');\n *\n * // Select an option\n * const select = ActionResponseBuilder.select('inst_123', 'option_a');\n *\n * // Submit a form\n * const form = ActionResponseBuilder.submitForm('inst_123', {\n * amount: '500',\n * currency: 'USD',\n * });\n * ```\n */\n\nimport type { ActionResponse } from '../types/actions';\n\nexport class ActionResponseBuilder {\n /**\n * Accept a consent or confirm action.\n *\n * @param instructionId - The instruction ID from `pendingAction.instructionId`\n */\n static accept(instructionId: string): ActionResponse {\n return { instructionId, accepted: true };\n }\n\n /**\n * Reject a consent or confirm action.\n *\n * @param instructionId - The instruction ID from `pendingAction.instructionId`\n */\n static reject(instructionId: string): ActionResponse {\n return { instructionId, accepted: false };\n }\n\n /**\n * Select an option from a select action.\n *\n * @param instructionId - The instruction ID from `pendingAction.instructionId`\n * @param value - The selected option value\n */\n static select(instructionId: string, value: string): ActionResponse {\n return { instructionId, accepted: true, selectedValue: value };\n }\n\n /**\n * Submit form values for a form action.\n *\n * @param instructionId - The instruction ID from `pendingAction.instructionId`\n * @param values - Key-value map of form field names to values\n */\n static submitForm(instructionId: string, values: Record<string, string>): ActionResponse {\n return { instructionId, accepted: true, formValues: values };\n }\n}\n"],"names":["ThaliqError","Error","constructor","message","code","status","super","this","name","AuthError","RateLimitError","retryAfter","ValidationError","ServiceError","StreamError","TimeoutError","ConnectionError","mapHttpError","headers","get","parseInt","AgentStreamImpl","source","abortController","onEvent","onComplete","_conversationId","_status","_pendingAction","_consumed","_source","_abortController","_onEvent","_onComplete","conversationId","pendingAction","abort","Symbol","asyncIterator","event","type","action","finalResponse","metadata","insights","delta","response","model","promptTokens","completionTokens","processingTimeMs","generatedAt","Date","toISOString","text","accumulated","isRetryableError","error","calculateBackoff","attempt","baseDelay","maxDelay","exponential","Math","pow","clamped","min","jitter","random","floor","sleep","ms","Promise","resolve","setTimeout","async","withRetry","fn","options","config","logger","onRetry","signal","lastError","maxRetries","aborted","delayMs","warn","AgentClient","provider","getIdentity","emitter","conversationManager","chat","request","buildRequest","retry","emit","setActive","stream","AbortController","err","respondToAction","originalMessage","agentType","actionResponse","feedback","identity","resolveHeaders","fetch","baseUrl","method","authorization","body","JSON","stringify","messageId","ok","catch","abortSignal","timeout","apiKey","integrationType","userId","participantId","token","mcpTokens","Object","keys","length","key","value","entries","defaultHeaders","ConversationManager","_active","_history","create","ref","id","crypto","randomUUID","replace","c","r","toString","createdAt","push","active","history","existing","find","clear","HttpClient","defaultTimeout","json","rawFetch","parsed","parse","url","path","timeoutController","timeoutId","addEventListener","reason","once","debug","DOMException","clearTimeout","parseRawEvent","block","data","lines","split","line","startsWith","slice","trim","mapToStreamEvent","raw","payload","tool","success","agentName","ts","ThaliqNativeProvider","http","params","URLSearchParams","set","accept","reader","getReader","decoder","TextDecoder","buffer","done","read","decode","parts","pop","part","mapped","releaseLock","parseSSEStream","TypedEventEmitter","_listeners","Map","on","listener","has","Set","add","_once","off","delete","size","args","removeAllListeners","listenerCount","LEVEL_ORDER","info","silent","DEFAULT_BASE_URL","Thaliq","userConfig","logLevel","minLevel","console","createDefaultLogger","resolveConfig","conversations","agent","identify","user","reset","ActionResponseBuilder","instructionId","accepted","reject","select","selectedValue","submitForm","values","formValues"],"mappings":"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"}
package/types/agent.d.ts CHANGED
@@ -7,9 +7,10 @@ import { ChatResponse } from './responses';
7
7
  * - `'completed'` — Stream finished with a `response.completed` event
8
8
  * - `'awaiting_action'` — Stream paused; a HITL action requires user response
9
9
  * - `'error'` — An error event was received
10
+ * - `'handoff'` — Conversation was escalated to a human agent
10
11
  * - `'aborted'` — Stream was cancelled via `abort()`
11
12
  */
12
- export type StreamStatus = 'streaming' | 'completed' | 'awaiting_action' | 'error' | 'aborted';
13
+ export type StreamStatus = 'streaming' | 'completed' | 'awaiting_action' | 'handoff' | 'error' | 'aborted';
13
14
  /** Agent type — `'general'` is default, tenants can define custom types in their configuration. */
14
15
  export type AgentType = 'general' | (string & Record<never, never>);
15
16
  /** Options for non-streaming chat */
package/types/events.d.ts CHANGED
@@ -39,6 +39,13 @@ export interface ResponseCompletedEvent {
39
39
  insights: Insight[];
40
40
  metadata: ResponseMetadata;
41
41
  }
42
+ /** Handoff to human agent — conversation escalated */
43
+ export interface HandoffEvent {
44
+ type: 'handoff';
45
+ message: string;
46
+ agentName?: string;
47
+ reason?: string;
48
+ }
42
49
  /** Error during streaming */
43
50
  export interface ErrorEvent {
44
51
  type: 'error';
@@ -67,4 +74,4 @@ export interface KeepaliveEvent {
67
74
  * }
68
75
  * ```
69
76
  */
70
- export type StreamEvent = MetaEvent | StatusEvent | ContentDeltaEvent | ToolStartEvent | ToolEndEvent | ActionEvent | ResponseCompletedEvent | ErrorEvent | KeepaliveEvent;
77
+ export type StreamEvent = MetaEvent | StatusEvent | ContentDeltaEvent | ToolStartEvent | ToolEndEvent | ActionEvent | HandoffEvent | ResponseCompletedEvent | ErrorEvent | KeepaliveEvent;
@@ -22,6 +22,8 @@ export interface Insight {
22
22
  export interface ResponseMetadata {
23
23
  /** Conversation ID */
24
24
  conversationId: string;
25
+ /** Message ID (for feedback) */
26
+ messageId?: string;
25
27
  /** Model used for generation */
26
28
  model: string;
27
29
  /** Number of input/prompt tokens */
@@ -33,6 +35,8 @@ export interface ResponseMetadata {
33
35
  /** ISO timestamp of generation */
34
36
  generatedAt: string;
35
37
  }
38
+ /** Feedback type for rating messages */
39
+ export type MessageFeedback = 'positive' | 'negative';
36
40
  /** Complete chat response (non-streaming or accumulated) */
37
41
  export interface ChatResponse {
38
42
  /** The agent's text response */
package/README.md DELETED
@@ -1,224 +0,0 @@
1
- # @thaliq/sdk
2
-
3
- Headless, type-safe, provider-agnostic SDK for building applications with [Thaliq](https://thaliq.com) AI agents.
4
-
5
- - **Streaming-first** — `AsyncIterable<StreamEvent>` as primary primitive
6
- - **Zero dependencies** — Only native runtime APIs (`fetch`, `ReadableStream`)
7
- - **Provider-agnostic** — Swap backends via the `Provider` interface
8
- - **Human-in-the-Loop** — Built-in HITL action support (consent, confirm, select, form)
9
- - **Automatic retry** — Exponential backoff on server/network errors
10
-
11
- ## Installation
12
-
13
- ```bash
14
- npm install @thaliq/sdk
15
- ```
16
-
17
- ## Quick Start
18
-
19
- ```typescript
20
- import { Thaliq } from '@thaliq/sdk';
21
-
22
- const thaliq = new Thaliq({ apiKey: 'tq_live_xxx' });
23
-
24
- // Non-streaming
25
- const response = await thaliq.agent.chat('Hello!');
26
- console.log(response.message);
27
-
28
- // Streaming
29
- const stream = thaliq.agent.stream('Analyze Q4 sales');
30
- for await (const event of stream) {
31
- if (event.type === 'content.delta') {
32
- process.stdout.write(event.delta);
33
- }
34
- }
35
- ```
36
-
37
- ## Streaming
38
-
39
- Every stream event has a `type` field for type narrowing:
40
-
41
- ```typescript
42
- const stream = thaliq.agent.stream('Hello');
43
-
44
- for await (const event of stream) {
45
- switch (event.type) {
46
- case 'meta':
47
- console.log('Conversation:', event.conversationId);
48
- break;
49
- case 'status':
50
- console.log('Status:', event.text);
51
- break;
52
- case 'content.delta':
53
- process.stdout.write(event.delta);
54
- break;
55
- case 'tool.start':
56
- console.log(`Running tool: ${event.tool}`);
57
- break;
58
- case 'tool.end':
59
- console.log(`Tool ${event.tool}: ${event.success ? 'ok' : 'failed'}`);
60
- break;
61
- case 'response.completed':
62
- console.log('\nDone. Tokens:', event.metadata.completionTokens);
63
- break;
64
- case 'error':
65
- console.error('Error:', event.message);
66
- break;
67
- }
68
- }
69
- ```
70
-
71
- ### Convenience methods
72
-
73
- ```typescript
74
- // Get just the text
75
- const text = await thaliq.agent.stream('Summarize this').text();
76
-
77
- // Get the full response (like chat, but streamed)
78
- const response = await thaliq.agent.stream('Summarize this').finalResponse();
79
- ```
80
-
81
- ## User Identity
82
-
83
- For authenticated B2B scenarios, identify the user before sending messages:
84
-
85
- ```typescript
86
- thaliq.identify({
87
- userId: 'usr_123',
88
- email: 'user@company.com',
89
- token: 'eyJ...', // JWT passthrough for MCP servers
90
- mcpTokens: { 'my-mcp-server': 'server-specific-token' },
91
- });
92
-
93
- // Clear on logout
94
- thaliq.reset();
95
- ```
96
-
97
- ## Human-in-the-Loop (HITL)
98
-
99
- When the agent requires user approval before executing a tool:
100
-
101
- ```typescript
102
- import { ActionResponseBuilder } from '@thaliq/sdk';
103
-
104
- const stream = thaliq.agent.stream('Transfer $500 to Alice');
105
- for await (const event of stream) {
106
- if (event.type === 'content.delta') process.stdout.write(event.delta);
107
- }
108
-
109
- if (stream.pendingAction) {
110
- // User approved — resume the stream
111
- const resumed = thaliq.agent.respondToAction({
112
- conversationId: stream.conversationId!,
113
- originalMessage: 'Transfer $500 to Alice',
114
- actionResponse: ActionResponseBuilder.accept(stream.pendingAction.instructionId),
115
- });
116
-
117
- for await (const event of resumed) {
118
- if (event.type === 'content.delta') process.stdout.write(event.delta);
119
- }
120
- }
121
- ```
122
-
123
- Action response helpers:
124
-
125
- ```typescript
126
- ActionResponseBuilder.accept(instructionId); // consent/confirm
127
- ActionResponseBuilder.reject(instructionId); // reject
128
- ActionResponseBuilder.select(instructionId, 'option_a'); // select
129
- ActionResponseBuilder.submitForm(instructionId, { amount: '500' }); // form
130
- ```
131
-
132
- ## Conversations
133
-
134
- Conversations are auto-tracked across streams:
135
-
136
- ```typescript
137
- const stream = thaliq.agent.stream('Hello');
138
- for await (const event of stream) { /* ... */ }
139
-
140
- // Continue the conversation
141
- const followUp = thaliq.agent.stream('Tell me more', {
142
- conversationId: thaliq.conversations.active!.id,
143
- });
144
- ```
145
-
146
- ## Configuration
147
-
148
- ```typescript
149
- const thaliq = new Thaliq({
150
- apiKey: 'tq_live_xxx', // Required
151
- baseUrl: 'https://api.thaliq.com', // Default
152
- integrationType: 'sdk', // 'sdk' | 'widget'
153
- timeout: 30000, // Request timeout (ms)
154
- maxRetries: 2, // Automatic retries
155
- retry: {
156
- baseDelay: 500, // Initial retry delay
157
- maxDelay: 10000, // Max retry delay
158
- },
159
- logLevel: 'warn', // 'debug' | 'info' | 'warn' | 'error' | 'silent'
160
- defaultHeaders: { // Custom headers on every request
161
- 'x-tenant-id': 'abc',
162
- },
163
- });
164
- ```
165
-
166
- ## Events
167
-
168
- ```typescript
169
- thaliq.on('error', (err) => console.error(err.code, err.message));
170
- thaliq.on('retry', (attempt, err, delayMs) => console.warn(`Retry #${attempt}`));
171
- thaliq.on('stream.start', (convId) => { /* ... */ });
172
- thaliq.on('stream.end', (convId) => { /* ... */ });
173
- thaliq.on('identify', (userId) => { /* ... */ });
174
- thaliq.on('reset', () => { /* ... */ });
175
- ```
176
-
177
- ## Error Handling
178
-
179
- All SDK errors extend `ThaliqError` with a `code` property:
180
-
181
- ```typescript
182
- import { ThaliqError, AuthError, RateLimitError } from '@thaliq/sdk';
183
-
184
- try {
185
- await thaliq.agent.chat('Hello');
186
- } catch (err) {
187
- if (err instanceof RateLimitError) {
188
- console.log(`Rate limited. Retry after ${err.retryAfter}s`);
189
- } else if (err instanceof AuthError) {
190
- console.log('Invalid API key');
191
- } else if (err instanceof ThaliqError) {
192
- console.log(err.code, err.message);
193
- }
194
- }
195
- ```
196
-
197
- | Error Class | Code | HTTP Status |
198
- |-------------|------|-------------|
199
- | `AuthError` | `AUTH_ERROR` | 401, 403 |
200
- | `RateLimitError` | `RATE_LIMIT` | 429 |
201
- | `ValidationError` | `VALIDATION_ERROR` | 400 |
202
- | `ServiceError` | `SERVICE_ERROR` | 503 |
203
- | `StreamError` | `STREAM_ERROR` | — |
204
- | `TimeoutError` | `TIMEOUT_ERROR` | — |
205
- | `ConnectionError` | `CONNECTION_ERROR` | — |
206
-
207
- ## Compatibility
208
-
209
- | Runtime | Minimum |
210
- |---------|---------|
211
- | Node.js | 18+ (native `fetch`) |
212
- | Browsers | Chrome 89+, Firefox 89+, Safari 15+ |
213
- | Deno | 1.28+ |
214
- | Bun | 1.0+ |
215
-
216
- ## Documentation
217
-
218
- - [Full SDK Documentation](https://docs.thaliq.com/sdk)
219
- - [SDK Protocol Specification](https://docs.thaliq.com/sdk/protocol)
220
- - [Integration Guide](https://docs.thaliq.com/integration)
221
-
222
- ## License
223
-
224
- MIT
package/thaliq-sdk.cjs.js DELETED
@@ -1,2 +0,0 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class t extends Error{constructor(t,e,s){super(t),this.name="ThaliqError",this.code=e,this.status=s}}class e extends t{constructor(t,e=401){super(t,"AUTH_ERROR",e),this.name="AuthError"}}class s extends t{constructor(t,e=60){super(t,"RATE_LIMIT",429),this.name="RateLimitError",this.retryAfter=e}}class n extends t{constructor(t){super(t,"VALIDATION_ERROR",400),this.name="ValidationError"}}class r extends t{constructor(t){super(t,"SERVICE_ERROR",503),this.name="ServiceError"}}class o extends t{constructor(t){super(t,"STREAM_ERROR"),this.name="StreamError"}}class i extends t{constructor(t="Request timed out"){super(t,"TIMEOUT_ERROR"),this.name="TimeoutError"}}class a extends t{constructor(t="Connection failed"){super(t,"CONNECTION_ERROR"),this.name="ConnectionError"}}function c(o,i,a){switch(o){case 400:return new n(i);case 401:case 403:return new e(i,o);case 429:{const t=a?.get("retry-after");return new s(i,t?parseInt(t,10):60)}case 503:return new r(i);default:return new t(i,"UNKNOWN_ERROR",o)}}class l{constructor(t,e,s,n){this._conversationId=null,this._status="streaming",this._pendingAction=null,this._consumed=!1,this._source=t,this._abortController=e,this._onEvent=s,this._onComplete=n}get conversationId(){return this._conversationId}get status(){return this._status}get pendingAction(){return this._pendingAction}abort(){this._status="aborted",this._abortController.abort()}async*[Symbol.asyncIterator](){if(this._consumed)throw new o("AgentStream can only be consumed once");this._consumed=!0;try{for await(const t of this._source)"meta"===t.type&&(this._conversationId=t.conversationId),"response.completed"!==t.type||this._conversationId||(this._conversationId=t.conversationId),"action"===t.type&&(this._pendingAction=t.action,this._status="awaiting_action"),"response.completed"===t.type&&(this._status="completed"),"error"===t.type&&(this._status="error"),this._onEvent&&this._onEvent(t),yield t;"streaming"===this._status&&(this._status=this._pendingAction?"awaiting_action":"completed")}finally{this._onComplete&&this._onComplete(this._conversationId,this._status)}}async finalResponse(){let t,e,s="",n="",r=[];for await(const a of this)switch(a.type){case"meta":n=a.conversationId;break;case"content.delta":s+=a.delta;break;case"action":e=a.action;break;case"response.completed":s=a.message,n=a.conversationId,r=a.insights,t=a.metadata;break;case"error":throw new o(a.message)}const i={message:s,conversationId:n,insights:r,metadata:t??{conversationId:n,model:"unknown",promptTokens:0,completionTokens:0,processingTimeMs:0,generatedAt:(new Date).toISOString()}};return e&&(i.action=e),i}async text(){let t="";for await(const e of this){if("content.delta"===e.type&&(t+=e.delta),"response.completed"===e.type)return e.message;if("error"===e.type)throw new o(e.message)}return t}}function h(o){return!(o instanceof t)||!(o instanceof e)&&(!(o instanceof n)&&(!(o instanceof s)&&(o instanceof r||(o instanceof a||(o instanceof i||!!(o.status&&o.status>=500))))))}function d(t,e,s){const n=e*Math.pow(2,t),r=Math.min(n,s),o=r*Math.random()*.5;return Math.floor(r+o)}function u(t){return new Promise(e=>setTimeout(e,t))}async function p(e,s){const{config:n,logger:r,onRetry:o,signal:i}=s;let a;for(let l=0;l<=n.maxRetries;l++)try{return await e()}catch(c){if(a=c,l>=n.maxRetries)break;if(!h(c))break;if(i?.aborted)break;const e=d(l,n.baseDelay,n.maxDelay);r.warn(`Retry ${l+1}/${n.maxRetries} after ${e}ms`,c instanceof Error?c.message:c),o&&c instanceof t&&o(l+1,c,e),await u(e)}throw a}class g{constructor(t,e,s,n,r){this.config=t,this.provider=e,this.getIdentity=s,this.emitter=n,this.conversationManager=r}async chat(t,e){const s=this.buildRequest(t,e),n=await p(()=>this.provider.chat(s),{config:this.config.retry,logger:this.config.logger,signal:e?.signal,onRetry:(t,e,s)=>{this.emitter.emit("retry",t,e,s)}});return n.conversationId&&this.conversationManager.setActive(n.conversationId),n}stream(e,s){const n=new AbortController,r=this.buildRequest(e,s,n.signal),o=this.provider.stream(r);this.emitter.emit("stream.start",s?.conversationId??null);return new l(o,n,e=>{if("meta"===e.type&&e.conversationId&&this.conversationManager.setActive(e.conversationId),"error"===e.type){const s=new t(e.message,"STREAM_ERROR");this.emitter.emit("error",s)}s?.onEvent&&s.onEvent(e)},t=>{this.emitter.emit("stream.end",t)})}respondToAction(t){return this.stream(t.originalMessage,{conversationId:t.conversationId,agentType:t.agentType,actionResponse:t.actionResponse,onEvent:t.onEvent,signal:t.signal})}buildRequest(t,e,s){const n=this.getIdentity(),r=e?.signal??s;return{message:t,conversationId:e?.conversationId,agentType:e?.agentType,actionResponse:e?.actionResponse,headers:this.resolveHeaders(n),signal:r,timeout:this.config.timeout}}resolveHeaders(t){const e={"x-api-key":this.config.apiKey,"x-integration-type":this.config.integrationType};t&&(t.userId&&(e["x-user-id"]=t.userId),t.participantId&&(e["x-participant-id"]=t.participantId),t.token&&(e.authorization=`Bearer ${t.token}`),t.mcpTokens&&Object.keys(t.mcpTokens).length>0&&(e["x-mcp-tokens"]=JSON.stringify(t.mcpTokens)));for(const[s,n]of Object.entries(this.config.defaultHeaders))e[s]=n;return e}}class m{constructor(){this._active=null,this._history=[]}create(){const t={id:"undefined"!=typeof crypto&&"function"==typeof crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,t=>{const e=16*Math.random()|0;return("x"===t?e:3&e|8).toString(16)}),createdAt:new Date};return this._history.push(t),t}get active(){return this._active}get history(){return this._history}setActive(t){const e=this._history.find(e=>e.id===t);if(e)this._active=e;else{const e={id:t,createdAt:new Date};this._history.push(e),this._active=e}}clear(){this._active=null,this._history.length=0}}class f{constructor(t){this.baseUrl=t.baseUrl.replace(/\/+$/,""),this.defaultTimeout=t.timeout,this.logger=t.logger}async json(t){const e=await this.rawFetch(t);if(!e.ok){const t=await e.text().catch(()=>"Unknown error");let s;try{const e=JSON.parse(t);s=e.message??e.error??t}catch{s=t}throw c(e.status,s,e.headers)}return e.json()}async stream(t){const e=await this.rawFetch(t);if(!e.ok){const t=await e.text().catch(()=>"Unknown error");let s;try{const e=JSON.parse(t);s=e.message??e.error??t}catch{s=t}throw c(e.status,s,e.headers)}return e}async rawFetch(t){const e=`${this.baseUrl}${t.path}`,s=t.timeout??this.defaultTimeout,n=new AbortController;let r;t.signal&&t.signal.addEventListener("abort",()=>n.abort(t.signal?.reason),{once:!0}),r=setTimeout(()=>{n.abort(new i(`Request timed out after ${s}ms`))},s);const o={"content-type":"application/json"};for(const[i,a]of Object.entries(t.headers))void 0!==a&&(o[i]=a);this.logger.debug(`${t.method} ${e}`);try{return await fetch(e,{method:t.method,headers:o,body:t.body?JSON.stringify(t.body):void 0,signal:n.signal})}catch(c){if(c instanceof i)throw c;if(c instanceof DOMException&&"AbortError"===c.name){if(n.signal.reason instanceof i)throw n.signal.reason;throw c}throw new a(c instanceof Error?c.message:"Connection failed")}finally{void 0!==r&&clearTimeout(r)}}}function y(t){let e="",s="",n="";const r=t.split("\n");for(const o of r)o.startsWith("event:")?e=o.slice(6).trim():o.startsWith("data:")?s=o.slice(5).trim():o.startsWith("id:")&&(n=o.slice(3).trim());return e||s?{event:e,data:s,id:n}:null}function v(t){const e=t.event;try{const s=t.data?JSON.parse(t.data):{};switch(e){case"meta":return{type:"meta",conversationId:s.conversationId};case"status":return{type:"status",text:s.text};case"content.delta":return{type:"content.delta",delta:s.delta};case"tool.start":return{type:"tool.start",tool:s.tool};case"tool.end":return{type:"tool.end",tool:s.tool,success:s.success};case"action":return{type:"action",action:s};case"response.completed":return{type:"response.completed",message:s.message,conversationId:s.conversationId,insights:s.insights??[],metadata:s.metadata};case"error":return{type:"error",message:s.message};case"keepalive":return{type:"keepalive",ts:s.ts};default:return null}}catch{return null}}class x{constructor(t){this.name="thaliq-native",this.logger=t.logger,this.http=new f({baseUrl:t.baseUrl,timeout:t.timeout,logger:t.logger})}async chat(t){const e={message:t.message};return t.conversationId&&(e.conversationId=t.conversationId),t.agentType&&(e.agentType=t.agentType),t.actionResponse&&(e.actionResponse=t.actionResponse),this.http.json({method:"POST",path:"/api/agent/chat",headers:t.headers,body:e,signal:t.signal,timeout:t.timeout})}async*stream(t){const e=new URLSearchParams;e.set("q",t.message),t.conversationId&&e.set("conversationId",t.conversationId),t.agentType&&e.set("agentType",t.agentType),t.actionResponse&&e.set("actionResponse",JSON.stringify(t.actionResponse));const s=await this.http.stream({method:"GET",path:`/api/agent/stream?${e.toString()}`,headers:{...t.headers,accept:"text/event-stream"},signal:t.signal,timeout:t.timeout});if(!s.body)throw new o("Response body is null — streaming not supported");this.logger.debug("SSE stream connected"),yield*async function*(t){const e=t.getReader(),s=new TextDecoder;let n="";try{for(;;){const{done:t,value:r}=await e.read();if(t)break;n+=s.decode(r,{stream:!0});const o=n.split("\n\n");n=o.pop()??"";for(const e of o){const t=y(e);if(!t)continue;const s=v(t);s&&(yield s)}}if(n.trim()){const t=y(n);if(t){const e=v(t);e&&(yield e)}}}finally{e.releaseLock()}}(s.body)}}class w{constructor(){this._listeners=new Map}on(t,e){return this._listeners.has(t)||this._listeners.set(t,new Set),this._listeners.get(t).add(e),this}once(t,e){return e._once=!0,this.on(t,e)}off(t,e){const s=this._listeners.get(t);return s&&(s.delete(e),0===s.size&&this._listeners.delete(t)),this}emit(t,...e){const s=this._listeners.get(t);if(s){for(const t of s)t(...e),t._once&&s.delete(t);0===s.size&&this._listeners.delete(t)}}removeAllListeners(t){return t?this._listeners.delete(t):this._listeners.clear(),this}listenerCount(t){return this._listeners.get(t)?.size??0}}const _={debug:0,info:1,warn:2,error:3,silent:4};const R="https://api.thaliq.com";exports.ActionResponseBuilder=class{static accept(t){return{instructionId:t,accepted:!0}}static reject(t){return{instructionId:t,accepted:!1}}static select(t,e){return{instructionId:t,accepted:!0,selectedValue:e}}static submitForm(t,e){return{instructionId:t,accepted:!0,formValues:e}}},exports.AuthError=e,exports.ConnectionError=a,exports.ConversationManager=m,exports.RateLimitError=s,exports.ServiceError=r,exports.StreamError=o,exports.Thaliq=class{constructor(t){this.emitter=new w,this.identity=null,this.config=function(t){if(!t.apiKey)throw new n("apiKey is required");const e=t.logLevel??"warn",s=t.logger??function(t){const e=_[t];return{debug(t,...s){e<=_.debug&&console.debug(`[thaliq] ${t}`,...s)},info(t,...s){e<=_.info&&console.info(`[thaliq] ${t}`,...s)},warn(t,...s){e<=_.warn&&console.warn(`[thaliq] ${t}`,...s)},error(t,...s){e<=_.error&&console.error(`[thaliq] ${t}`,...s)}}}(e),r=t.maxRetries??t.retry?.maxRetries??2;return{apiKey:t.apiKey,baseUrl:(t.baseUrl??R).replace(/\/+$/,""),integrationType:t.integrationType??"sdk",timeout:t.timeout??3e4,maxRetries:r,retry:{maxRetries:r,baseDelay:t.retry?.baseDelay??500,maxDelay:t.retry?.maxDelay??1e4},logger:s,logLevel:e,defaultHeaders:t.defaultHeaders??{}}}(t),this.provider=t.provider??new x({baseUrl:this.config.baseUrl,timeout:this.config.timeout,logger:this.config.logger}),this.conversations=new m,this.agent=new g(this.config,this.provider,()=>this.identity,this.emitter,this.conversations)}on(t,e){return this.emitter.on(t,e),this}once(t,e){return this.emitter.once(t,e),this}off(t,e){return this.emitter.off(t,e),this}identify(t){if(!t.userId)throw new n("userId is required for identify()");this.identity=t,this.config.logger.info(`User identified: ${t.userId}`),this.emitter.emit("identify",t.userId)}reset(){this.identity=null,this.conversations.clear(),this.config.logger.info("SDK state reset"),this.emitter.emit("reset")}},exports.ThaliqError=t,exports.ThaliqNativeProvider=x,exports.TimeoutError=i,exports.TypedEventEmitter=w,exports.ValidationError=n,exports.calculateBackoff=d,exports.isRetryableError=h,exports.withRetry=p;
2
- //# sourceMappingURL=thaliq-sdk.cjs.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"thaliq-sdk.cjs.js","sources":["../../../libs/sdk/src/types/errors.ts","../../../libs/sdk/src/agent/agent-stream.ts","../../../libs/sdk/src/utils/retry.ts","../../../libs/sdk/src/agent/agent-client.ts","../../../libs/sdk/src/agent/conversation-manager.ts","../../../libs/sdk/src/utils/uuid.ts","../../../libs/sdk/src/providers/thaliq-native/http-client.ts","../../../libs/sdk/src/providers/thaliq-native/sse-parser.ts","../../../libs/sdk/src/providers/thaliq-native/thaliq-native.provider.ts","../../../libs/sdk/src/utils/event-emitter.ts","../../../libs/sdk/src/utils/logger.ts","../../../libs/sdk/src/client.ts","../../../libs/sdk/src/utils/action-response-builder.ts"],"sourcesContent":["/**\n * @thaliq/sdk - Error Types\n * @module types/errors\n */\n\n/**\n * SDK error codes used in `ThaliqError.code`.\n * Use these to programmatically distinguish error types.\n */\nexport type ErrorCode =\n | 'AUTH_ERROR'\n | 'RATE_LIMIT'\n | 'VALIDATION_ERROR'\n | 'SERVICE_ERROR'\n | 'STREAM_ERROR'\n | 'TIMEOUT_ERROR'\n | 'CONNECTION_ERROR'\n | 'UNKNOWN_ERROR';\n\n/** Base error class for all SDK errors */\nexport class ThaliqError extends Error {\n readonly code: ErrorCode;\n readonly status?: number;\n\n constructor(message: string, code: ErrorCode, status?: number) {\n super(message);\n this.name = 'ThaliqError';\n this.code = code;\n this.status = status;\n }\n}\n\n/** Authentication or authorization error (401/403) */\nexport class AuthError extends ThaliqError {\n constructor(message: string, status: number = 401) {\n super(message, 'AUTH_ERROR', status);\n this.name = 'AuthError';\n }\n}\n\n/** Rate limit exceeded (429) */\nexport class RateLimitError extends ThaliqError {\n readonly retryAfter: number;\n\n constructor(message: string, retryAfter: number = 60) {\n super(message, 'RATE_LIMIT', 429);\n this.name = 'RateLimitError';\n this.retryAfter = retryAfter;\n }\n}\n\n/** Request validation error (400) */\nexport class ValidationError extends ThaliqError {\n constructor(message: string) {\n super(message, 'VALIDATION_ERROR', 400);\n this.name = 'ValidationError';\n }\n}\n\n/** Service unavailable (503) */\nexport class ServiceError extends ThaliqError {\n constructor(message: string) {\n super(message, 'SERVICE_ERROR', 503);\n this.name = 'ServiceError';\n }\n}\n\n/** Error during SSE streaming */\nexport class StreamError extends ThaliqError {\n constructor(message: string) {\n super(message, 'STREAM_ERROR');\n this.name = 'StreamError';\n }\n}\n\n/** Request timeout */\nexport class TimeoutError extends ThaliqError {\n constructor(message: string = 'Request timed out') {\n super(message, 'TIMEOUT_ERROR');\n this.name = 'TimeoutError';\n }\n}\n\n/** Network/connection error */\nexport class ConnectionError extends ThaliqError {\n constructor(message: string = 'Connection failed') {\n super(message, 'CONNECTION_ERROR');\n this.name = 'ConnectionError';\n }\n}\n\n/**\n * Maps an HTTP status code to the appropriate ThaliqError subclass.\n * Used internally by the HTTP client; also useful for custom providers.\n */\nexport function mapHttpError(status: number, message: string, headers?: Headers): ThaliqError {\n switch (status) {\n case 400:\n return new ValidationError(message);\n case 401:\n case 403:\n return new AuthError(message, status);\n case 429: {\n const retryAfter = headers?.get('retry-after');\n return new RateLimitError(message, retryAfter ? parseInt(retryAfter, 10) : 60);\n }\n case 503:\n return new ServiceError(message);\n default:\n return new ThaliqError(message, 'UNKNOWN_ERROR', status);\n }\n}\n","/**\n * AgentStream — AsyncIterable wrapper over SSE events.\n *\n * Provides convenient access to the conversation ID, abort,\n * and methods to accumulate the final response or text.\n */\n\nimport type { AgentStream as IAgentStream, StreamStatus } from '../types/agent';\nimport type { StreamEvent } from '../types/events';\nimport type { ChatResponse } from '../types/responses';\nimport type { Insight, ResponseMetadata } from '../types/responses';\nimport type { PendingAction } from '../types/actions';\nimport { StreamError } from '../types/errors';\n\nexport class AgentStreamImpl implements IAgentStream {\n private _conversationId: string | null = null;\n private _status: StreamStatus = 'streaming';\n private _pendingAction: PendingAction | null = null;\n private readonly _source: AsyncIterable<StreamEvent>;\n private readonly _abortController: AbortController;\n private readonly _onEvent?: (event: StreamEvent) => void;\n private readonly _onComplete?: (conversationId: string | null, status: StreamStatus) => void;\n private _consumed = false;\n\n constructor(\n source: AsyncIterable<StreamEvent>,\n abortController: AbortController,\n onEvent?: (event: StreamEvent) => void,\n onComplete?: (conversationId: string | null, status: StreamStatus) => void,\n ) {\n this._source = source;\n this._abortController = abortController;\n this._onEvent = onEvent;\n this._onComplete = onComplete;\n }\n\n get conversationId(): string | null {\n return this._conversationId;\n }\n\n get status(): StreamStatus {\n return this._status;\n }\n\n get pendingAction(): PendingAction | null {\n return this._pendingAction;\n }\n\n abort(): void {\n this._status = 'aborted';\n this._abortController.abort();\n }\n\n async *[Symbol.asyncIterator](): AsyncIterator<StreamEvent> {\n if (this._consumed) {\n throw new StreamError('AgentStream can only be consumed once');\n }\n this._consumed = true;\n\n try {\n for await (const event of this._source) {\n // Track conversation ID from meta event\n if (event.type === 'meta') {\n this._conversationId = event.conversationId;\n }\n\n // Also track from response.completed\n if (event.type === 'response.completed' && !this._conversationId) {\n this._conversationId = event.conversationId;\n }\n\n // Track action events — stream is awaiting user response\n if (event.type === 'action') {\n this._pendingAction = event.action;\n this._status = 'awaiting_action';\n }\n\n // Track completion\n if (event.type === 'response.completed') {\n this._status = 'completed';\n }\n\n // Track errors\n if (event.type === 'error') {\n this._status = 'error';\n }\n\n // Fire optional callback\n if (this._onEvent) {\n this._onEvent(event);\n }\n\n yield event;\n }\n\n // If stream ended naturally without explicit status, mark completed\n if (this._status === 'streaming') {\n this._status = this._pendingAction ? 'awaiting_action' : 'completed';\n }\n } finally {\n // Notify completion regardless of how stream ended\n if (this._onComplete) {\n this._onComplete(this._conversationId, this._status);\n }\n }\n }\n\n async finalResponse(): Promise<ChatResponse> {\n let message = '';\n let conversationId = '';\n let insights: Insight[] = [];\n let metadata: ResponseMetadata | undefined;\n let action: PendingAction | undefined;\n\n for await (const event of this) {\n switch (event.type) {\n case 'meta':\n conversationId = event.conversationId;\n break;\n case 'content.delta':\n message += event.delta;\n break;\n case 'action':\n action = event.action;\n break;\n case 'response.completed':\n message = event.message;\n conversationId = event.conversationId;\n insights = event.insights;\n metadata = event.metadata;\n break;\n case 'error':\n throw new StreamError(event.message);\n }\n }\n\n const response: ChatResponse = {\n message,\n conversationId,\n insights,\n metadata: metadata ?? {\n conversationId,\n model: 'unknown',\n promptTokens: 0,\n completionTokens: 0,\n processingTimeMs: 0,\n generatedAt: new Date().toISOString(),\n },\n };\n\n if (action) {\n response.action = action;\n }\n\n return response;\n }\n\n async text(): Promise<string> {\n let accumulated = '';\n\n for await (const event of this) {\n if (event.type === 'content.delta') {\n accumulated += event.delta;\n }\n if (event.type === 'response.completed') {\n return event.message;\n }\n if (event.type === 'error') {\n throw new StreamError(event.message);\n }\n }\n\n return accumulated;\n }\n}\n","/**\n * Retry logic with exponential backoff and jitter.\n *\n * Retries on server errors (500/502/503/504) and network errors.\n * Never retries on client errors (400/401/403/429).\n */\n\nimport type { ResolvedRetryConfig, Logger } from '../types/config';\nimport {\n ThaliqError,\n RateLimitError,\n AuthError,\n ValidationError,\n TimeoutError,\n ConnectionError,\n ServiceError,\n} from '../types/errors';\n\n/**\n * Check if an error is retryable.\n * Returns `true` for server errors (5xx), timeouts, and connection errors.\n * Returns `false` for auth errors (401/403), validation (400), and rate limits (429).\n */\nexport function isRetryableError(error: unknown): boolean {\n if (!(error instanceof ThaliqError)) {\n // Unknown errors (network failures, etc.) are retryable\n return true;\n }\n\n // Never retry client errors\n if (error instanceof AuthError) return false;\n if (error instanceof ValidationError) return false;\n if (error instanceof RateLimitError) return false;\n\n // Retry server errors and connection issues\n if (error instanceof ServiceError) return true;\n if (error instanceof ConnectionError) return true;\n if (error instanceof TimeoutError) return true;\n\n // Retry 5xx status codes\n if (error.status && error.status >= 500) return true;\n\n return false;\n}\n\n/**\n * Calculate the retry delay with exponential backoff and jitter.\n * Formula: `min(baseDelay * 2^attempt, maxDelay) + random(0..50%)`.\n */\nexport function calculateBackoff(\n attempt: number,\n baseDelay: number,\n maxDelay: number,\n): number {\n // Exponential: baseDelay * 2^attempt\n const exponential = baseDelay * Math.pow(2, attempt);\n // Clamp to maxDelay\n const clamped = Math.min(exponential, maxDelay);\n // Add jitter: random 0-50% of the delay\n const jitter = clamped * Math.random() * 0.5;\n return Math.floor(clamped + jitter);\n}\n\n/** Sleep for a given number of milliseconds */\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/** Options for the retry wrapper */\nexport interface RetryOptions {\n config: ResolvedRetryConfig;\n logger: Logger;\n /** Called before each retry attempt */\n onRetry?: (attempt: number, error: ThaliqError, delayMs: number) => void;\n /** AbortSignal to cancel retries */\n signal?: AbortSignal;\n}\n\n/**\n * Execute an async function with automatic retry on retryable errors.\n * Uses exponential backoff with jitter between attempts.\n *\n * @param fn - The async function to execute (and potentially retry)\n * @param options - Retry configuration, logger, and optional callbacks\n * @returns The result of `fn()` on success\n * @throws The last error after all retries are exhausted\n */\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n options: RetryOptions,\n): Promise<T> {\n const { config, logger, onRetry, signal } = options;\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= config.maxRetries; attempt++) {\n try {\n return await fn();\n } catch (error: unknown) {\n lastError = error;\n\n // Don't retry if we've exhausted attempts\n if (attempt >= config.maxRetries) break;\n\n // Don't retry non-retryable errors\n if (!isRetryableError(error)) break;\n\n // Don't retry if aborted\n if (signal?.aborted) break;\n\n const delayMs = calculateBackoff(attempt, config.baseDelay, config.maxDelay);\n\n logger.warn(\n `Retry ${attempt + 1}/${config.maxRetries} after ${delayMs}ms`,\n error instanceof Error ? error.message : error,\n );\n\n if (onRetry && error instanceof ThaliqError) {\n onRetry(attempt + 1, error, delayMs);\n }\n\n await sleep(delayMs);\n }\n }\n\n throw lastError;\n}\n","/**\n * AgentClient — main interface for interacting with agents.\n *\n * Accessed via `thaliq.agent.chat()` and `thaliq.agent.stream()`.\n * Includes automatic retry with exponential backoff for chat requests.\n */\n\nimport type { Provider, ProviderRequest, ResolvedHeaders } from '../types/provider';\nimport type { ChatOptions, StreamOptions, AgentStream, RespondToActionOptions, StreamStatus } from '../types/agent';\nimport type { ChatResponse } from '../types/responses';\nimport type { UserIdentity } from '../types/identity';\nimport type { ResolvedConfig, SDKEventMap } from '../types/config';\nimport type { TypedEventEmitter } from '../utils/event-emitter';\nimport type { ConversationManager } from './conversation-manager';\nimport { RateLimitError, ThaliqError } from '../types/errors';\nimport { AgentStreamImpl } from './agent-stream';\nimport { withRetry } from '../utils/retry';\n\nexport class AgentClient {\n private readonly config: ResolvedConfig;\n private readonly provider: Provider;\n private readonly getIdentity: () => UserIdentity | null;\n private readonly emitter: TypedEventEmitter<SDKEventMap>;\n private readonly conversationManager: ConversationManager;\n\n constructor(\n config: ResolvedConfig,\n provider: Provider,\n getIdentity: () => UserIdentity | null,\n emitter: TypedEventEmitter<SDKEventMap>,\n conversationManager: ConversationManager,\n ) {\n this.config = config;\n this.provider = provider;\n this.getIdentity = getIdentity;\n this.emitter = emitter;\n this.conversationManager = conversationManager;\n }\n\n /** Send a message and wait for the complete response (with automatic retry) */\n async chat(message: string, options?: ChatOptions): Promise<ChatResponse> {\n const request = this.buildRequest(message, options);\n\n const response = await withRetry(\n () => this.provider.chat(request),\n {\n config: this.config.retry,\n logger: this.config.logger,\n signal: options?.signal,\n onRetry: (attempt, error, delayMs) => {\n this.emitter.emit('retry', attempt, error, delayMs);\n },\n },\n );\n\n // Auto-track conversation\n if (response.conversationId) {\n this.conversationManager.setActive(response.conversationId);\n }\n\n return response;\n }\n\n /** Send a message with streaming — returns an AgentStream */\n stream(message: string, options?: StreamOptions): AgentStream {\n const abortController = new AbortController();\n const request = this.buildRequest(message, options, abortController.signal);\n\n // The provider returns an AsyncIterable<StreamEvent>\n const source = this.provider.stream(request);\n\n // Emit stream.start\n this.emitter.emit('stream.start', options?.conversationId ?? null);\n\n const stream = new AgentStreamImpl(\n source,\n abortController,\n (event) => {\n // Auto-track conversation from meta event\n if (event.type === 'meta' && event.conversationId) {\n this.conversationManager.setActive(event.conversationId);\n }\n\n // Emit error/rateLimit events\n if (event.type === 'error') {\n const err = new ThaliqError(event.message, 'STREAM_ERROR');\n this.emitter.emit('error', err);\n }\n\n // Forward to user callback\n if (options?.onEvent) {\n options.onEvent(event);\n }\n },\n // onComplete callback for stream.end event\n (conversationId) => {\n this.emitter.emit('stream.end', conversationId);\n },\n );\n\n return stream;\n }\n\n /**\n * Respond to a pending HITL action and resume the conversation.\n *\n * This is a convenience method that creates a new stream with the\n * action response, continuing the conversation where it left off.\n *\n * @example\n * ```typescript\n * const stream = thaliq.agent.stream('Transfer $500');\n * for await (const event of stream) { ... }\n *\n * if (stream.pendingAction) {\n * const resumed = thaliq.agent.respondToAction({\n * conversationId: stream.conversationId!,\n * originalMessage: 'Transfer $500',\n * actionResponse: ActionResponseBuilder.accept(stream.pendingAction.instructionId),\n * });\n * for await (const event of resumed) { ... }\n * }\n * ```\n */\n respondToAction(options: RespondToActionOptions): AgentStream {\n return this.stream(options.originalMessage, {\n conversationId: options.conversationId,\n agentType: options.agentType,\n actionResponse: options.actionResponse,\n onEvent: options.onEvent,\n signal: options.signal,\n });\n }\n\n /** Build the ProviderRequest from message + options + identity */\n private buildRequest(\n message: string,\n options?: ChatOptions,\n abortSignal?: AbortSignal,\n ): ProviderRequest {\n const identity = this.getIdentity();\n const signal = options?.signal ?? abortSignal;\n\n return {\n message,\n conversationId: options?.conversationId,\n agentType: options?.agentType,\n actionResponse: options?.actionResponse,\n headers: this.resolveHeaders(identity),\n signal,\n timeout: this.config.timeout,\n };\n }\n\n /** Resolve all headers from config + identity */\n private resolveHeaders(identity: UserIdentity | null): ResolvedHeaders {\n const headers: ResolvedHeaders = {\n 'x-api-key': this.config.apiKey,\n 'x-integration-type': this.config.integrationType,\n };\n\n // Identity headers\n if (identity) {\n if (identity.userId) {\n headers['x-user-id'] = identity.userId;\n }\n if (identity.participantId) {\n headers['x-participant-id'] = identity.participantId;\n }\n if (identity.token) {\n headers['authorization'] = `Bearer ${identity.token}`;\n }\n if (identity.mcpTokens && Object.keys(identity.mcpTokens).length > 0) {\n headers['x-mcp-tokens'] = JSON.stringify(identity.mcpTokens);\n }\n }\n\n // Custom default headers\n for (const [key, value] of Object.entries(this.config.defaultHeaders)) {\n headers[key] = value;\n }\n\n return headers;\n }\n}\n","/**\n * ConversationManager — tracks active conversations and auto-assigns IDs.\n *\n * @example\n * ```typescript\n * const conv = thaliq.conversations.create();\n * console.log(conv.id); // UUID\n *\n * // After streaming, the active conversation is auto-tracked\n * const stream = thaliq.agent.stream('Hello', { conversationId: conv.id });\n * for await (const event of stream) { ... }\n *\n * console.log(thaliq.conversations.active); // conv.id\n * ```\n */\n\nimport type { ConversationRef } from '../types/conversations';\nimport { uuid } from '../utils/uuid';\n\nexport class ConversationManager {\n private _active: ConversationRef | null = null;\n private readonly _history: ConversationRef[] = [];\n\n /** Create a new conversation reference */\n create(): ConversationRef {\n const ref: ConversationRef = {\n id: uuid(),\n createdAt: new Date(),\n };\n this._history.push(ref);\n return ref;\n }\n\n /** Get the most recently active conversation */\n get active(): ConversationRef | null {\n return this._active;\n }\n\n /** Get all known conversation references (in-memory only) */\n get history(): readonly ConversationRef[] {\n return this._history;\n }\n\n /**\n * Set the active conversation by ID (called internally after stream completes).\n * If the ID matches an existing ref, that ref becomes active.\n * Otherwise a new ref is created.\n */\n setActive(conversationId: string): void {\n const existing = this._history.find(c => c.id === conversationId);\n if (existing) {\n this._active = existing;\n } else {\n const ref: ConversationRef = {\n id: conversationId,\n createdAt: new Date(),\n };\n this._history.push(ref);\n this._active = ref;\n }\n }\n\n /** Clear all state */\n clear(): void {\n this._active = null;\n this._history.length = 0;\n }\n}\n","/**\n * Generate a UUID v4 using crypto.randomUUID when available,\n * falling back to a manual implementation.\n */\nexport function uuid(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n\n // Fallback for environments without crypto.randomUUID\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n","/**\n * HTTP client wrapper for the Thaliq Native Provider.\n *\n * Handles fetch with timeout via AbortController,\n * error mapping from HTTP status codes, and response parsing.\n */\n\nimport {\n mapHttpError,\n TimeoutError,\n ConnectionError,\n} from '../../types/errors';\nimport type { Logger } from '../../types/config';\n\nexport interface HttpClientConfig {\n baseUrl: string;\n timeout: number;\n logger: Logger;\n}\n\nexport interface HttpRequestOptions {\n method: 'GET' | 'POST';\n path: string;\n headers: Record<string, string | undefined>;\n body?: unknown;\n signal?: AbortSignal;\n timeout: number;\n}\n\nexport class HttpClient {\n private readonly baseUrl: string;\n private readonly defaultTimeout: number;\n private readonly logger: Logger;\n\n constructor(config: HttpClientConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/+$/, '');\n this.defaultTimeout = config.timeout;\n this.logger = config.logger;\n }\n\n /** Execute a JSON request and return the parsed response */\n async json<T>(options: HttpRequestOptions): Promise<T> {\n const response = await this.rawFetch(options);\n\n if (!response.ok) {\n const body = await response.text().catch(() => 'Unknown error');\n let message: string;\n try {\n const parsed = JSON.parse(body);\n message = parsed.message ?? parsed.error ?? body;\n } catch {\n message = body;\n }\n throw mapHttpError(response.status, message, response.headers);\n }\n\n return response.json() as Promise<T>;\n }\n\n /** Execute a request and return the raw Response (for SSE streaming) */\n async stream(options: HttpRequestOptions): Promise<Response> {\n const response = await this.rawFetch(options);\n\n if (!response.ok) {\n const body = await response.text().catch(() => 'Unknown error');\n let message: string;\n try {\n const parsed = JSON.parse(body);\n message = parsed.message ?? parsed.error ?? body;\n } catch {\n message = body;\n }\n throw mapHttpError(response.status, message, response.headers);\n }\n\n return response;\n }\n\n /** Low-level fetch with timeout and error wrapping */\n private async rawFetch(options: HttpRequestOptions): Promise<Response> {\n const url = `${this.baseUrl}${options.path}`;\n const timeout = options.timeout ?? this.defaultTimeout;\n\n // Create a timeout controller that will abort if no external signal is provided\n const timeoutController = new AbortController();\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n // If the caller provided an AbortSignal, listen to it\n if (options.signal) {\n options.signal.addEventListener('abort', () => timeoutController.abort(options.signal?.reason), {\n once: true,\n });\n }\n\n timeoutId = setTimeout(() => {\n timeoutController.abort(new TimeoutError(`Request timed out after ${timeout}ms`));\n }, timeout);\n\n // Clean up headers: remove undefined values\n const headers: Record<string, string> = { 'content-type': 'application/json' };\n for (const [key, value] of Object.entries(options.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n\n this.logger.debug(`${options.method} ${url}`);\n\n try {\n const response = await fetch(url, {\n method: options.method,\n headers,\n body: options.body ? JSON.stringify(options.body) : undefined,\n signal: timeoutController.signal,\n });\n\n return response;\n } catch (error: unknown) {\n if (error instanceof TimeoutError) throw error;\n if (error instanceof DOMException && error.name === 'AbortError') {\n // Check if it was a timeout or user abort\n if (timeoutController.signal.reason instanceof TimeoutError) {\n throw timeoutController.signal.reason;\n }\n throw error;\n }\n throw new ConnectionError(\n error instanceof Error ? error.message : 'Connection failed',\n );\n } finally {\n if (timeoutId !== undefined) clearTimeout(timeoutId);\n }\n }\n}\n","/**\n * SSE (Server-Sent Events) parser.\n *\n * Converts a ReadableStream<Uint8Array> into an AsyncIterable of parsed SSE events.\n * Follows the SSE spec: each event is delimited by a blank line,\n * and fields are `event:`, `data:`, `id:`.\n */\n\nimport type { StreamEvent } from '../../types/events';\nimport type { PendingAction } from '../../types/actions';\n\ninterface RawSSEEvent {\n event: string;\n data: string;\n id: string;\n}\n\n/**\n * Parse a ReadableStream into SSE events.\n * Yields StreamEvent objects as they arrive.\n */\nexport async function* parseSSEStream(\n stream: ReadableStream<Uint8Array>,\n): AsyncIterable<StreamEvent> {\n const reader = stream.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n\n // Split on double newlines (SSE event delimiter)\n const parts = buffer.split('\\n\\n');\n // Keep the last part as buffer (may be incomplete)\n buffer = parts.pop() ?? '';\n\n for (const part of parts) {\n const raw = parseRawEvent(part);\n if (!raw) continue;\n\n const mapped = mapToStreamEvent(raw);\n if (mapped) yield mapped;\n }\n }\n\n // Process any remaining buffer\n if (buffer.trim()) {\n const raw = parseRawEvent(buffer);\n if (raw) {\n const mapped = mapToStreamEvent(raw);\n if (mapped) yield mapped;\n }\n }\n } finally {\n reader.releaseLock();\n }\n}\n\n/** Parse raw SSE text block into event/data/id fields */\nfunction parseRawEvent(block: string): RawSSEEvent | null {\n let event = '';\n let data = '';\n let id = '';\n\n const lines = block.split('\\n');\n for (const line of lines) {\n if (line.startsWith('event:')) {\n event = line.slice(6).trim();\n } else if (line.startsWith('data:')) {\n data = line.slice(5).trim();\n } else if (line.startsWith('id:')) {\n id = line.slice(3).trim();\n }\n // Lines starting with ':' are comments, ignored\n }\n\n if (!event && !data) return null;\n\n return { event, data, id };\n}\n\n/** Map a raw SSE event to a typed StreamEvent */\nfunction mapToStreamEvent(raw: RawSSEEvent): StreamEvent | null {\n const type = raw.event;\n\n try {\n const payload = raw.data ? JSON.parse(raw.data) : {};\n\n switch (type) {\n case 'meta':\n return {\n type: 'meta',\n conversationId: payload.conversationId,\n };\n\n case 'status':\n return {\n type: 'status',\n text: payload.text,\n };\n\n case 'content.delta':\n return {\n type: 'content.delta',\n delta: payload.delta,\n };\n\n case 'tool.start':\n return {\n type: 'tool.start',\n tool: payload.tool,\n };\n\n case 'tool.end':\n return {\n type: 'tool.end',\n tool: payload.tool,\n success: payload.success,\n };\n\n case 'action':\n return {\n type: 'action',\n action: payload as PendingAction,\n };\n\n case 'response.completed':\n return {\n type: 'response.completed',\n message: payload.message,\n conversationId: payload.conversationId,\n insights: payload.insights ?? [],\n metadata: payload.metadata,\n };\n\n case 'error':\n return {\n type: 'error',\n message: payload.message,\n };\n\n case 'keepalive':\n return {\n type: 'keepalive',\n ts: payload.ts,\n };\n\n default:\n // Unknown event type — skip\n return null;\n }\n } catch {\n // Malformed JSON — skip\n return null;\n }\n}\n","/**\n * ThaliqNativeProvider — Default provider that communicates with the Thaliq API.\n *\n * - chat() → POST /api/agent/chat\n * - stream() → GET /api/agent/stream (SSE)\n */\n\nimport type { Provider, ProviderRequest } from '../../types/provider';\nimport type { ChatResponse } from '../../types/responses';\nimport type { StreamEvent } from '../../types/events';\nimport type { Logger } from '../../types/config';\nimport { StreamError } from '../../types/errors';\nimport { HttpClient } from './http-client';\nimport { parseSSEStream } from './sse-parser';\n\nexport interface ThaliqNativeProviderConfig {\n baseUrl: string;\n timeout: number;\n logger: Logger;\n}\n\nexport class ThaliqNativeProvider implements Provider {\n readonly name = 'thaliq-native';\n private readonly http: HttpClient;\n private readonly logger: Logger;\n\n constructor(config: ThaliqNativeProviderConfig) {\n this.logger = config.logger;\n this.http = new HttpClient({\n baseUrl: config.baseUrl,\n timeout: config.timeout,\n logger: config.logger,\n });\n }\n\n /** POST /api/agent/chat — non-streaming */\n async chat(request: ProviderRequest): Promise<ChatResponse> {\n const body: Record<string, unknown> = {\n message: request.message,\n };\n\n if (request.conversationId) body['conversationId'] = request.conversationId;\n if (request.agentType) body['agentType'] = request.agentType;\n if (request.actionResponse) body['actionResponse'] = request.actionResponse;\n\n return this.http.json<ChatResponse>({\n method: 'POST',\n path: '/api/agent/chat',\n headers: request.headers,\n body,\n signal: request.signal,\n timeout: request.timeout,\n });\n }\n\n /** GET /api/agent/stream — SSE streaming */\n async *stream(request: ProviderRequest): AsyncIterable<StreamEvent> {\n // Build query string\n const params = new URLSearchParams();\n params.set('q', request.message);\n if (request.conversationId) params.set('conversationId', request.conversationId);\n if (request.agentType) params.set('agentType', request.agentType);\n if (request.actionResponse) {\n params.set('actionResponse', JSON.stringify(request.actionResponse));\n }\n\n const response = await this.http.stream({\n method: 'GET',\n path: `/api/agent/stream?${params.toString()}`,\n headers: {\n ...request.headers,\n accept: 'text/event-stream',\n },\n signal: request.signal,\n timeout: request.timeout,\n });\n\n if (!response.body) {\n throw new StreamError('Response body is null — streaming not supported');\n }\n\n this.logger.debug('SSE stream connected');\n\n yield* parseSSEStream(response.body);\n }\n}\n","/**\n * Typed EventEmitter — zero-dependency, type-safe event system.\n *\n * @example\n * ```typescript\n * const emitter = new TypedEventEmitter<SDKEventMap>();\n * emitter.on('error', (err) => console.error(err));\n * emitter.once('identify', (userId) => console.log('Identified:', userId));\n * ```\n */\n\n/** Callback function type */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype Callback = (...args: any[]) => void;\n\n/** Typed listener with optional _once flag */\ntype Listener = Callback & { _once?: boolean };\n\nexport class TypedEventEmitter<T extends { [K in keyof T]: Callback }> {\n private readonly _listeners = new Map<keyof T, Set<Listener>>();\n\n /** Register a listener for an event */\n on<K extends keyof T>(event: K, listener: T[K]): this {\n if (!this._listeners.has(event)) {\n this._listeners.set(event, new Set());\n }\n this._listeners.get(event)!.add(listener as Listener);\n return this;\n }\n\n /** Register a one-time listener */\n once<K extends keyof T>(event: K, listener: T[K]): this {\n const wrapped = listener as Listener;\n wrapped._once = true;\n return this.on(event, listener);\n }\n\n /** Remove a listener */\n off<K extends keyof T>(event: K, listener: T[K]): this {\n const set = this._listeners.get(event);\n if (set) {\n set.delete(listener as Listener);\n if (set.size === 0) {\n this._listeners.delete(event);\n }\n }\n return this;\n }\n\n /** Emit an event to all registered listeners */\n emit<K extends keyof T>(event: K, ...args: Parameters<T[K]>): void {\n const set = this._listeners.get(event);\n if (!set) return;\n\n for (const listener of set) {\n listener(...args);\n if (listener._once) {\n set.delete(listener);\n }\n }\n\n if (set.size === 0) {\n this._listeners.delete(event);\n }\n }\n\n /** Remove all listeners for an event, or all listeners if no event specified */\n removeAllListeners(event?: keyof T): this {\n if (event) {\n this._listeners.delete(event);\n } else {\n this._listeners.clear();\n }\n return this;\n }\n\n /** Get the count of listeners for a specific event */\n listenerCount(event: keyof T): number {\n return this._listeners.get(event)?.size ?? 0;\n }\n}\n","/**\n * Default console-based logger with level filtering.\n */\n\nimport type { Logger, LogLevel } from '../types/config';\n\nconst LEVEL_ORDER: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n silent: 4,\n};\n\nexport function createDefaultLogger(minLevel: LogLevel): Logger {\n const min = LEVEL_ORDER[minLevel];\n\n return {\n debug(message: string, ...args: unknown[]) {\n if (min <= LEVEL_ORDER.debug) console.debug(`[thaliq] ${message}`, ...args);\n },\n info(message: string, ...args: unknown[]) {\n if (min <= LEVEL_ORDER.info) console.info(`[thaliq] ${message}`, ...args);\n },\n warn(message: string, ...args: unknown[]) {\n if (min <= LEVEL_ORDER.warn) console.warn(`[thaliq] ${message}`, ...args);\n },\n error(message: string, ...args: unknown[]) {\n if (min <= LEVEL_ORDER.error) console.error(`[thaliq] ${message}`, ...args);\n },\n };\n}\n","/**\n * Thaliq — Main SDK client class.\n *\n * @example\n * ```typescript\n * import { Thaliq } from '@thaliq/sdk';\n *\n * const thaliq = new Thaliq({ apiKey: 'tq_live_xxx' });\n *\n * // Events\n * thaliq.on('error', (err) => console.error(err));\n * thaliq.on('retry', (attempt, err, delay) => console.warn(`Retry #${attempt}`));\n *\n * // Identify user (B2B)\n * thaliq.identify({ userId: 'usr_123', email: 'user@company.com' });\n *\n * // Chat\n * const response = await thaliq.agent.chat('Hello!');\n *\n * // Stream\n * const stream = thaliq.agent.stream('Analyze Q4 sales');\n * for await (const event of stream) {\n * if (event.type === 'content.delta') process.stdout.write(event.delta);\n * }\n *\n * // Conversations are auto-tracked\n * console.log(thaliq.conversations.active);\n * ```\n */\n\nimport type { ThaliqConfig, ResolvedConfig, SDKEventMap } from './types/config';\nimport type { UserIdentity } from './types/identity';\nimport type { Provider } from './types/provider';\nimport { ValidationError } from './types/errors';\nimport { AgentClient } from './agent/agent-client';\nimport { ConversationManager } from './agent/conversation-manager';\nimport { ThaliqNativeProvider } from './providers/thaliq-native';\nimport { TypedEventEmitter } from './utils/event-emitter';\nimport { createDefaultLogger } from './utils/logger';\n\nconst DEFAULT_BASE_URL = 'https://api.thaliq.com';\nconst DEFAULT_TIMEOUT = 30_000;\nconst DEFAULT_MAX_RETRIES = 2;\nconst DEFAULT_BASE_DELAY = 500;\nconst DEFAULT_MAX_DELAY = 10_000;\n\nexport class Thaliq {\n private readonly config: ResolvedConfig;\n private readonly provider: Provider;\n private readonly emitter = new TypedEventEmitter<SDKEventMap>();\n private identity: UserIdentity | null = null;\n\n /** Agent client — use `thaliq.agent.chat()` and `thaliq.agent.stream()` */\n readonly agent: AgentClient;\n\n /** Conversations manager — create, track, and list conversations */\n readonly conversations: ConversationManager;\n\n constructor(userConfig: ThaliqConfig) {\n this.config = resolveConfig(userConfig);\n this.provider = userConfig.provider ?? new ThaliqNativeProvider({\n baseUrl: this.config.baseUrl,\n timeout: this.config.timeout,\n logger: this.config.logger,\n });\n\n this.conversations = new ConversationManager();\n\n this.agent = new AgentClient(\n this.config,\n this.provider,\n () => this.identity,\n this.emitter,\n this.conversations,\n );\n }\n\n /** Register an event listener */\n on<K extends keyof SDKEventMap>(event: K, listener: SDKEventMap[K]): this {\n this.emitter.on(event, listener);\n return this;\n }\n\n /** Register a one-time event listener */\n once<K extends keyof SDKEventMap>(event: K, listener: SDKEventMap[K]): this {\n this.emitter.once(event, listener);\n return this;\n }\n\n /** Remove an event listener */\n off<K extends keyof SDKEventMap>(event: K, listener: SDKEventMap[K]): this {\n this.emitter.off(event, listener);\n return this;\n }\n\n /** Set the user identity for subsequent requests */\n identify(user: UserIdentity): void {\n if (!user.userId) {\n throw new ValidationError('userId is required for identify()');\n }\n this.identity = user;\n this.config.logger.info(`User identified: ${user.userId}`);\n this.emitter.emit('identify', user.userId);\n }\n\n /** Clear user identity and local state */\n reset(): void {\n this.identity = null;\n this.conversations.clear();\n this.config.logger.info('SDK state reset');\n this.emitter.emit('reset');\n }\n}\n\n/** Merge user config with defaults */\nfunction resolveConfig(config: ThaliqConfig): ResolvedConfig {\n if (!config.apiKey) {\n throw new ValidationError('apiKey is required');\n }\n\n const logLevel = config.logLevel ?? 'warn';\n const logger = config.logger ?? createDefaultLogger(logLevel);\n const maxRetries = config.maxRetries ?? config.retry?.maxRetries ?? DEFAULT_MAX_RETRIES;\n\n return {\n apiKey: config.apiKey,\n baseUrl: (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, ''),\n integrationType: config.integrationType ?? 'sdk',\n timeout: config.timeout ?? DEFAULT_TIMEOUT,\n maxRetries,\n retry: {\n maxRetries,\n baseDelay: config.retry?.baseDelay ?? DEFAULT_BASE_DELAY,\n maxDelay: config.retry?.maxDelay ?? DEFAULT_MAX_DELAY,\n },\n logger,\n logLevel,\n defaultHeaders: config.defaultHeaders ?? {},\n };\n}\n","/**\n * ActionResponseBuilder — helpers for constructing ActionResponse objects.\n *\n * Provides static factory methods for each HITL action type,\n * so developers don't need to manually build ActionResponse objects.\n *\n * @example\n * ```typescript\n * import { ActionResponseBuilder } from '@thaliq/sdk';\n *\n * // Accept a consent/confirm action\n * const accept = ActionResponseBuilder.accept('inst_123');\n *\n * // Reject an action\n * const reject = ActionResponseBuilder.reject('inst_123');\n *\n * // Select an option\n * const select = ActionResponseBuilder.select('inst_123', 'option_a');\n *\n * // Submit a form\n * const form = ActionResponseBuilder.submitForm('inst_123', {\n * amount: '500',\n * currency: 'USD',\n * });\n * ```\n */\n\nimport type { ActionResponse } from '../types/actions';\n\nexport class ActionResponseBuilder {\n /**\n * Accept a consent or confirm action.\n *\n * @param instructionId - The instruction ID from `pendingAction.instructionId`\n */\n static accept(instructionId: string): ActionResponse {\n return { instructionId, accepted: true };\n }\n\n /**\n * Reject a consent or confirm action.\n *\n * @param instructionId - The instruction ID from `pendingAction.instructionId`\n */\n static reject(instructionId: string): ActionResponse {\n return { instructionId, accepted: false };\n }\n\n /**\n * Select an option from a select action.\n *\n * @param instructionId - The instruction ID from `pendingAction.instructionId`\n * @param value - The selected option value\n */\n static select(instructionId: string, value: string): ActionResponse {\n return { instructionId, accepted: true, selectedValue: value };\n }\n\n /**\n * Submit form values for a form action.\n *\n * @param instructionId - The instruction ID from `pendingAction.instructionId`\n * @param values - Key-value map of form field names to values\n */\n static submitForm(instructionId: string, values: Record<string, string>): ActionResponse {\n return { instructionId, accepted: true, formValues: values };\n }\n}\n"],"names":["ThaliqError","Error","constructor","message","code","status","super","this","name","AuthError","RateLimitError","retryAfter","ValidationError","ServiceError","StreamError","TimeoutError","ConnectionError","mapHttpError","headers","get","parseInt","AgentStreamImpl","source","abortController","onEvent","onComplete","_conversationId","_status","_pendingAction","_consumed","_source","_abortController","_onEvent","_onComplete","conversationId","pendingAction","abort","Symbol","asyncIterator","event","type","action","finalResponse","metadata","insights","delta","response","model","promptTokens","completionTokens","processingTimeMs","generatedAt","Date","toISOString","text","accumulated","isRetryableError","error","calculateBackoff","attempt","baseDelay","maxDelay","exponential","Math","pow","clamped","min","jitter","random","floor","sleep","ms","Promise","resolve","setTimeout","async","withRetry","fn","options","config","logger","onRetry","signal","lastError","maxRetries","aborted","delayMs","warn","AgentClient","provider","getIdentity","emitter","conversationManager","chat","request","buildRequest","retry","emit","setActive","stream","AbortController","err","respondToAction","originalMessage","agentType","actionResponse","abortSignal","identity","resolveHeaders","timeout","apiKey","integrationType","userId","participantId","token","mcpTokens","Object","keys","length","JSON","stringify","key","value","entries","defaultHeaders","ConversationManager","_active","_history","create","ref","id","crypto","randomUUID","replace","c","r","toString","createdAt","push","active","history","existing","find","clear","HttpClient","baseUrl","defaultTimeout","json","rawFetch","ok","body","catch","parsed","parse","url","path","timeoutController","timeoutId","addEventListener","reason","once","debug","method","fetch","DOMException","clearTimeout","parseRawEvent","block","data","lines","split","line","startsWith","slice","trim","mapToStreamEvent","raw","payload","tool","success","ts","ThaliqNativeProvider","http","params","URLSearchParams","set","accept","reader","getReader","decoder","TextDecoder","buffer","done","read","decode","parts","pop","part","mapped","releaseLock","parseSSEStream","TypedEventEmitter","_listeners","Map","on","listener","has","Set","add","_once","off","delete","size","args","removeAllListeners","listenerCount","LEVEL_ORDER","info","silent","DEFAULT_BASE_URL","instructionId","accepted","reject","select","selectedValue","submitForm","values","formValues","userConfig","logLevel","minLevel","console","createDefaultLogger","resolveConfig","conversations","agent","identify","user","reset"],"mappings":"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"}