feat: channels on the direct-IIOS path — kernel-client + KernelClientAdapter
- iios-kernel-client: RestClient.discoverThreads (GET /v1/threads/discover) + leaveThread (DELETE /v1/threads/:id/me); DiscoveredThread type - KernelClientAdapter implements the four channel methods: browseChannels maps discovered public channels → ChannelSummary; createChannel → createThread (membership=channel, ADMIN, visibility/topic metadata); joinChannel → socket.openThread (governed public self-join); leaveChannel → rest.leaveThread - adapter channel test over the fake transport (13 kernel-adapter tests); 57 green Co-Authored-By: Claude Opus 4.8 <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, RouteBinding, RouteDecision, AiArtifact, AiJobResult, Meeting, MeetingActionItem, ThreadSummary, SavedItem, LoginResult } from './types';
|
||||
import type { Message, InboxItem, InboxState, Ticket, TicketState, CallbackRequest, RouteBinding, RouteDecision, AiArtifact, AiJobResult, Meeting, MeetingActionItem, ThreadSummary, DiscoveredThread, SavedItem, LoginResult } from './types';
|
||||
|
||||
export interface RestConfig {
|
||||
serviceUrl: string;
|
||||
@@ -103,6 +103,27 @@ export class RestClient {
|
||||
return this.post<{ threadId: string }>('/v1/threads', opts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Discover threads across your scope matching an opaque metadata filter (e.g. browse public
|
||||
* channels: `{ membership: 'channel', visibility: 'public' }`). Returns ones you have NOT joined
|
||||
* too, each flagged `joined`.
|
||||
*/
|
||||
async discoverThreads(filter?: { metadata?: Record<string, string> }): Promise<DiscoveredThread[]> {
|
||||
const qs = filter?.metadata
|
||||
? '?' + Object.entries(filter.metadata).map(([k, v]) => `metadata[${encodeURIComponent(k)}]=${encodeURIComponent(v)}`).join('&')
|
||||
: '';
|
||||
const r = await fetch(this.url(`/v1/threads/discover${qs}`), { headers: this.headers() });
|
||||
if (!r.ok) throw new Error(`discoverThreads ${r.status}`);
|
||||
return (await r.json()) as DiscoveredThread[];
|
||||
}
|
||||
|
||||
/** Self-leave a thread (e.g. leave a channel). */
|
||||
async leaveThread(threadId: string): Promise<{ threadId: string; participantCount: number }> {
|
||||
const r = await fetch(this.url(`/v1/threads/${threadId}/me`), { method: 'DELETE', headers: this.headers() });
|
||||
if (!r.ok) throw new Error(`leaveThread ${r.status}`);
|
||||
return (await r.json()) as { threadId: string; participantCount: number };
|
||||
}
|
||||
|
||||
/** My saved messages (personal bookmarks), newest first, with thread context. */
|
||||
async listSaved(): Promise<SavedItem[]> {
|
||||
const r = await fetch(this.url('/v1/threads/my-annotations?type=save'), { headers: this.headers() });
|
||||
|
||||
Reference in New Issue
Block a user