@zooid/transport-matrix 0.12.0 → 0.14.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/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { TransportContextProvider, HistoryOptions, HistoryPage, ThreadOverviewPage, Member, ChannelInfo, RoomBinding, AcpRegistry, ApprovalCorrelator } from '@zooid/core';
1
+ import { TransportContextProvider, RoomBinding, HistoryOptions, HistoryPage, ThreadOverviewPage, Member, RoomInfo, SendMessageInput as SendMessageInput$1, SendMessageResult, AcpRegistry, ApprovalCorrelator, PendingInputRegistry, TaskActions, InvocationRecord, ThreadCompletion, ThreadStartContent } from '@zooid/core';
2
2
  import * as hono_types from 'hono/types';
3
3
  import { Hono } from 'hono';
4
4
 
@@ -16,12 +16,14 @@ interface SendMessageInput {
16
16
  [k: string]: unknown;
17
17
  };
18
18
  threadRoot?: string;
19
+ txnId?: string;
19
20
  }
20
21
  interface SendCustomEventInput {
21
22
  roomId: string;
22
23
  asUserId: string;
23
24
  eventType: string;
24
25
  content: Record<string, unknown>;
26
+ txnId?: string;
25
27
  }
26
28
  interface SetTypingInput {
27
29
  roomId: string;
@@ -177,10 +179,30 @@ declare class MatrixClient {
177
179
 
178
180
  interface MatrixContextProviderOpts {
179
181
  client: MatrixClient;
180
- /** AS sender_localpart user (read access). */
182
+ /**
183
+ * The **agent's own** Matrix user (`@{workstation}.{name}:server`), which
184
+ * every read is impersonated as via `?user_id=`. Not the AS bot: that would
185
+ * read every room on the homeserver and make this class the only thing
186
+ * standing between an agent and someone else's conversation.
187
+ *
188
+ * This is load-bearing. It is what makes the homeserver — not our own
189
+ * bookkeeping — the authorization boundary for context reads, so a room or
190
+ * thread the agent is not in fails at Matrix with 403/404. Anything that
191
+ * widens who can name a room (a CLI, a new tool parameter) is safe only
192
+ * while this holds.
193
+ */
181
194
  asUserId: string;
182
195
  /** Map of Matrix user IDs → agent names, for is_agent / agent_name flags. */
183
196
  agentBots: Map<string, string>;
197
+ /**
198
+ * This agent's own room bindings — the live array `BotPool.bootstrap`
199
+ * rewrites `.alias` on in place, so reads through this field after
200
+ * bootstrap see canonical room IDs. Backs `getRooms()` and the
201
+ * `sendMessage()` authorization check. Absent/empty = no rooms known
202
+ * (context providers built before this field existed, or in tests that
203
+ * don't exercise either method).
204
+ */
205
+ rooms?: RoomBinding[];
184
206
  }
185
207
  declare class MatrixContextProvider implements TransportContextProvider {
186
208
  private readonly opts;
@@ -190,7 +212,9 @@ declare class MatrixContextProvider implements TransportContextProvider {
190
212
  getThreadHistory(channelId: string, threadId: string, hopts: HistoryOptions): Promise<HistoryPage>;
191
213
  private toMessage;
192
214
  getChannelMembers(channelId: string): Promise<Member[]>;
193
- getChannelInfo(channelId: string): Promise<ChannelInfo>;
215
+ getRoomInfo(channelId: string): Promise<RoomInfo>;
216
+ getRooms(): Promise<RoomInfo[]>;
217
+ sendMessage(input: SendMessageInput$1): Promise<SendMessageResult>;
194
218
  }
195
219
 
196
220
  interface MatrixTransportConfig {
@@ -279,6 +303,10 @@ interface ThreadState {
279
303
  */
280
304
  handoffs: Record<string, string[]>;
281
305
  }
306
+ interface TaskThreadContext {
307
+ assignee: string;
308
+ isRoot: boolean;
309
+ }
282
310
  interface MaybeEvent {
283
311
  type?: string;
284
312
  room_id?: string;
@@ -292,7 +320,7 @@ interface MaybeEvent {
292
320
  };
293
321
  }
294
322
  type RouteMatch = AgentBinding;
295
- declare function route(event: MaybeEvent, agents: AgentBinding[], threadStates?: Map<string, ThreadState>): RouteMatch[];
323
+ declare function route(event: MaybeEvent, agents: AgentBinding[], threadStates?: Map<string, ThreadState>, task?: TaskThreadContext): RouteMatch[];
296
324
 
297
325
  interface BootstrapOpts {
298
326
  /** Invited to any newly-created room; absent = no invite. */
@@ -367,6 +395,69 @@ declare class SyncLoop {
367
395
  stop(): void;
368
396
  }
369
397
 
398
+ declare const MAX_OPEN_TASKS_PER_ROOM = 5;
399
+ type TaskPhase = 'reserved' | 'uncertain' | 'open' | 'closed';
400
+ interface TaskRecord {
401
+ taskId: string;
402
+ attemptId: string;
403
+ roomId: string;
404
+ assignee: string;
405
+ notify: 'caller' | 'none';
406
+ parent: {
407
+ agent: string;
408
+ threadRoot: string;
409
+ sessionKey: string;
410
+ generation: number;
411
+ };
412
+ phase: TaskPhase;
413
+ threadRoot?: string;
414
+ summary?: string;
415
+ runId?: string;
416
+ closedAt?: string;
417
+ }
418
+ interface PersistedTask extends Required<Pick<TaskRecord, 'taskId' | 'attemptId' | 'roomId' | 'assignee' | 'notify' | 'parent' | 'phase'>> {
419
+ threadRoot?: string;
420
+ summary?: string;
421
+ runId: string;
422
+ closedAt?: string;
423
+ }
424
+ interface TaskJournal {
425
+ load(): PersistedTask[];
426
+ save(tasks: PersistedTask[]): void;
427
+ }
428
+ declare class TaskRegistry {
429
+ private readonly opts;
430
+ private readonly tasks;
431
+ private readonly byRoot;
432
+ private readonly generations;
433
+ private readonly runIdValue;
434
+ constructor(opts?: {
435
+ maxOpenPerRoom?: number;
436
+ newId?: () => string;
437
+ journal?: TaskJournal;
438
+ runId?: string;
439
+ maxClosedRecords?: number;
440
+ });
441
+ private get max();
442
+ private get runId();
443
+ private save;
444
+ openCount(roomId: string): number;
445
+ reserve(input: Omit<TaskRecord, 'taskId' | 'attemptId' | 'phase' | 'threadRoot' | 'summary'>): TaskRecord | undefined;
446
+ activate(taskId: string, threadRoot: string): void;
447
+ abandon(taskId: string): void;
448
+ markUncertain(taskId: string): void;
449
+ adopt(attemptId: string, threadRoot: string): TaskRecord | undefined;
450
+ taskForRoot(threadRoot: string): TaskRecord | undefined;
451
+ openTaskFor(agent: string, root: string): TaskRecord | undefined;
452
+ recordSummary(id: string, summary: string): "recorded" | "already_recorded";
453
+ clearSummary(id: string): void;
454
+ close(id: string): boolean;
455
+ /** Reconcile records from a prior daemon run and retain closed roots for trust checks. */
456
+ restore(): TaskRecord[];
457
+ generationOf(agent: string, session: string): number;
458
+ bumpGeneration(agent: string, session: string): void;
459
+ }
460
+
370
461
  interface MediaClientLike {
371
462
  download(input: {
372
463
  mxcUri: string;
@@ -417,9 +508,16 @@ interface CreateMatrixTransportOptions {
417
508
  loadSince?: (agentUserId: string) => string | null;
418
509
  /** Pull mode: persist the `since` cursor after each sync poll. */
419
510
  saveSince?: (agentUserId: string, since: string) => void;
511
+ /** Durable lifecycle state; supplied by the daemon when it has a data directory. */
512
+ taskJournal?: TaskJournal;
513
+ taskRunId?: string;
514
+ pendingInput?: PendingInputRegistry;
515
+ /** Deferred-return fallback window. Defaults to `RETURN_GRACE_MS`. */
516
+ returnGraceMs?: number;
420
517
  }
421
518
  declare function createMatrixTransport(opts: CreateMatrixTransportOptions): {
422
519
  app: Hono<hono_types.BlankEnv, hono_types.BlankSchema, "/">;
520
+ taskActions: TaskActions;
423
521
  syncLoops: SyncLoop[] | undefined;
424
522
  bootstrap: (bootstrapOpts?: {
425
523
  spaceRoomId?: string;
@@ -565,4 +663,65 @@ declare class PendingMediaStore {
565
663
  drain(roomId: string, threadKey: string | undefined, sender: string): PendingMediaItem[];
566
664
  }
567
665
 
568
- export { AGENT_KEY_RE, type AgentBinding, BotPool, type CreateMatrixTransportOptions, type EnsureDefaultChannelOpts, type EnsureSpaceOpts, INLINE_IMAGE_MIMES, MAX_DOWNLOAD_BYTES, MAX_INLINE_IMAGE_BYTES, MAX_MEDIA_PER_TURN, MEDIA_MSGTYPES, MatrixClient, type MatrixClientOptions, MatrixContextProvider, type MatrixContextProviderOpts, type MatrixTransportConfig, type MaybeMessage, MediaClient, type MediaClientLike, type MediaClientOptions, type PendingMediaItem, PendingMediaStore, type PublishOpts, type PublisherHandle, type RouteMatch, SLUG_RE, type SendCustomEventInput, type SendMessageInput, type StartOpts as StartWorkforcePublisherOpts, type SyncClient, SyncLoop, type SyncLoopOptions, type SyncResponse, type WorkforceRoster, type WriteAttachmentInput, agentMxid, buildWorkforceRoster, createMatrixTransport, ensureDefaultChannel, ensureWorkforceSpace, extractMentions, isMediaMsgtype, isValidAgentKey, isValidWorkstation, parseMxcUri, publishWorkforce, renderRegistration, route, serverNameFromMxid, splitAgentLocalpart, startWorkforcePublisher, workstationUserNamespace, writeAttachment };
666
+ declare class InvocationRegistry {
667
+ private readonly opts;
668
+ private readonly records;
669
+ private readonly byCallee;
670
+ private readonly byEvent;
671
+ constructor(opts?: {
672
+ newId?: () => string;
673
+ });
674
+ open(input: Omit<InvocationRecord, 'invocationId' | 'state'>): InvocationRecord;
675
+ attachCallEvent(id: string, eventId: string, sessionKey: string): void;
676
+ get(id: string): InvocationRecord | undefined;
677
+ byCallEvent(eventId: string): InvocationRecord | undefined;
678
+ forCalleeSession(session: string): InvocationRecord | undefined;
679
+ outstandingFor(session: string): InvocationRecord[];
680
+ outstandingForTask(taskId: string): InvocationRecord[];
681
+ resolve(id: string): InvocationRecord | undefined;
682
+ cancelForTask(taskId: string): InvocationRecord[];
683
+ ancestorAgents(session: string): string[];
684
+ isOutstandingAncestor(session: string, agent: string): boolean;
685
+ }
686
+
687
+ /** ACP's stable prompt termination values (kept local to avoid an SDK runtime dep). */
688
+ type StopReason = 'end_turn' | 'max_tokens' | 'max_turn_requests' | 'refusal' | 'cancelled';
689
+ interface CompletionInputs {
690
+ agent: string;
691
+ threadId: string;
692
+ stopReason?: StopReason;
693
+ error?: unknown;
694
+ summary?: string;
695
+ prose?: string;
696
+ outstanding: number;
697
+ awaitingHuman: number;
698
+ }
699
+ type CompletionDecision = {
700
+ decision: 'stay_open';
701
+ reason: 'outstanding_handoff' | 'awaiting_human';
702
+ } | {
703
+ decision: 'finish';
704
+ completion: ThreadCompletion;
705
+ };
706
+ declare function evaluateCompletion(input: CompletionInputs): CompletionDecision;
707
+
708
+ type Admission = {
709
+ ok: true;
710
+ } | {
711
+ ok: false;
712
+ reason: string;
713
+ };
714
+ declare function checkDelegable(agentName: string, roomId: string, bindings: AgentBinding[]): Admission;
715
+ declare function buildAssignmentContent(input: {
716
+ assigneeUserId: string;
717
+ prompt: string;
718
+ start: ThreadStartContent;
719
+ }): {
720
+ msgtype: string;
721
+ body: string;
722
+ [key: string]: unknown;
723
+ };
724
+ declare function renderCompletionPrompt(c: ThreadCompletion): string;
725
+ declare function renderInvocationReturn(c: ThreadCompletion): string;
726
+
727
+ export { AGENT_KEY_RE, type AgentBinding, BotPool, type CompletionDecision, type CompletionInputs, type CreateMatrixTransportOptions, type EnsureDefaultChannelOpts, type EnsureSpaceOpts, INLINE_IMAGE_MIMES, InvocationRegistry, MAX_DOWNLOAD_BYTES, MAX_INLINE_IMAGE_BYTES, MAX_MEDIA_PER_TURN, MAX_OPEN_TASKS_PER_ROOM, MEDIA_MSGTYPES, MatrixClient, type MatrixClientOptions, MatrixContextProvider, type MatrixContextProviderOpts, type MatrixTransportConfig, type MaybeMessage, MediaClient, type MediaClientLike, type MediaClientOptions, type PendingMediaItem, PendingMediaStore, type PersistedTask, type PublishOpts, type PublisherHandle, type RouteMatch, SLUG_RE, type SendCustomEventInput, type SendMessageInput, type StartOpts as StartWorkforcePublisherOpts, type StopReason, type SyncClient, SyncLoop, type SyncLoopOptions, type SyncResponse, type TaskJournal, type TaskPhase, type TaskRecord, TaskRegistry, type WorkforceRoster, type WriteAttachmentInput, agentMxid, buildAssignmentContent, buildWorkforceRoster, checkDelegable, createMatrixTransport, ensureDefaultChannel, ensureWorkforceSpace, evaluateCompletion, extractMentions, isMediaMsgtype, isValidAgentKey, isValidWorkstation, parseMxcUri, publishWorkforce, renderCompletionPrompt, renderInvocationReturn, renderRegistration, route, serverNameFromMxid, splitAgentLocalpart, startWorkforcePublisher, workstationUserNamespace, writeAttachment };