feat(p6): kernel-client route methods + @insignia/iios-community-web SDK
Task 6.5: add createBinding/listBindings/simulateRoute/listRouteDecisions/ approveDecision/denyDecision to RestClient + RouteBinding/RouteDecision types. New @insignia/iios-community-web package (CommunityProvider, useBindings, useRoutePreview, useRouteDecisions). Boundary allowlist: community-web -> contracts + kernel-client. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import type { IngestInteractionRequest } from '@insignia/iios-contracts';
|
||||
import type { Message, InboxItem, InboxState, Ticket, TicketState, CallbackRequest } from './types';
|
||||
import type { Message, InboxItem, InboxState, Ticket, TicketState, CallbackRequest, RouteBinding, RouteDecision } from './types';
|
||||
|
||||
export interface RestConfig {
|
||||
serviceUrl: string;
|
||||
@@ -100,6 +100,30 @@ export class RestClient {
|
||||
return r.json();
|
||||
}
|
||||
|
||||
// ─── routing (P6) ─────────────────────────────────────────────
|
||||
async createBinding(input: Partial<RouteBinding>): Promise<RouteBinding> {
|
||||
return this.post<RouteBinding>('/v1/routes/bindings', input);
|
||||
}
|
||||
async listBindings(): Promise<RouteBinding[]> {
|
||||
const r = await fetch(this.url('/v1/routes/bindings'), { headers: this.headers() });
|
||||
if (!r.ok) throw new Error(`listBindings ${r.status}`);
|
||||
return (await r.json()) as RouteBinding[];
|
||||
}
|
||||
async simulateRoute(input: { interactionId: string; originChannelType: string; originRef?: string }): Promise<{ simulationId: string; decisions: RouteDecision[] }> {
|
||||
return this.post('/v1/routes/simulate', input);
|
||||
}
|
||||
async listRouteDecisions(state?: string): Promise<RouteDecision[]> {
|
||||
const r = await fetch(this.url(`/v1/routes/decisions${state ? `?state=${state}` : ''}`), { headers: this.headers() });
|
||||
if (!r.ok) throw new Error(`listRouteDecisions ${r.status}`);
|
||||
return (await r.json()) as RouteDecision[];
|
||||
}
|
||||
async approveDecision(id: string): Promise<RouteDecision> {
|
||||
return this.post<RouteDecision>(`/v1/routes/decisions/${id}/approve`, {});
|
||||
}
|
||||
async denyDecision(id: string): Promise<RouteDecision> {
|
||||
return this.post<RouteDecision>(`/v1/routes/decisions/${id}/deny`, {});
|
||||
}
|
||||
|
||||
private async post<T>(path: string, body: unknown): Promise<T> {
|
||||
const r = await fetch(this.url(path), { method: 'POST', headers: this.headers(), body: JSON.stringify(body) });
|
||||
if (!r.ok) throw new Error(`POST ${path} ${r.status}`);
|
||||
|
||||
@@ -77,6 +77,31 @@ export interface CallbackRequest {
|
||||
preferChannel: string;
|
||||
}
|
||||
|
||||
export interface RouteBinding {
|
||||
id: string;
|
||||
originChannelType: string;
|
||||
originRef?: string | null;
|
||||
destinationChannelType: string;
|
||||
destinationRef?: string | null;
|
||||
restrictionProfile?: string | null;
|
||||
mode: string;
|
||||
outputFormat: string;
|
||||
requiresReview: boolean;
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
export interface RouteDecision {
|
||||
id: string;
|
||||
interactionId: string;
|
||||
routeBindingId: string;
|
||||
decisionState: string;
|
||||
reasonCodes: string[];
|
||||
previewPayload: { text?: string; destinationRef?: string | null; format?: string } | unknown;
|
||||
outputFormat: string;
|
||||
executed: boolean;
|
||||
routeBinding?: RouteBinding;
|
||||
}
|
||||
|
||||
/** Minimal socket surface so the facade can be unit-tested with a fake. */
|
||||
export interface SocketLike {
|
||||
on(event: string, handler: (...args: unknown[]) => void): unknown;
|
||||
|
||||
Reference in New Issue
Block a user