@openchamber/sdk 2.5.3 → 2.6.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.
@@ -1,5 +1,6 @@
1
1
  import { z } from 'zod';
2
- import { BROWSER_CONTROL_ACTIONS, SOURCE_CONTROL_OUTBOUND_BODY_MAX, SOURCE_CONTROL_OUTBOUND_METHODS, SOURCE_CONTROL_OUTBOUND_REQUEST_HEADERS, SOURCE_CONTROL_PROVIDER_ERROR_MESSAGE_MAX, SOURCE_CONTROL_PROVIDER_METHODS, SOURCE_CONTROL_PROVIDER_RESPONSE_MAX, SOURCE_CONTROL_PROVIDER_TARGET_MAX, } from './service-providers.js';
2
+ import { BROWSER_CONTROL_ACTIONS, NOTIFICATIONS_PROVIDER_METHODS, SOURCE_CONTROL_OUTBOUND_BODY_MAX, SOURCE_CONTROL_OUTBOUND_METHODS, SOURCE_CONTROL_OUTBOUND_REQUEST_HEADERS, SOURCE_CONTROL_PROVIDER_ERROR_MESSAGE_MAX, SOURCE_CONTROL_PROVIDER_METHODS, SOURCE_CONTROL_PROVIDER_RESPONSE_MAX, SOURCE_CONTROL_PROVIDER_TARGET_MAX, TRACKER_PROVIDER_CONTAINERS_MAX, TRACKER_PROVIDER_LIST_MAX, TRACKER_PROVIDER_LIVE_SUMMARIES_MAX, TRACKER_PROVIDER_METHODS, } from './service-providers.js';
3
+ import { SESSION_EVENT_ERROR_MAX } from './session-events.js';
3
4
  /**
4
5
  * Host-side parse of what a browser provider answers. `data` stays whatever
5
6
  * the service produced: the host hands it to the agent as is, and only
@@ -9,6 +10,19 @@ export const browserProviderResultSchema = z.union([
9
10
  z.object({ ok: z.literal(true), data: z.object({}).passthrough() }),
10
11
  z.object({ ok: z.literal(false), error: z.string().min(1).max(2_000) }),
11
12
  ]);
13
+ /**
14
+ * Host-side parse of what a service answers a session event with. OpenChamber
15
+ * acts on nothing in it beyond logging a failure's `error`; an answer that does
16
+ * not parse is a failed delivery, never a delivered one.
17
+ */
18
+ export const sessionEventResultSchema = z.union([
19
+ z.object({ ok: z.literal(true) }).strict(),
20
+ z.object({ ok: z.literal(false), error: z.string().min(1).max(SESSION_EVENT_ERROR_MAX) }).strict(),
21
+ ]);
22
+ const assertSessionEventResultParsed = (value) => value;
23
+ const assertSessionEventResultContract = (value) => value;
24
+ void assertSessionEventResultParsed;
25
+ void assertSessionEventResultContract;
12
26
  export const browserControlActionSchema = z.enum(BROWSER_CONTROL_ACTIONS);
