@firststep-studio/sdk 0.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.
- package/README.md +40 -0
- package/dist/index.d.mts +299 -0
- package/dist/index.d.ts +299 -0
- package/dist/index.js +238 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +204 -0
- package/dist/index.mjs.map +1 -0
- package/dist/server.d.mts +77 -0
- package/dist/server.d.ts +77 -0
- package/dist/server.js +312 -0
- package/dist/server.js.map +1 -0
- package/dist/server.mjs +287 -0
- package/dist/server.mjs.map +1 -0
- package/dist/types-Bm98aHcd.d.mts +438 -0
- package/dist/types-Bm98aHcd.d.ts +438 -0
- package/llms.txt +597 -0
- package/package.json +45 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server.ts","../src/auth.ts"],"sourcesContent":["/**\n * FirstStep SDK Server\n *\n * Standalone HTTP server for protocol handlers.\n * Zero external dependencies, uses Node.js built-in `http` module.\n *\n * @example\n * ```typescript\n * import { createServer } from '@firststep-studio/sdk/server';\n * import type { ProtocolHandler } from '@firststep-studio/sdk';\n *\n * const handler: ProtocolHandler = {\n * async handleMessage(request, context) {\n * return {\n * message: 'Hello from my handler!',\n * sessionId: request.sessionId || 'new',\n * agentId: 'main',\n * sessionStatus: 'active',\n * };\n * },\n * getCapabilities() {\n * return { streaming: false, formQuestions: false, knowledgeActions: false, integrations: false };\n * },\n * };\n *\n * const server = createServer(handler, {\n * token: process.env.FIRSTSTEP_TOKEN!,\n * port: 3001,\n * });\n *\n * server.start();\n * ```\n */\n\nimport { createServer as createHttpServer, IncomingMessage, ServerResponse } from 'http';\nimport type {\n ProtocolHandler,\n ProtocolRequest,\n ProtocolContext,\n ProtocolCapabilities,\n ProtocolStreamChunk,\n} from './types';\nimport { verifyRequestSignature } from './auth';\n\n// ============================================\n// Configuration\n// ============================================\n\nexport interface ServerConfig {\n /** API token (FIRSTSTEP_TOKEN). Used for request signature verification. */\n token: string;\n\n /** Port to listen on. Defaults to 3001, or the PORT env variable. */\n port?: number;\n\n /** Host to bind to. Defaults to '0.0.0.0'. */\n host?: string;\n\n /** Skip signature verification (for local development only). */\n skipSignatureVerification?: boolean;\n}\n\n// ============================================\n// Server Instance\n// ============================================\n\nexport interface FirstStepServer {\n /** Start the server */\n start(): Promise<void>;\n\n /** Stop the server gracefully */\n stop(): Promise<void>;\n\n /**\n * Get the request handler function.\n * Use this to integrate with Express, Fastify, or other frameworks.\n *\n * @example\n * ```typescript\n * // Express\n * const server = createServer(handler, { token: '...' });\n * app.post('/handshake', server.getRequestHandler());\n * app.post('/message', server.getRequestHandler());\n * ```\n */\n getRequestHandler(): (req: IncomingMessage, res: ServerResponse) => void;\n}\n\n// ============================================\n// Internal Helpers\n// ============================================\n\nfunction readBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n req.on('data', (chunk: Buffer) => chunks.push(chunk));\n req.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));\n req.on('error', reject);\n });\n}\n\nfunction sendJson(res: ServerResponse, status: number, body: unknown): void {\n const json = JSON.stringify(body);\n res.writeHead(status, {\n 'Content-Type': 'application/json',\n 'Content-Length': Buffer.byteLength(json),\n 'Access-Control-Allow-Origin': '*',\n });\n res.end(json);\n}\n\nfunction parsePath(url: string | undefined): string {\n if (!url) return '/';\n const idx = url.indexOf('?');\n return idx >= 0 ? url.substring(0, idx) : url;\n}\n\n/**\n * Build a stub ProtocolContext for external handlers.\n *\n * External handlers receive context data as plain JSON from the platform.\n * The stub provides no-op implementations for methods like session.getState()\n * since those will be handled by callback APIs to the FirstStep backend.\n *\n * When the platform sends a /message request, the request body includes\n * a `context` field with serialized context data. This function merges\n * that data with no-op method stubs.\n */\nfunction buildStubContext(data?: Partial<ProtocolContext>): ProtocolContext {\n const noopAsync = async () => ({} as any);\n const noop = () => {};\n\n return {\n session: {\n sessionId: '',\n getState: noopAsync,\n updateState: noopAsync,\n getHistory: async () => [],\n saveMessage: noopAsync,\n complete: noopAsync,\n getFormData: async () => ({}),\n updateFormField: noopAsync,\n updateFormData: noopAsync,\n ...data?.session,\n },\n knowledge: {\n queryDatabase: noopAsync,\n searchPages: noopAsync,\n ...data?.knowledge,\n },\n integrations: {\n execute: noopAsync,\n ...data?.integrations,\n },\n analytics: {\n logActionExecuted: noop,\n logInteraction: noop,\n logCustomEvent: noop,\n ...data?.analytics,\n },\n logger: {\n debug: noop,\n info: noop,\n warn: noop,\n error: noop,\n logRouting: noop,\n logToolUse: noop,\n ...data?.logger,\n },\n deployment: {\n id: '',\n slug: '',\n name: '',\n protocolType: 'external',\n ...data?.deployment,\n },\n chatbot: data?.chatbot,\n };\n}\n\n// ============================================\n// createServer\n// ============================================\n\n/**\n * Create a standalone HTTP server for a protocol handler.\n *\n * The server exposes three endpoints:\n * - `GET /health` - Health check (always 200)\n * - `POST /handshake` - Returns handler capabilities (signature verified)\n * - `POST /message` - Handles a chat message (signature verified)\n */\nexport function createServer(\n handler: ProtocolHandler,\n config: ServerConfig\n): FirstStepServer {\n const {\n token,\n port = parseInt(process.env.PORT || '3001', 10),\n host = '0.0.0.0',\n skipSignatureVerification = false,\n } = config;\n\n // Validate config\n if (!token && !skipSignatureVerification) {\n throw new Error(\n 'FIRSTSTEP_TOKEN is required. Pass it via config.token or set skipSignatureVerification for local dev.'\n );\n }\n\n /**\n * Core request router\n */\n async function handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const path = parsePath(req.url);\n const method = (req.method || 'GET').toUpperCase();\n\n // CORS preflight\n if (method === 'OPTIONS') {\n res.writeHead(204, {\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',\n 'Access-Control-Allow-Headers': 'Content-Type, Authorization, X-FirstStep-Signature',\n 'Access-Control-Max-Age': '86400',\n });\n res.end();\n return;\n }\n\n // Health check\n if (path === '/health' && method === 'GET') {\n sendJson(res, 200, { status: 'ok', timestamp: Date.now() });\n return;\n }\n\n // Handshake\n if (path === '/handshake' && method === 'POST') {\n const body = await readBody(req);\n\n if (!skipSignatureVerification) {\n const signature = req.headers['x-firststep-signature'] as string;\n if (!signature || !verifyRequestSignature(token, body, signature)) {\n sendJson(res, 401, { error: 'Invalid signature' });\n return;\n }\n }\n\n const capabilities: ProtocolCapabilities = handler.getCapabilities();\n const handlerInfo = handler.getHandlerInfo?.();\n sendJson(res, 200, { capabilities, handler: handlerInfo || undefined });\n return;\n }\n\n // Message\n if (path === '/message' && method === 'POST') {\n const body = await readBody(req);\n\n if (!skipSignatureVerification) {\n const signature = req.headers['x-firststep-signature'] as string;\n if (!signature || !verifyRequestSignature(token, body, signature)) {\n sendJson(res, 401, { error: 'Invalid signature' });\n return;\n }\n }\n\n let parsed: { request: ProtocolRequest; context?: Partial<ProtocolContext> };\n try {\n parsed = JSON.parse(body);\n } catch {\n sendJson(res, 400, { error: 'Invalid JSON body' });\n return;\n }\n\n const context = buildStubContext(parsed.context);\n\n try {\n const response = await handler.handleMessage(parsed.request, context);\n sendJson(res, 200, response);\n } catch (err: any) {\n console.error('[firststep] Handler error:', err);\n sendJson(res, 500, {\n error: 'Handler error',\n message: err?.message || 'Unknown error',\n });\n }\n return;\n }\n\n // Message (streaming via SSE)\n if (path === '/message/stream' && method === 'POST') {\n const body = await readBody(req);\n\n if (!skipSignatureVerification) {\n const signature = req.headers['x-firststep-signature'] as string;\n if (!signature || !verifyRequestSignature(token, body, signature)) {\n sendJson(res, 401, { error: 'Invalid signature' });\n return;\n }\n }\n\n let parsed: { request: ProtocolRequest; context?: Partial<ProtocolContext> };\n try {\n parsed = JSON.parse(body);\n } catch {\n sendJson(res, 400, { error: 'Invalid JSON body' });\n return;\n }\n\n if (!handler.handleStream) {\n // Fallback: use non-streaming handleMessage, send as single SSE burst\n const context = buildStubContext(parsed.context);\n try {\n const response = await handler.handleMessage(parsed.request, context);\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive',\n 'Access-Control-Allow-Origin': '*',\n });\n const sendSSE = (event: string, data: unknown) => {\n res.write(`event: ${event}\\ndata: ${JSON.stringify(data)}\\n\\n`);\n };\n sendSSE('connected', { sessionId: response.sessionId });\n sendSSE('text', { type: 'text', content: response.message, sessionId: response.sessionId });\n if (response.metadata) {\n sendSSE('metadata', { type: 'metadata', content: response.metadata, sessionId: response.sessionId });\n }\n if (response.form) {\n sendSSE('form', { type: 'form', content: response.form, sessionId: response.sessionId });\n }\n sendSSE('status', { type: 'status', content: response.sessionStatus, sessionId: response.sessionId });\n sendSSE('done', { sessionId: response.sessionId });\n res.end();\n } catch (err: any) {\n console.error('[firststep] Handler error:', err);\n sendJson(res, 500, { error: 'Handler error', message: err?.message || 'Unknown error' });\n }\n return;\n }\n\n const context = buildStubContext(parsed.context);\n\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive',\n 'Access-Control-Allow-Origin': '*',\n });\n\n const sendSSE = (event: string, data: unknown) => {\n res.write(`event: ${event}\\ndata: ${JSON.stringify(data)}\\n\\n`);\n };\n\n const sessionId = parsed.request.sessionId || `ext-${Date.now()}`;\n sendSSE('connected', { sessionId });\n\n try {\n for await (const chunk of handler.handleStream(parsed.request, context)) {\n sendSSE(chunk.type, {\n type: chunk.type,\n content: chunk.content,\n sessionId,\n });\n }\n sendSSE('done', { sessionId });\n } catch (err: any) {\n console.error('[firststep] Stream error:', err);\n sendSSE('error', { code: 'STREAM_ERROR', message: err?.message || 'Unknown error' });\n }\n\n res.end();\n return;\n }\n\n // 404\n sendJson(res, 404, { error: 'Not found' });\n }\n\n // Wrap in error boundary\n function requestListener(req: IncomingMessage, res: ServerResponse): void {\n handleRequest(req, res).catch((err) => {\n console.error('[firststep] Unexpected error:', err);\n if (!res.headersSent) {\n sendJson(res, 500, { error: 'Internal server error' });\n }\n });\n }\n\n const httpServer = createHttpServer(requestListener);\n\n return {\n start() {\n return new Promise<void>((resolve) => {\n httpServer.listen(port, host, () => {\n console.log(`[firststep] Handler server listening on ${host}:${port}`);\n console.log(`[firststep] Endpoints:`);\n console.log(` GET /health - Health check`);\n console.log(` POST /handshake - Capability exchange`);\n console.log(` POST /message - Handle chat message`);\n console.log(` POST /message/stream - Handle chat message (SSE stream)`);\n resolve();\n });\n });\n },\n\n stop() {\n return new Promise<void>((resolve, reject) => {\n httpServer.close((err) => {\n if (err) reject(err);\n else resolve();\n });\n });\n },\n\n getRequestHandler() {\n return requestListener;\n },\n };\n}\n","import { createHmac, timingSafeEqual } from 'crypto';\n\nconst TOKEN_PREFIX = 'fst_';\nconst TOKEN_LENGTH = 44; // fst_ (4) + 40 hex chars\n\n/**\n * Verify an HMAC-SHA256 request signature.\n *\n * The handler server can use this to verify that incoming webhook\n * requests were signed by the FirstStep platform using the shared token.\n *\n * @param token - The API token (FIRSTSTEP_TOKEN)\n * @param payload - The raw request body string\n * @param signature - The signature from the X-FirstStep-Signature header\n * @returns true if the signature is valid\n *\n * @example\n * ```typescript\n * import { verifyRequestSignature } from '@firststep-studio/sdk';\n *\n * app.post('/webhook', (req, res) => {\n * const signature = req.headers['x-firststep-signature'] as string;\n * if (!verifyRequestSignature(process.env.FIRSTSTEP_TOKEN!, req.body, signature)) {\n * return res.status(401).send('Invalid signature');\n * }\n * // Process the request...\n * });\n * ```\n */\nexport function verifyRequestSignature(\n token: string,\n payload: string,\n signature: string\n): boolean {\n try {\n const expected = createHmac('sha256', token)\n .update(payload)\n .digest('hex');\n const expectedBuffer = Buffer.from(expected, 'hex');\n const signatureBuffer = Buffer.from(signature, 'hex');\n\n if (expectedBuffer.length !== signatureBuffer.length) {\n return false;\n }\n\n return timingSafeEqual(expectedBuffer, signatureBuffer);\n } catch {\n return false;\n }\n}\n\n/**\n * Create an HMAC-SHA256 signature for a payload.\n *\n * Used by the platform to sign outgoing requests to handler servers.\n *\n * @param token - The API token\n * @param payload - The request body string to sign\n * @returns The hex-encoded HMAC signature\n */\nexport function createRequestSignature(\n token: string,\n payload: string\n): string {\n return createHmac('sha256', token).update(payload).digest('hex');\n}\n\n/**\n * Create an Authorization header value for API requests.\n *\n * @param token - The API token (fst_xxx)\n * @returns The header value, e.g. \"Bearer fst_xxx\"\n *\n * @example\n * ```typescript\n * import { createAuthHeader } from '@firststep-studio/sdk';\n *\n * const response = await fetch('https://api.firststep.ai/api/projects', {\n * headers: {\n * 'Authorization': createAuthHeader(process.env.FIRSTSTEP_TOKEN!),\n * },\n * });\n * ```\n */\nexport function createAuthHeader(token: string): string {\n return `Bearer ${token}`;\n}\n\n/**\n * Validate that a token has the correct format (fst_ prefix + 40 hex chars).\n *\n * @param token - The token string to validate\n * @returns true if the token matches the expected format\n */\nexport function isValidToken(token: string): boolean {\n return (\n typeof token === 'string' &&\n token.startsWith(TOKEN_PREFIX) &&\n token.length === TOKEN_LENGTH\n );\n}\n"],"mappings":"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","names":["context","sendSSE"]}
|
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FirstStep Protocol SDK Types
|
|
3
|
+
*
|
|
4
|
+
* Implement this interface to communicate with FirstStep Studio.
|
|
5
|
+
* GuidedForm is the built-in implementation of this interface.
|
|
6
|
+
*/
|
|
7
|
+
interface ProtocolRequest {
|
|
8
|
+
/**
|
|
9
|
+
* User message.
|
|
10
|
+
* Optional - if not provided, this is a session initialization request
|
|
11
|
+
* and the handler should return the initial message (welcome/form).
|
|
12
|
+
*/
|
|
13
|
+
message?: string;
|
|
14
|
+
/** Session ID (new session created if not provided) */
|
|
15
|
+
sessionId?: string;
|
|
16
|
+
/** Deployment slug */
|
|
17
|
+
deploymentSlug: string;
|
|
18
|
+
/** Additional metadata */
|
|
19
|
+
metadata?: Record<string, unknown>;
|
|
20
|
+
}
|
|
21
|
+
interface ProtocolResponse {
|
|
22
|
+
/** AI response message */
|
|
23
|
+
message: string;
|
|
24
|
+
/** Session ID */
|
|
25
|
+
sessionId: string;
|
|
26
|
+
/** Current agent ID */
|
|
27
|
+
agentId: string;
|
|
28
|
+
/** Session status */
|
|
29
|
+
sessionStatus: SessionStatus;
|
|
30
|
+
/** Form rendering info (optional) */
|
|
31
|
+
form?: ProtocolForm;
|
|
32
|
+
/** Response metadata */
|
|
33
|
+
metadata?: Record<string, unknown>;
|
|
34
|
+
}
|
|
35
|
+
type SessionStatus = 'active' | 'completed' | 'error';
|
|
36
|
+
interface ProtocolForm {
|
|
37
|
+
/** Form type */
|
|
38
|
+
type: 'question' | 'closing' | 'custom';
|
|
39
|
+
/** Question ID */
|
|
40
|
+
questionId?: string;
|
|
41
|
+
/** Form fields */
|
|
42
|
+
fields: ProtocolFormField[];
|
|
43
|
+
/** Form metadata */
|
|
44
|
+
metadata?: Record<string, unknown>;
|
|
45
|
+
}
|
|
46
|
+
interface ProtocolFormField {
|
|
47
|
+
/** Field ID */
|
|
48
|
+
id: string;
|
|
49
|
+
/** Field type */
|
|
50
|
+
type: 'text' | 'textarea' | 'select' | 'multiselect' | 'date' | 'number' | 'email' | 'phone';
|
|
51
|
+
/** Display label */
|
|
52
|
+
label: string;
|
|
53
|
+
/** Placeholder text */
|
|
54
|
+
placeholder?: string;
|
|
55
|
+
/** Options for select/multiselect */
|
|
56
|
+
options?: ProtocolFormOption[];
|
|
57
|
+
/** Required flag */
|
|
58
|
+
required?: boolean;
|
|
59
|
+
/** Validation rules */
|
|
60
|
+
validation?: ProtocolFieldValidation;
|
|
61
|
+
}
|
|
62
|
+
interface ProtocolFormOption {
|
|
63
|
+
value: string;
|
|
64
|
+
label: string;
|
|
65
|
+
}
|
|
66
|
+
interface ProtocolFieldValidation {
|
|
67
|
+
pattern?: string;
|
|
68
|
+
minLength?: number;
|
|
69
|
+
maxLength?: number;
|
|
70
|
+
min?: number;
|
|
71
|
+
max?: number;
|
|
72
|
+
message?: string;
|
|
73
|
+
}
|
|
74
|
+
interface ProtocolStreamChunk {
|
|
75
|
+
/** Chunk type */
|
|
76
|
+
type: 'text' | 'form' | 'status' | 'error' | 'metadata';
|
|
77
|
+
/** Chunk content */
|
|
78
|
+
content: string | ProtocolForm | SessionStatus | ProtocolError | Record<string, unknown>;
|
|
79
|
+
}
|
|
80
|
+
interface ProtocolError {
|
|
81
|
+
code: string;
|
|
82
|
+
message: string;
|
|
83
|
+
details?: Record<string, unknown>;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Protocol Handler Interface
|
|
87
|
+
*
|
|
88
|
+
* Implement this interface to work as a FirstStep Studio Protocol.
|
|
89
|
+
* GuidedForm is the built-in implementation of this interface.
|
|
90
|
+
*/
|
|
91
|
+
interface ProtocolHandler {
|
|
92
|
+
/**
|
|
93
|
+
* Handle message (non-streaming)
|
|
94
|
+
*/
|
|
95
|
+
handleMessage(request: ProtocolRequest, context: ProtocolContext): Promise<ProtocolResponse>;
|
|
96
|
+
/**
|
|
97
|
+
* Handle message (streaming)
|
|
98
|
+
*/
|
|
99
|
+
handleStream?(request: ProtocolRequest, context: ProtocolContext): AsyncGenerator<ProtocolStreamChunk>;
|
|
100
|
+
/**
|
|
101
|
+
* Declare handler capabilities
|
|
102
|
+
*/
|
|
103
|
+
getCapabilities(): ProtocolCapabilities;
|
|
104
|
+
/**
|
|
105
|
+
* Handler metadata returned during handshake.
|
|
106
|
+
* Used to auto-fill project name and description on registration.
|
|
107
|
+
*/
|
|
108
|
+
getHandlerInfo?(): HandlerInfo;
|
|
109
|
+
}
|
|
110
|
+
interface HandlerInfo {
|
|
111
|
+
/** Handler display name */
|
|
112
|
+
name: string;
|
|
113
|
+
/** Handler description */
|
|
114
|
+
description?: string;
|
|
115
|
+
}
|
|
116
|
+
interface ProtocolCapabilities {
|
|
117
|
+
/** Streaming support */
|
|
118
|
+
streaming: boolean;
|
|
119
|
+
/** Form questions support */
|
|
120
|
+
formQuestions: boolean;
|
|
121
|
+
/** Knowledge actions usage */
|
|
122
|
+
knowledgeActions: boolean;
|
|
123
|
+
/** Integrations usage */
|
|
124
|
+
integrations: boolean;
|
|
125
|
+
/** Custom capabilities */
|
|
126
|
+
custom?: Record<string, boolean>;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Platform Context
|
|
130
|
+
*
|
|
131
|
+
* Interface for handlers to access FirstStep Studio features:
|
|
132
|
+
* - Session management
|
|
133
|
+
* - Knowledge base queries
|
|
134
|
+
* - Integration calls
|
|
135
|
+
* - Analytics tracking
|
|
136
|
+
* - Logging
|
|
137
|
+
*/
|
|
138
|
+
interface ProtocolContext {
|
|
139
|
+
/** Session management */
|
|
140
|
+
session: SessionContext;
|
|
141
|
+
/** Knowledge base access */
|
|
142
|
+
knowledge: KnowledgeContext;
|
|
143
|
+
/** Integration access */
|
|
144
|
+
integrations: IntegrationContext;
|
|
145
|
+
/** Analytics tracking */
|
|
146
|
+
analytics: AnalyticsContext;
|
|
147
|
+
/** Logging */
|
|
148
|
+
logger: LoggerContext;
|
|
149
|
+
/** Deployment info */
|
|
150
|
+
deployment: DeploymentInfo;
|
|
151
|
+
/** Chatbot info (for GuidedForm) */
|
|
152
|
+
chatbot?: ChatbotInfo;
|
|
153
|
+
}
|
|
154
|
+
interface SessionContext {
|
|
155
|
+
/** Session ID */
|
|
156
|
+
sessionId: string;
|
|
157
|
+
/** Get session state */
|
|
158
|
+
getState(): Promise<SessionState>;
|
|
159
|
+
/** Update session state */
|
|
160
|
+
updateState(updates: Partial<SessionState>): Promise<void>;
|
|
161
|
+
/** Get message history */
|
|
162
|
+
getHistory(): Promise<ChatMessage[]>;
|
|
163
|
+
/** Save message */
|
|
164
|
+
saveMessage(message: ChatMessage): Promise<void>;
|
|
165
|
+
/** Complete session */
|
|
166
|
+
complete(): Promise<void>;
|
|
167
|
+
/** Get all collected form data */
|
|
168
|
+
getFormData(): Promise<FormData>;
|
|
169
|
+
/** Update a single form field */
|
|
170
|
+
updateFormField(fieldId: string, value: FormFieldValue): Promise<void>;
|
|
171
|
+
/** Update multiple form fields */
|
|
172
|
+
updateFormData(fields: Record<string, FormFieldValue>): Promise<void>;
|
|
173
|
+
}
|
|
174
|
+
interface SessionState {
|
|
175
|
+
sessionId: string;
|
|
176
|
+
deploymentId: string;
|
|
177
|
+
currentAgentId?: string;
|
|
178
|
+
/** Current question being asked (for proper answer tracking) */
|
|
179
|
+
currentQuestionId?: string;
|
|
180
|
+
/** Internal form data storage (handler-specific format) */
|
|
181
|
+
formData?: Record<string, unknown>;
|
|
182
|
+
metadata?: SessionMetadata;
|
|
183
|
+
createdAt: Date;
|
|
184
|
+
updatedAt: Date;
|
|
185
|
+
}
|
|
186
|
+
interface ChatMessage {
|
|
187
|
+
role: 'user' | 'assistant' | 'system';
|
|
188
|
+
content: string;
|
|
189
|
+
agentId?: string;
|
|
190
|
+
timestamp?: Date;
|
|
191
|
+
metadata?: Record<string, unknown>;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* FormData - Collected user responses
|
|
195
|
+
*
|
|
196
|
+
* Standard format for all protocol handlers.
|
|
197
|
+
* Used for KPI calculation and session analytics.
|
|
198
|
+
*/
|
|
199
|
+
interface FormData {
|
|
200
|
+
[fieldId: string]: FormFieldValue;
|
|
201
|
+
}
|
|
202
|
+
interface FormFieldValue {
|
|
203
|
+
/** The collected value */
|
|
204
|
+
value: string | string[] | number | boolean | null;
|
|
205
|
+
/** When this field was answered */
|
|
206
|
+
answeredAt?: Date;
|
|
207
|
+
/** Which agent collected this (for GuidedForm) */
|
|
208
|
+
agentId?: string;
|
|
209
|
+
/** Raw user response before processing */
|
|
210
|
+
rawResponse?: string;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* RoutingLog - Record of routing decisions
|
|
214
|
+
*
|
|
215
|
+
* Stored automatically when context.logger.logRouting() is called.
|
|
216
|
+
*/
|
|
217
|
+
interface RoutingLog {
|
|
218
|
+
/** When the routing decision was made */
|
|
219
|
+
timestamp: Date;
|
|
220
|
+
/** Decision type (e.g., 'FIRST_MESSAGE', 'CLASSIFIER_ROUTING') */
|
|
221
|
+
decision: string;
|
|
222
|
+
/** Human-readable reason */
|
|
223
|
+
reason: string;
|
|
224
|
+
/** Source agent */
|
|
225
|
+
fromAgent?: string;
|
|
226
|
+
/** Target agent */
|
|
227
|
+
toAgent: string;
|
|
228
|
+
/** Classification result if applicable */
|
|
229
|
+
classification?: {
|
|
230
|
+
category?: string;
|
|
231
|
+
level?: string;
|
|
232
|
+
confidence?: number;
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* SessionMetadata - Session-level analytics data
|
|
237
|
+
*
|
|
238
|
+
* Automatically tracked by the platform.
|
|
239
|
+
*/
|
|
240
|
+
interface SessionMetadata {
|
|
241
|
+
turnCount?: number;
|
|
242
|
+
totalMessages?: number;
|
|
243
|
+
userMessageCount?: number;
|
|
244
|
+
durationSeconds?: number;
|
|
245
|
+
startedAt?: Date;
|
|
246
|
+
endedAt?: Date;
|
|
247
|
+
lastActivityAt?: Date;
|
|
248
|
+
userAgent?: string;
|
|
249
|
+
ipAddress?: string;
|
|
250
|
+
referrer?: string;
|
|
251
|
+
source?: string;
|
|
252
|
+
language?: string;
|
|
253
|
+
timezone?: string;
|
|
254
|
+
knowledgeActionExecuted?: boolean;
|
|
255
|
+
helplineActionExecuted?: boolean;
|
|
256
|
+
executedKnowledgeIds?: string[];
|
|
257
|
+
helplineSmsClicked?: string;
|
|
258
|
+
helplineCallClicked?: string;
|
|
259
|
+
helplineWebsiteClicked?: string;
|
|
260
|
+
knowledgeLinkClicked?: string;
|
|
261
|
+
announcementCtaClicked?: boolean;
|
|
262
|
+
zendeskTicketId?: string;
|
|
263
|
+
zendeskTicketUrl?: string;
|
|
264
|
+
completed?: boolean;
|
|
265
|
+
completedAt?: string;
|
|
266
|
+
custom?: Record<string, unknown>;
|
|
267
|
+
}
|
|
268
|
+
interface KnowledgeContext {
|
|
269
|
+
/** Query database knowledge */
|
|
270
|
+
queryDatabase(knowledgeId: string, query: string): Promise<KnowledgeResult>;
|
|
271
|
+
/** Search page knowledge */
|
|
272
|
+
searchPages(knowledgeId: string, query: string): Promise<KnowledgeResult>;
|
|
273
|
+
}
|
|
274
|
+
interface KnowledgeResult {
|
|
275
|
+
success: boolean;
|
|
276
|
+
records?: Record<string, unknown>[];
|
|
277
|
+
error?: string;
|
|
278
|
+
}
|
|
279
|
+
interface IntegrationContext {
|
|
280
|
+
/** Execute integration */
|
|
281
|
+
execute(integrationId: string, params: Record<string, unknown>): Promise<IntegrationResult>;
|
|
282
|
+
/** Search helplines (Throughline) */
|
|
283
|
+
searchHelplines?(query: string, options?: HelplineSearchOptions): Promise<HelplineResult>;
|
|
284
|
+
}
|
|
285
|
+
interface IntegrationResult {
|
|
286
|
+
success: boolean;
|
|
287
|
+
data?: Record<string, unknown>;
|
|
288
|
+
error?: string;
|
|
289
|
+
}
|
|
290
|
+
interface HelplineSearchOptions {
|
|
291
|
+
country?: string;
|
|
292
|
+
topics?: string[];
|
|
293
|
+
limit?: number;
|
|
294
|
+
}
|
|
295
|
+
interface HelplineResult {
|
|
296
|
+
success: boolean;
|
|
297
|
+
helplines?: Helpline[];
|
|
298
|
+
error?: string;
|
|
299
|
+
}
|
|
300
|
+
interface Helpline {
|
|
301
|
+
name: string;
|
|
302
|
+
phone?: string;
|
|
303
|
+
website?: string;
|
|
304
|
+
description?: string;
|
|
305
|
+
}
|
|
306
|
+
interface LoggerContext {
|
|
307
|
+
debug(message: string, data?: Record<string, unknown>): void;
|
|
308
|
+
info(message: string, data?: Record<string, unknown>): void;
|
|
309
|
+
warn(message: string, data?: Record<string, unknown>): void;
|
|
310
|
+
error(message: string, data?: Record<string, unknown>): void;
|
|
311
|
+
/** Log routing decision */
|
|
312
|
+
logRouting(decision: RoutingDecision): void;
|
|
313
|
+
/** Log tool usage */
|
|
314
|
+
logToolUse(tool: string, params: Record<string, unknown>, result: unknown): void;
|
|
315
|
+
}
|
|
316
|
+
interface RoutingDecision {
|
|
317
|
+
decision: string;
|
|
318
|
+
reason: string;
|
|
319
|
+
fromAgent?: string;
|
|
320
|
+
toAgent: string;
|
|
321
|
+
timestamp: Date;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Analytics Context
|
|
325
|
+
*
|
|
326
|
+
* Track user interactions and action executions.
|
|
327
|
+
* Data is stored in SessionMetadata for KPI/reporting.
|
|
328
|
+
*/
|
|
329
|
+
interface AnalyticsContext {
|
|
330
|
+
/**
|
|
331
|
+
* Log action execution
|
|
332
|
+
* Tracks when knowledge, helpline, or integration actions are executed.
|
|
333
|
+
*/
|
|
334
|
+
logActionExecuted(type: 'knowledge' | 'helpline' | 'integration', actionId: string, metadata?: Record<string, unknown>): void;
|
|
335
|
+
/**
|
|
336
|
+
* Log user interaction
|
|
337
|
+
* Tracks clicks on helplines, knowledge links, CTAs, etc.
|
|
338
|
+
*/
|
|
339
|
+
logInteraction(event: InteractionEvent): void;
|
|
340
|
+
/**
|
|
341
|
+
* Log custom event
|
|
342
|
+
* For handler-specific analytics.
|
|
343
|
+
*/
|
|
344
|
+
logCustomEvent(eventName: string, data?: Record<string, unknown>): void;
|
|
345
|
+
}
|
|
346
|
+
interface InteractionEvent {
|
|
347
|
+
/** Event type */
|
|
348
|
+
type: InteractionEventType;
|
|
349
|
+
/** Target identifier (e.g., helpline name, knowledge ID) */
|
|
350
|
+
targetId?: string;
|
|
351
|
+
/** Additional event data */
|
|
352
|
+
metadata?: Record<string, unknown>;
|
|
353
|
+
/** Event timestamp (auto-filled if not provided) */
|
|
354
|
+
timestamp?: Date;
|
|
355
|
+
}
|
|
356
|
+
type InteractionEventType = 'helpline_sms_click' | 'helpline_call_click' | 'helpline_website_click' | 'knowledge_link_click' | 'announcement_cta_click' | 'card_click' | 'form_submit' | 'custom';
|
|
357
|
+
/**
|
|
358
|
+
* FormSchema - Defines what data a protocol handler collects
|
|
359
|
+
*
|
|
360
|
+
* Registered when a protocol is set up.
|
|
361
|
+
* Used for analytics, validation, and dashboard display.
|
|
362
|
+
*/
|
|
363
|
+
interface FormSchema {
|
|
364
|
+
/** Schema version for migrations */
|
|
365
|
+
version?: string;
|
|
366
|
+
/** Field definitions */
|
|
367
|
+
fields: FormFieldDefinition[];
|
|
368
|
+
}
|
|
369
|
+
interface FormFieldDefinition {
|
|
370
|
+
/** Unique field identifier */
|
|
371
|
+
id: string;
|
|
372
|
+
/** Display name */
|
|
373
|
+
name: string;
|
|
374
|
+
/** Field type */
|
|
375
|
+
type: FormFieldType;
|
|
376
|
+
/** Options for select/multiselect */
|
|
377
|
+
options?: string[];
|
|
378
|
+
/** Whether this field is required */
|
|
379
|
+
required?: boolean;
|
|
380
|
+
/** Which agent owns this field (for GuidedForm) */
|
|
381
|
+
agentId?: string;
|
|
382
|
+
/** Field description for documentation */
|
|
383
|
+
description?: string;
|
|
384
|
+
/** Display order */
|
|
385
|
+
order?: number;
|
|
386
|
+
}
|
|
387
|
+
type FormFieldType = 'text' | 'number' | 'date' | 'boolean' | 'select' | 'multiselect' | 'email' | 'phone' | 'url';
|
|
388
|
+
/**
|
|
389
|
+
* Protocol Registration
|
|
390
|
+
*
|
|
391
|
+
* Configuration for registering a protocol handler.
|
|
392
|
+
*/
|
|
393
|
+
interface ProtocolRegistration {
|
|
394
|
+
/** Unique slug identifier */
|
|
395
|
+
slug: string;
|
|
396
|
+
/** Display name */
|
|
397
|
+
name: string;
|
|
398
|
+
/** Description */
|
|
399
|
+
description?: string;
|
|
400
|
+
/** External handler endpoint URL (for external handlers) */
|
|
401
|
+
endpoint?: string;
|
|
402
|
+
/** Form schema - what data this handler collects */
|
|
403
|
+
formSchema?: FormSchema;
|
|
404
|
+
/** Handler capabilities */
|
|
405
|
+
capabilities?: ProtocolCapabilities;
|
|
406
|
+
/** Whether this is a built-in handler */
|
|
407
|
+
builtIn?: boolean;
|
|
408
|
+
}
|
|
409
|
+
interface DeploymentInfo {
|
|
410
|
+
id: string;
|
|
411
|
+
slug: string;
|
|
412
|
+
name: string;
|
|
413
|
+
protocolType: string;
|
|
414
|
+
metadata?: Record<string, unknown>;
|
|
415
|
+
}
|
|
416
|
+
interface ChatbotInfo {
|
|
417
|
+
id: string;
|
|
418
|
+
name: string;
|
|
419
|
+
/** GuidedForm only - full config including agents, questions, etc. */
|
|
420
|
+
config?: Record<string, unknown>;
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Classifier configuration for protocol handlers
|
|
424
|
+
*
|
|
425
|
+
* Classifiers can be configured as:
|
|
426
|
+
* - Local: classifierId points to a classifier in the FirstStep database
|
|
427
|
+
* - Remote: classifierId is a full UCP endpoint URL
|
|
428
|
+
*/
|
|
429
|
+
interface ClassifierConfig {
|
|
430
|
+
/** Classifier ID or UCP endpoint URL */
|
|
431
|
+
classifierId: string;
|
|
432
|
+
/** API key for remote UCP endpoints (optional) */
|
|
433
|
+
apiKey?: string;
|
|
434
|
+
/** Whether classification is required for routing */
|
|
435
|
+
required?: boolean;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
export type { AnalyticsContext as A, FormFieldType as B, ChatMessage as C, DeploymentInfo as D, ProtocolRegistration as E, FormData as F, HandlerInfo as H, IntegrationContext as I, KnowledgeContext as K, LoggerContext as L, ProtocolRequest as P, RoutingDecision as R, SessionStatus as S, ProtocolResponse as a, ProtocolForm as b, ProtocolFormField as c, ProtocolFormOption as d, ProtocolFieldValidation as e, ProtocolStreamChunk as f, ProtocolError as g, ProtocolHandler as h, ProtocolCapabilities as i, ProtocolContext as j, SessionContext as k, SessionState as l, KnowledgeResult as m, IntegrationResult as n, HelplineSearchOptions as o, HelplineResult as p, Helpline as q, ChatbotInfo as r, ClassifierConfig as s, FormFieldValue as t, RoutingLog as u, SessionMetadata as v, InteractionEvent as w, InteractionEventType as x, FormSchema as y, FormFieldDefinition as z };
|