feat(sdk): P2.5 @insignia/iios-kernel-client — REST + socket facade
MessageSocket (open/send/read/typing via emitWithAck, reconnect re-opens thread, no socket.io types leak) + RestClient (ingest/getThreadMessages/sendMessage). tsup ESM+dts. Facade unit test with injectable fake socket (3 tests). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
import type { IngestInteractionRequest } from '@insignia/iios-contracts';
|
||||
import type { Message } from './types';
|
||||
|
||||
export interface RestConfig {
|
||||
serviceUrl: string;
|
||||
token?: string;
|
||||
}
|
||||
|
||||
/** REST/polling client for kernel reads and the native-send fallback. */
|
||||
export class RestClient {
|
||||
constructor(private readonly config: RestConfig) {}
|
||||
|
||||
private url(path: string): string {
|
||||
return `${this.config.serviceUrl.replace(/\/$/, '')}${path}`;
|
||||
}
|
||||
|
||||
private headers(extra: Record<string, string> = {}): Record<string, string> {
|
||||
const h: Record<string, string> = { 'content-type': 'application/json', ...extra };
|
||||
if (this.config.token) h.authorization = `Bearer ${this.config.token}`;
|
||||
return h;
|
||||
}
|
||||
|
||||
async getThreadMessages(threadId: string): Promise<{ threadId: string; messages: unknown[] }> {
|
||||
const r = await fetch(this.url(`/v1/threads/${threadId}/messages`), { headers: this.headers() });
|
||||
if (!r.ok) throw new Error(`getThreadMessages ${r.status}`);
|
||||
return (await r.json()) as { threadId: string; messages: unknown[] };
|
||||
}
|
||||
|
||||
async sendMessage(
|
||||
threadId: string,
|
||||
content: string,
|
||||
opts?: { contentRef?: string; idempotencyKey?: string },
|
||||
): Promise<Message> {
|
||||
const r = await fetch(this.url(`/v1/threads/${threadId}/messages`), {
|
||||
method: 'POST',
|
||||
headers: this.headers(opts?.idempotencyKey ? { 'idempotency-key': opts.idempotencyKey } : {}),
|
||||
body: JSON.stringify({ content, contentRef: opts?.contentRef }),
|
||||
});
|
||||
if (!r.ok) throw new Error(`sendMessage ${r.status}`);
|
||||
return (await r.json()) as Message;
|
||||
}
|
||||
|
||||
async ingest(body: IngestInteractionRequest, idempotencyKey: string): Promise<unknown> {
|
||||
const r = await fetch(this.url('/v1/interactions/ingest'), {
|
||||
method: 'POST',
|
||||
headers: this.headers({ 'idempotency-key': idempotencyKey }),
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
if (!r.ok) throw new Error(`ingest ${r.status}`);
|
||||
return r.json();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user