13
27
  /*
14
28
  * Host-side parse of what a source-control provider answers. Every answer is
@@ -230,3 +244,147 @@ export const sourceControlProviderSchemasV1 = {
230
244
  data: dataSchemas,
231
245
  };
232
246
  export const sourceControlProviderMethodSchema = z.enum(SOURCE_CONTROL_PROVIDER_METHODS);
247
+ /*
248
+ * Host-side parse of what a notifications provider answers. The envelope and
249
+ * the error are the Git host's: `ok: true` with `data`, or `ok: false` with
250
+ * `{ message, status?, code? }`, and a 401 writes the account off only when
251
+ * OpenChamber's proxy saw the channel's server answer it.
252
+ */
253
+ const notificationsAccountSchema = z.object({
254
+ account: z.object({
255
+ id: z.string().min(1).max(256),
256
+ login: z.string().min(1).max(256),
257
+ name: optionalText,
258
+ }),
259
+ });
260
+ const notificationsNotifySchema = z.object({ delivered: z.literal(true) }).strict();
261
+ const notificationsDataSchemas = {
262
+ 'auth.verify': notificationsAccountSchema,
263
+ 'auth.probe': probeSchema,
264
+ notify: notificationsNotifySchema,
265
+ };
266
+ /** Wire 1 of the notifications role, as the host parses it. `data[method]` checks an `ok: true` answer's `data`. */
267
+ export const notificationsProviderSchemasV1 = {
268
+ envelope: envelopeSchema,
269
+ error: errorSchema,
270
+ account: notificationsAccountSchema,
271
+ probe: probeSchema,
272
+ notify: notificationsNotifySchema,
273
+ outboundRequest: outboundRequestSchema,
274
+ data: notificationsDataSchemas,
275
+ };
276
+ export const notificationsProviderMethodSchema = z.enum(NOTIFICATIONS_PROVIDER_METHODS);
277
+ /*
278
+ * Host-side parse of what a tracker answers. The envelope and the error are
279
+ * the Git host's. Every item is checked in the neutral shapes before the host
280
+ * hands it to the UI, bounded in count and length, and asserted against the
281
+ * TypeScript types the service writes against, so the two cannot drift. A
282
+ * failed parse is a malformed answer, never an empty list.
283
+ */
284
+ const trackerText = z.string().min(1).max(1_024);
285
+ const trackerTitle = z.string().max(4_096);
286
+ // An item's link is opened and drawn as a link in the app: http(s) only, so an answer cannot hand the UI a `javascript:` URL.
287
+ const trackerUrl = z.string().min(1).max(2_048).refine((value) => /^https?:\/\//i.test(value) && URL.canParse(value), { message: 'must be an http(s) URL' });
288
+ const trackerCategory = z.enum(['triage', 'backlog', 'todo', 'in-progress', 'done', 'canceled']);
289
+ const trackerPriority = z.enum(['none', 'urgent', 'high', 'medium', 'low']);
290
+ const trackerPerson = z.object({ name: z.string().max(256).nullable(), avatarUrl: z.string().max(2_048).nullable() }).strict();
291
+ const trackerContainer = z.object({ id: trackerText, key: z.string().max(64).nullable(), name: z.string().min(1).max(256) }).strict();
292
+ const trackerState = z.object({ id: trackerText.nullable(), name: z.string().max(256), category: trackerCategory.nullable() }).strict();
293
+ const trackerItemFields = {
294
+ id: trackerText,
295
+ identifier: z.string().min(1).max(128),
296
+ title: trackerTitle,
297
+ url: trackerUrl,
298
+ state: trackerState.nullable(),
299
+ priority: trackerPriority.nullable().optional(),
300
+ labels: z.array(z.object({ id: trackerText, name: z.string().min(1).max(256), color: z.string().max(32).nullable() }).strict()).max(TRACKER_PROVIDER_LIST_MAX).optional(),
301
+ assignee: trackerPerson.nullable().optional(),
302
+ container: trackerContainer.nullable().optional(),
303
+ progress: z.object({ total: z.number().int().nonnegative(), done: z.number().int().nonnegative(), more: z.boolean() }).strict().nullable().optional(),
304
+ updatedAt: z.string().max(64).nullable().optional(),
305
+ };
306
+ /** A related item (a parent, a child): one level deep, naming no parent of its own (`null` at most). */
307
+ const trackerRelatedItemSchema = z.object({ ...trackerItemFields, parent: z.null().optional() }).strict();
308
+ const trackerItemSummarySchema = z.object({ ...trackerItemFields, parent: trackerRelatedItemSchema.nullable().optional() }).strict();
309
+ const trackerCommentSchema = z.object({
310
+ id: trackerText,
311
+ body: z.string().max(65_536),
312
+ createdAt: z.string().max(64).nullable(),
313
+ author: trackerPerson.nullable(),
314
+ }).strict();
315
+ const trackerItemSchema = trackerItemSummarySchema.extend({
316
+ description: z.string().max(262_144).nullable().optional(),
317
+ comments: z.array(trackerCommentSchema).max(TRACKER_PROVIDER_LIST_MAX).optional(),
318
+ children: z.array(trackerRelatedItemSchema).max(TRACKER_PROVIDER_LIST_MAX).optional(),
319
+ childrenMore: z.boolean().optional(),
320
+ }).strict();
321
+ const trackerAccountSchema = z.object({
322
+ account: z.object({
323
+ id: z.string().min(1).max(256),
324
+ login: z.string().min(1).max(256).nullable(),
325
+ name: optionalText,
326
+ avatarUrl: z.string().max(2_048).optional(),
327
+ }).strict(),
328
+ }).strict();
329
+ const trackerListSchema = z.object({
330
+ items: z.array(trackerItemSummarySchema).max(TRACKER_PROVIDER_LIST_MAX),
331
+ cursor: z.string().min(1).max(2_048).nullable(),
332
+ hasMore: z.boolean(),
333
+ }).strict();
334
+ const trackerItemDataSchema = z.object({ item: trackerItemSchema.nullable() }).strict();
335
+ const trackerStatesSchema = z.object({
336
+ states: z.array(z.object({ id: trackerText, name: z.string().min(1).max(256), category: trackerCategory.nullable(), position: z.number() }).strict()).max(TRACKER_PROVIDER_LIST_MAX * 2),
337
+ }).strict();
338
+ const trackerLiveSummariesSchema = z.object({
339
+ items: z.array(z.object({
340
+ identifier: z.string().min(1).max(128),
341
+ title: trackerTitle,
342
+ state: z.object({ name: z.string().max(256), category: trackerCategory }).strict(),
343
+ }).strict()).max(TRACKER_PROVIDER_LIVE_SUMMARIES_MAX),
344
+ }).strict();
345
+ const trackerContainersSchema = z.object({ containers: z.array(trackerContainer).max(TRACKER_PROVIDER_CONTAINERS_MAX) }).strict();
346
+ const trackerCommentDataSchema = z.object({ comment: z.object({ id: trackerText }).strict().nullable() }).strict();
347
+ const assertTrackerSummary = (value) => value;
348
+ const assertTrackerItem = (value) => value;
349
+ const assertTrackerAccount = (value) => value;
350
+ const assertTrackerList = (value) => value;
351
+ const assertTrackerItemData = (value) => value;
352
+ const assertTrackerStates = (value) => value;
353
+ const assertTrackerLive = (value) => value;
354
+ const assertTrackerContainers = (value) => value;
355
+ void assertTrackerSummary;
356
+ void assertTrackerItem;
357
+ void assertTrackerAccount;
358
+ void assertTrackerList;
359
+ void assertTrackerItemData;
360
+ void assertTrackerStates;
361
+ void assertTrackerLive;
362
+ void assertTrackerContainers;
363
+ const trackerDataSchemas = {
364
+ 'auth.probe': probeSchema,
365
+ 'auth.verify': trackerAccountSchema,
366
+ 'items.list': trackerListSchema,
367
+ 'items.get': trackerItemDataSchema,
368
+ 'items.updateState': trackerItemDataSchema,
369
+ 'items.liveSummaries': trackerLiveSummariesSchema,
370
+ 'states.list': trackerStatesSchema,
371
+ 'containers.list': trackerContainersSchema,
372
+ 'comments.create': trackerCommentDataSchema,
373
+ };
374
+ /** Wire 1 of the tracker role, as the host parses it. `data[method]` checks an `ok: true` answer's `data`. */
375
+ export const trackerProviderSchemasV1 = {
376
+ envelope: envelopeSchema,
377
+ error: errorSchema,
378
+ account: trackerAccountSchema,
379
+ probe: probeSchema,
380
+ itemSummary: trackerItemSummarySchema,
381
+ item: trackerItemSchema,
382
+ list: trackerListSchema,
383
+ states: trackerStatesSchema,
384
+ liveSummaries: trackerLiveSummariesSchema,
385
+ containers: trackerContainersSchema,
386
+ comment: trackerCommentDataSchema,
387
+ outboundRequest: outboundRequestSchema,
388
+ data: trackerDataSchemas,
389
+ };
390
+ export const trackerProviderMethodSchema = z.enum(TRACKER_PROVIDER_METHODS);
@@ -308,7 +308,8 @@ export declare const sourceControlProviderTimeoutMs: (method: SourceControlProvi
308
308
  /**
309
309
  * Environment variable with the base URL of OpenChamber's callback listener
310
310
  * (`http://127.0.0.1:<port>`). Set only for a service that provides
311
- * `source-control`; `createSourceControlForge` reads it.
311
+ * `source-control`, `notifications` or `tracker`; `createSourceControlForge`,
312
+ * `createNotificationsOutbound` and `createTrackerOutbound` read it.
312
313
  */
313
314
  export declare const OPENCHAMBER_HOST_CALLBACK_URL = "OPENCHAMBER_HOST_CALLBACK_URL";
314
315
  /** Route on the callback listener a service sends a forge request to. */
@@ -622,4 +623,424 @@ export type SourceControlForge = {
622
623
  export declare const createSourceControlForge: ({ env }: {
623
624
  env: Record<string, string | undefined>;
624
625
  }) => SourceControlForge;
626
+ /** Route on the service loopback OpenChamber posts every notifications call to. */
627
+ export declare const NOTIFICATIONS_PROVIDER_PATH = "/notifications";
628
+ /** The `v` of every request; a service answers a version it does not know with HTTP 400. */
629
+ export declare const NOTIFICATIONS_PROVIDER_WIRE_VERSION = 1;
630
+ /**
631
+ * `auth.verify` reads who a candidate token belongs to, `auth.probe` whether
632
+ * an instance is this channel's server, `notify` delivers one notification.
633
+ */
634
+ export declare const NOTIFICATIONS_PROVIDER_METHODS: readonly ['auth.verify', 'auth.probe', 'notify'];
635
+ export type NotificationsProviderMethod = (typeof NOTIFICATIONS_PROVIDER_METHODS)[number];
636
+ /** A notification is delivered within this deadline; a slower service drops it. */
637
+ export declare const NOTIFICATIONS_PROVIDER_NOTIFY_TIMEOUT_MS = 10000;
638
+ export declare const NOTIFICATIONS_PROVIDER_AUTH_TIMEOUT_MS = 15000;
639
+ /** Bytes of an answer OpenChamber reads. */
640
+ export declare const NOTIFICATIONS_PROVIDER_RESPONSE_MAX = 16000;
641
+ /** Characters of `error.message` OpenChamber reads. */
642
+ export declare const NOTIFICATIONS_PROVIDER_ERROR_MESSAGE_MAX = 2000;
643
+ /** No call for this long stops the service; the next call starts it again. */
644
+ export declare const NOTIFICATIONS_PROVIDER_IDLE_MS: number;
645
+ /** Route on the callback listener a service sends the channel's requests to. */
646
+ export declare const NOTIFICATIONS_OUTBOUND_PATH = "/notifications/outbound";
647
+ /** One outbound request may take this long; the call's own deadline may end it sooner. */
648
+ export declare const NOTIFICATIONS_OUTBOUND_TIMEOUT_MS = 20000;
649
+ export declare const notificationsProviderTimeoutMs: (method: NotificationsProviderMethod) => number;
650
+ /**
651
+ * The kinds OpenChamber notifies about. `ready`: the agent finished; `error`:
652
+ * the turn failed; `question` and `permission`: the agent waits for the user;
653
+ * `review`: an auto-review ended; the `goal_*` kinds: a session goal settled.
654
+ * Which kinds reach a channel follows the user's own notification toggles.
655
+ */
656
+ export declare const GUEST_NOTIFICATION_KINDS: readonly ['ready', 'error', 'question', 'permission', 'review', 'goal_complete', 'goal_blocked', 'goal_budget'];
657
+ export type GuestNotificationKind = (typeof GUEST_NOTIFICATION_KINDS)[number];
658
+ /**
659
+ * One notification as OpenChamber shows it, after the user's templates. In
660
+ * enterprise mode `title` is the kind's generic title and `body`,
661
+ * `sessionName` and `directory` are empty, as they are for the phone.
662
+ */
663
+ export type GuestNotification = {
664
+ kind: GuestNotificationKind;
665
+ title: string;
666
+ body: string;
667
+ /** Groups repeats of one thing (`ready-<sessionId>`): a later one may replace an earlier one where the channel can. */
668
+ tag: string;
669
+ /** Epoch milliseconds. */
670
+ at: number;
671
+ sessionId: string | null;
672
+ sessionName: string | null;
673
+ directory: string | null;
674
+ /** The link that opens the session in OpenChamber, when there is one. */
675
+ url: string | null;
676
+ };
677
+ /** The connected account a call acts as; `null` in `auth.verify` and `auth.probe`, before one exists. */
678
+ export type NotificationsProviderAccount = {
679
+ id: string;
680
+ login: string | null;
681
+ };
682
+ /**
683
+ * Who a call is for. `instance` is the account's origin (`https://slack.com`,
684
+ * a Matrix homeserver). `handle` is the capability for this one call: pass it
685
+ * to `createNotificationsOutbound(...).request`. It stops working when the
686
+ * call ends; never store it.
687
+ */
688
+ export type NotificationsProviderSession = {
689
+ instance: string;
690
+ handle: string;
691
+ account: NotificationsProviderAccount | null;
692
+ };
693
+ /** What each method's `input` holds. */
694
+ export type NotificationsProviderInputs = {
695
+ 'auth.verify': Record<string, never>;
696
+ 'auth.probe': Record<string, never>;
697
+ notify: {
698
+ notification: GuestNotification;
699
+ };
700
+ };
701
+ /**
702
+ * One call, as OpenChamber posts it. `provider` is the id OpenChamber gave
703
+ * this channel (`ext-<panel.id>`). `input` was built by OpenChamber; its shape
704
+ * per method is `NotificationsProviderInputs`.
705
+ */
706
+ export type NotificationsProviderRequest = {
707
+ v: typeof NOTIFICATIONS_PROVIDER_WIRE_VERSION;
708
+ requestId: string;
709
+ method: NotificationsProviderMethod;
710
+ provider: string;
711
+ session: NotificationsProviderSession;
712
+ input: SourceControlJsonObject;
713
+ };
714
+ /** Who the candidate token belongs to; OpenChamber stores the account under `id`. */
715
+ export type NotificationsAccountData = {
716
+ account: {
717
+ id: string;
718
+ login: string;
719
+ name?: string;
720
+ };
721
+ };
722
+ export type NotificationsProbeData = {
723
+ supported: boolean;
724
+ message?: string;
725
+ };
726
+ export type NotificationsNotifyData = {
727
+ delivered: true;
728
+ };
729
+ /**
730
+ * An answer. `error.status` is the HTTP status OpenChamber should treat the
731
+ * failure as; a 401 writes the account off only when OpenChamber's proxy saw
732
+ * the channel's server answer 401 itself. `error.code` is `[A-Z_]{1,64}`.
733
+ */
734
+ export type NotificationsProviderError = SourceControlProviderError;
735
+ export type NotificationsProviderResult = {
736
+ ok: true;
737
+ data: SourceControlJson;
738
+ } | {
739
+ ok: false;
740
+ error: NotificationsProviderError;
741
+ };
742
+ export declare const isNotificationsProviderMethod: (value: string) => value is NotificationsProviderMethod;
743
+ /**
744
+ * A service's read of the body OpenChamber posted to
745
+ * `NOTIFICATIONS_PROVIDER_PATH`. OpenChamber built `input`, so this checks the
746
+ * envelope, not every field, and the service bundle needs no schema library.
747
+ * `null` is a body that is not a notifications call of this wire version;
748
+ * answer it with HTTP 400.
749
+ */
750
+ export declare const readNotificationsProviderRequest: (body: string) => NotificationsProviderRequest | null;
751
+ /**
752
+ * OpenChamber refused the request (an expired handle, a path off the
753
+ * instance, a body too large), could not reach the channel's server, or did
754
+ * not answer. `status` is the callback listener's HTTP status, `0` when it
755
+ * gave none; `code` is its error code (`HOST_UNAVAILABLE` when there was no
756
+ * usable answer).
757
+ */
758
+ export declare class NotificationsOutboundError extends Error {
759
+ readonly code: string;
760
+ readonly status: number;
761
+ constructor(message: string, code: string, status: number);
762
+ }
763
+ export type NotificationsOutbound = {
764
+ /** Sends `request` to the server of the account `handle` belongs to, with the stored token when the call has one. */
765
+ request(handle: string, request: SourceControlOutboundRequest): Promise<SourceControlOutboundResponse>;
766
+ };
767
+ /**
768
+ * The service's way to the channel's server: OpenChamber's callback listener
769
+ * (`OPENCHAMBER_HOST_CALLBACK_URL`), which checks the handle, keeps the
770
+ * request on the account's origin and adds the token. Plain `fetch`, no
771
+ * dependencies. Throws `NotificationsOutboundError` when OpenChamber refuses
772
+ * the request; an answer of any status from the server resolves.
773
+ */
774
+ export declare const createNotificationsOutbound: ({ env }: {
775
+ env: Record<string, string | undefined>;
776
+ }) => NotificationsOutbound;
777
+ /** Route on the service loopback OpenChamber posts every tracker call to. */
778
+ export declare const TRACKER_PROVIDER_PATH = "/tracker";
779
+ /** The `v` of every request; a service answers a version it does not know with HTTP 400. */
780
+ export declare const TRACKER_PROVIDER_WIRE_VERSION = 1;
781
+ /**
782
+ * Every call OpenChamber forwards. `auth.probe` asks whether an instance is
783
+ * this tracker's server, `auth.verify` who a credential belongs to (the handle
784
+ * carries a pasted token or an OAuth access token); the reads answer in the
785
+ * neutral shapes; `items.updateState` and `comments.create` are the two
786
+ * writes, the only calls whose handle may send anything but `GET`.
787
+ */
788
+ export declare const TRACKER_PROVIDER_METHODS: readonly ['auth.probe', 'auth.verify', 'items.list', 'items.get', 'items.updateState', 'items.liveSummaries', 'states.list', 'containers.list', 'comments.create'];
789
+ export type TrackerProviderMethod = (typeof TRACKER_PROVIDER_METHODS)[number];
790
+ /** The calls that change something on the tracker. */
791
+ export declare const TRACKER_PROVIDER_WRITE_METHODS: readonly ["items.updateState", "comments.create"];
792
+ export declare const TRACKER_PROVIDER_AUTH_TIMEOUT_MS = 15000;
793
+ export declare const TRACKER_PROVIDER_READ_TIMEOUT_MS = 20000;
794
+ export declare const TRACKER_PROVIDER_WRITE_TIMEOUT_MS = 30000;
795
+ /** Bytes of an answer OpenChamber reads: a page of items with their labels and people. */
796
+ export declare const TRACKER_PROVIDER_RESPONSE_MAX = 2000000;
797
+ /** Characters of `error.message` OpenChamber reads. */
798
+ export declare const TRACKER_PROVIDER_ERROR_MESSAGE_MAX = 2000;
799
+ /** No call for this long stops the service; the next call starts it again. */
800
+ export declare const TRACKER_PROVIDER_IDLE_MS: number;
801
+ /** Items in one `items.list` page, children or comments of one item, states of one container. */
802
+ export declare const TRACKER_PROVIDER_LIST_MAX = 100;
803
+ /** Identifiers in one `items.liveSummaries` call. */
804
+ export declare const TRACKER_PROVIDER_LIVE_SUMMARIES_MAX = 50;
805
+ /** Containers in one `containers.list` answer. */
806
+ export declare const TRACKER_PROVIDER_CONTAINERS_MAX = 500;
807
+ /** Route on the callback listener a service sends the tracker's requests to. */
808
+ export declare const TRACKER_OUTBOUND_PATH = "/tracker/outbound";
809
+ /** One outbound request may take this long; the call's own deadline may end it sooner. */
810
+ export declare const TRACKER_OUTBOUND_TIMEOUT_MS = 20000;
811
+ export declare const isTrackerProviderWriteMethod: (method: TrackerProviderMethod) => boolean;
812
+ /** How long OpenChamber waits for the service to answer `method`. */
813
+ export declare const trackerProviderTimeoutMs: (method: TrackerProviderMethod) => number;
814
+ export type TrackerProviderStateCategory = 'triage' | 'backlog' | 'todo' | 'in-progress' | 'done' | 'canceled';
815
+ export type TrackerProviderPriority = 'none' | 'urgent' | 'high' | 'medium' | 'low';
816
+ export type TrackerProviderPerson = {
817
+ name: string | null;
818
+ avatarUrl: string | null;
819
+ };
820
+ export type TrackerProviderItemState = {
821
+ id: string | null;
822
+ name: string;
823
+ category: TrackerProviderStateCategory | null;
824
+ };
825
+ export type TrackerProviderContainer = {
826
+ id: string;
827
+ key: string | null;
828
+ name: string;
829
+ };
830
+ export type TrackerProviderLabel = {
831
+ id: string;
832
+ name: string;
833
+ color: string | null;
834
+ };
835
+ /** Only the first few children are counted; `more` says there are others. */
836
+ export type TrackerProviderProgress = {
837
+ total: number;
838
+ done: number;
839
+ more: boolean;
840
+ };
841
+ /** One item in a list, or a related item (a parent, a child), which carries no labels or progress of its own. */
842
+ export type TrackerProviderItemSummary = {
843
+ /** The tracker's stable id; what `items.get` and `items.updateState` take. */
844
+ id: string;
845
+ /** Human key (`PROJ-42`), the shape `contributes.tracker.identifier` declares; compared case-insensitively. */
846
+ identifier: string;
847
+ title: string;
848
+ url: string;
849
+ state: TrackerProviderItemState | null;
850
+ priority?: TrackerProviderPriority | null;
851
+ labels?: TrackerProviderLabel[];
852
+ assignee?: TrackerProviderPerson | null;
853
+ container?: TrackerProviderContainer | null;
854
+ parent?: TrackerProviderItemSummary | null;
855
+ progress?: TrackerProviderProgress | null;
856
+ /** ISO 8601. */
857
+ updatedAt?: string | null;
858
+ };
859
+ export type TrackerProviderComment = {
860
+ id: string;
861
+ body: string;
862
+ createdAt: string | null;
863
+ author: TrackerProviderPerson | null;
864
+ };
865
+ export type TrackerProviderItem = TrackerProviderItemSummary & {
866
+ description?: string | null;
867
+ comments?: TrackerProviderComment[];
868
+ /** The first page of children in the tracker's order; `childrenMore` says there are others. */
869
+ children?: TrackerProviderItemSummary[];
870
+ childrenMore?: boolean;
871
+ };
872
+ export type TrackerProviderWorkflowState = {
873
+ id: string;
874
+ name: string;
875
+ category: TrackerProviderStateCategory | null;
876
+ position: number;
877
+ };
878
+ export type TrackerProviderLiveSummary = {
879
+ identifier: string;
880
+ title: string;
881
+ state: {
882
+ name: string;
883
+ category: TrackerProviderStateCategory;
884
+ };
885
+ };
886
+ /** The connected account a call acts as; `null` in `auth.verify` and `auth.probe`, before one exists. */
887
+ export type TrackerProviderAccount = {
888
+ id: string;
889
+ login: string | null;
890
+ };
891
+ /**
892
+ * Who a call is for. `instance` is the account's origin (the tracker's one
893
+ * address, or the server the user typed). `handle` is the capability for this
894
+ * one call: pass it to `createTrackerOutbound(...).request`. It stops working
895
+ * when the call ends; never store it.
896
+ */
897
+ export type TrackerProviderSession = {
898
+ instance: string;
899
+ handle: string;
900
+ account: TrackerProviderAccount | null;
901
+ };
902
+ /** What each method's `input` holds. OpenChamber built and checked every field. */
903
+ export type TrackerProviderInputs = {
904
+ 'auth.probe': Record<string, never>;
905
+ 'auth.verify': Record<string, never>;
906
+ 'items.list': {
907
+ query?: string;
908
+ cursor?: string;
909
+ /** One of the manifest's `stateFilters`. */
910
+ state: string;
911
+ people: 'any' | 'me' | 'created';
912
+ priority: 'all' | TrackerProviderPriority;
913
+ containerId: string | null;
914
+ };
915
+ 'items.get': {
916
+ id: string;
917
+ };
918
+ 'items.updateState': {
919
+ id: string;
920
+ stateId: string;
921
+ };
922
+ 'items.liveSummaries': {
923
+ identifiers: string[];
924
+ };
925
+ 'states.list': {
926
+ containerId: string;
927
+ };
928
+ 'containers.list': Record<string, never>;
929
+ /** `body` is Markdown OpenChamber wrote: "OpenChamber session completed" with a link to the session. */
930
+ 'comments.create': {
931
+ identifier: string;
932
+ body: string;
933
+ };
934
+ };
935
+ /**
936
+ * One call, as OpenChamber posts it. `provider` is the id OpenChamber gave
937
+ * this tracker (`ext-<panel.id>`). `input` was built by OpenChamber; its shape
938
+ * per method is `TrackerProviderInputs`.
939
+ */
940
+ export type TrackerProviderRequest = {
941
+ v: typeof TRACKER_PROVIDER_WIRE_VERSION;
942
+ requestId: string;
943
+ method: TrackerProviderMethod;
944
+ provider: string;
945
+ session: TrackerProviderSession;
946
+ input: SourceControlJsonObject;
947
+ };
948
+ /** Who the credential belongs to; OpenChamber stores the account under `id` and shows `name`. */
949
+ export type TrackerProviderAccountData = {
950
+ account: {
951
+ id: string;
952
+ login: string | null;
953
+ name?: string;
954
+ avatarUrl?: string;
955
+ };
956
+ };
957
+ export type TrackerProviderProbeData = {
958
+ supported: boolean;
959
+ message?: string;
960
+ };
961
+ export type TrackerProviderListData = {
962
+ items: TrackerProviderItemSummary[];
963
+ cursor: string | null;
964
+ hasMore: boolean;
965
+ };
966
+ /** `item` is null when the tracker has no such item. */
967
+ export type TrackerProviderItemData = {
968
+ item: TrackerProviderItem | null;
969
+ };
970
+ export type TrackerProviderStatesData = {
971
+ states: TrackerProviderWorkflowState[];
972
+ };
973
+ /** Identifiers the tracker does not know are left out. */
974
+ export type TrackerProviderLiveSummariesData = {
975
+ items: TrackerProviderLiveSummary[];
976
+ };
977
+ export type TrackerProviderContainersData = {
978
+ containers: TrackerProviderContainer[];
979
+ };
980
+ /** `comment` is null when the item was not found. */
981
+ export type TrackerProviderCommentData = {
982
+ comment: {
983
+ id: string;
984
+ } | null;
985
+ };
986
+ /** What each method answers in `data`. */
987
+ export type TrackerProviderDataByMethod = {
988
+ 'auth.probe': TrackerProviderProbeData;
989
+ 'auth.verify': TrackerProviderAccountData;
990
+ 'items.list': TrackerProviderListData;
991
+ 'items.get': TrackerProviderItemData;
992
+ 'items.updateState': TrackerProviderItemData;
993
+ 'items.liveSummaries': TrackerProviderLiveSummariesData;
994
+ 'states.list': TrackerProviderStatesData;
995
+ 'containers.list': TrackerProviderContainersData;
996
+ 'comments.create': TrackerProviderCommentData;
997
+ };
998
+ /**
999
+ * An answer. `error.status` is the HTTP status OpenChamber should treat the
1000
+ * failure as; a 401 writes the account off only when OpenChamber's proxy saw
1001
+ * the tracker's server answer 401 itself. `error.code` is `[A-Z_]{1,64}`.
1002
+ */
1003
+ export type TrackerProviderError = SourceControlProviderError;
1004
+ export type TrackerProviderResult = {
1005
+ ok: true;
1006
+ data: SourceControlJson;
1007
+ } | {
1008
+ ok: false;
1009
+ error: TrackerProviderError;
1010
+ };
1011
+ export declare const isTrackerProviderMethod: (value: string) => value is TrackerProviderMethod;
1012
+ /**
1013
+ * A service's read of the body OpenChamber posted to `TRACKER_PROVIDER_PATH`.
1014
+ * OpenChamber built `input`, so this checks the envelope, not every field, and
1015
+ * the service bundle needs no schema library. `null` is a body that is not a
1016
+ * tracker call of this wire version; answer it with HTTP 400.
1017
+ */
1018
+ export declare const readTrackerProviderRequest: (body: string) => TrackerProviderRequest | null;
1019
+ /**
1020
+ * OpenChamber refused the request (an expired handle, a path off the
1021
+ * instance, a body too large, a write through a read's handle), could not
1022
+ * reach the tracker's server, or did not answer. `status` is the callback
1023
+ * listener's HTTP status, `0` when it gave none; `code` is its error code
1024
+ * (`HOST_UNAVAILABLE` when there was no usable answer).
1025
+ */
1026
+ export declare class TrackerOutboundError extends Error {
1027
+ readonly code: string;
1028
+ readonly status: number;
1029
+ constructor(message: string, code: string, status: number);
1030
+ }
1031
+ export type TrackerOutbound = {
1032
+ /** Sends `request` to the server of the account `handle` belongs to, with the stored credential when the call has one. */
1033
+ request(handle: string, request: SourceControlOutboundRequest): Promise<SourceControlOutboundResponse>;
1034
+ };
1035
+ /**
1036
+ * The service's way to the tracker's server: OpenChamber's callback listener
1037
+ * (`OPENCHAMBER_HOST_CALLBACK_URL`), which checks the handle, keeps the
1038
+ * request on the account's origin and adds the credential. Plain `fetch`, no
1039
+ * dependencies. Throws `TrackerOutboundError` when OpenChamber refuses the
1040
+ * request; an answer of any status from the server resolves. A read's handle
1041
+ * sends `GET` only; `items.updateState` and `comments.create` may send writes.
1042
+ */
1043
+ export declare const createTrackerOutbound: ({ env }: {
1044
+ env: Record<string, string | undefined>;
1045
+ }) => TrackerOutbound;
625
1046
  export {};