exponential-sdk 1.28.0 → 1.31.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
@@ -688,6 +688,132 @@ declare class CeremoniesApi {
688
688
  detachMeeting(meetingId: string): Promise<CeremonyMeetingAttachment>;
689
689
  }
690
690
 
691
+ /**
692
+ * Positions (ADR-0068): the roles & responsibilities of a workspace — "who
693
+ * does what", for humans and agents alike. Shown on the workspace settings
694
+ * page. Routing data only: a Position never grants or restricts access;
695
+ * the member's workspace role does that.
696
+ */
697
+ /** Someone who holds a Position. Always a member of the workspace. */
698
+ interface PositionHolder {
699
+ userId: string;
700
+ name: string | null;
701
+ image: string | null;
702
+ isAgent: boolean;
703
+ }
704
+ interface Position {
705
+ id: string;
706
+ /** 1–80 characters, unique per workspace (case-sensitive). */
707
+ title: string;
708
+ /** Markdown, 1–2000 characters: the kinds of work its holders take on. */
709
+ remit: string;
710
+ /** Markdown, up to 2000 characters. */
711
+ notAccountableFor: string | null;
712
+ holders: PositionHolder[];
713
+ }
714
+ /** One row per workspace member, from `positions.list()`. */
715
+ interface PositionMemberCoverage {
716
+ userId: string;
717
+ /** Ids of the Positions this member holds. */
718
+ positionIds: string[];
719
+ /** True when the member has no stated remit (no Position, and no agent description). */
720
+ remitGap: boolean;
721
+ }
722
+ interface PositionList {
723
+ positions: Position[];
724
+ members: PositionMemberCoverage[];
725
+ }
726
+ interface PositionCoverage {
727
+ /** Whether the chat would offer "Import roles & responsibilities". */
728
+ offerImport: boolean;
729
+ memberCount: number;
730
+ eligibleCount: number;
731
+ coveredCount: number;
732
+ }
733
+ /** One row of an import result, in input order. */
734
+ interface PositionImportResult {
735
+ title: string;
736
+ outcome: 'create' | 'update';
737
+ /** The value after the import. */
738
+ notAccountableFor: string | null;
739
+ /** Every holder after the import. */
740
+ holderUserIds: string[];
741
+ }
742
+ interface PositionImportOutput {
743
+ /** False for a dry run. */
744
+ written: boolean;
745
+ results: PositionImportResult[];
746
+ }
747
+
748
+ interface PositionCreateInput {
749
+ workspaceId: string;
750
+ /** 1–80 characters, unique per workspace. */
751
+ title: string;
752
+ /** Markdown, 1–2000 characters. */
753
+ remit: string;
754
+ /** Markdown, up to 2000 characters. */
755
+ notAccountableFor?: string;
756
+ /** Member userIds (max 50). Every one must belong to the workspace. */
757
+ holderUserIds?: string[];
758
+ }
759
+ /** At least one field besides the ids must be present. */
760
+ interface PositionUpdateInput {
761
+ workspaceId: string;
762
+ positionId: string;
763
+ title?: string;
764
+ remit?: string;
765
+ /** `null` or `""` clears it. */
766
+ notAccountableFor?: string | null;
767
+ /** Replaces the whole holder set (owner/admin only). */
768
+ holderUserIds?: string[];
769
+ }
770
+ interface PositionImportRow {
771
+ title: string;
772
+ remit: string;
773
+ /** Omit to keep the stored value on an update; `""` clears it. */
774
+ notAccountableFor?: string;
775
+ holderUserIds: string[];
776
+ }
777
+ interface PositionImportInput {
778
+ workspaceId: string;
779
+ /** Validate and return the plan without writing. */
780
+ dryRun: boolean;
781
+ /** 1–50 rows, titles unique (case-insensitive), at most 200 distinct holders. */
782
+ positions: PositionImportRow[];
783
+ }
784
+ /**
785
+ * Positions — a workspace's roles & responsibilities (ADR-0068).
786
+ *
787
+ * Every write is human-only: it needs a person's own API token (`exponential
788
+ * auth login`), and an agent key is refused with FORBIDDEN. Owners and admins
789
+ * create, rename, delete, set holders and import; a member may edit the
790
+ * remit of a Position they hold.
791
+ */
792
+ declare class PositionsApi {
793
+ private client;
794
+ constructor(client: TrpcClient);
795
+ /** Every Position with its holders, plus each member's coverage. */
796
+ list(workspaceId: string): Promise<PositionList>;
797
+ /** One Position by id, from `list` (the router has no single-row read). */
798
+ get(workspaceId: string, positionId: string): Promise<Position | null>;
799
+ /** How many members have a stated remit, and whether to offer an import. */
800
+ coverage(workspaceId: string): Promise<PositionCoverage>;
801
+ create(input: PositionCreateInput): Promise<Position>;
802
+ update(input: PositionUpdateInput): Promise<Position>;
803
+ /** Holders cascade. */
804
+ delete(workspaceId: string, positionId: string): Promise<{
805
+ id: string;
806
+ }>;
807
+ /** Replace the holder set; `[]` removes everyone. */
808
+ setHolders(workspaceId: string, positionId: string, userIds: string[]): Promise<Position>;
809
+ /**
810
+ * Upsert many Positions by title (matched case-insensitively, never renamed).
811
+ * An update replaces the remit and only ADDS holders. Run with
812
+ * `dryRun: true` first to see the plan.
813
+ */
814
+ importMany(input: PositionImportInput): Promise<PositionImportOutput>;
815
+ }
816
+
691
817
  type ActionInput = {
692
818
  assigneeId?: string;
693
819
  };
@@ -854,6 +980,36 @@ type ActionUpdateInput$1 = {
854
980
  effortEstimate?: number | null;
855
981
  blockedByIds?: string[];
856
982
  };
983
+ type CalendarProviderInput = 'google' | 'microsoft';
984
+ type CalendarAccountSelectorInput = {
985
+ provider?: CalendarProviderInput;
986
+ accountId?: string;
987
+ };
988
+ type CalendarCreateEventPayload = {
989
+ summary: string;
990
+ description?: string;
991
+ start: {
992
+ dateTime: string;
993
+ timeZone?: string;
994
+ };
995
+ end: {
996
+ dateTime: string;
997
+ timeZone?: string;
998
+ };
999
+ attendees?: Array<{
1000
+ email: string;
1001
+ }>;
1002
+ conferenceData?: {
1003
+ createRequest: {
1004
+ requestId: string;
1005
+ conferenceSolutionKey: {
1006
+ type: 'hangoutsMeet';
1007
+ };
1008
+ };
1009
+ };
1010
+ calendarId?: string;
1011
+ provider?: CalendarProviderInput;
1012
+ };
857
1013
  type MeetingParticipantPersonInput = {
858
1014
  userId?: string;
859
1015
  contactId?: string;
@@ -977,6 +1133,41 @@ interface TrpcClient {
977
1133
  }) => Promise<unknown>;
978
1134
  };
979
1135
  };
1136
+ calendar: {
1137
+ getAllConnectionStatuses: {
1138
+ query: () => Promise<unknown>;
1139
+ };
1140
+ getCalendarAccounts: {
1141
+ query: () => Promise<unknown>;
1142
+ };
1143
+ getEventsMultiCalendar: {
1144
+ query: (input: {
1145
+ timeMin?: Date;
1146
+ timeMax?: Date;
1147
+ maxResults?: number;
1148
+ }) => Promise<unknown[]>;
1149
+ };
1150
+ listCalendars: {
1151
+ query: (input?: CalendarAccountSelectorInput) => Promise<unknown[]>;
1152
+ };
1153
+ getCalendarPreferences: {
1154
+ query: (input?: CalendarAccountSelectorInput) => Promise<unknown>;
1155
+ };
1156
+ updateSelectedCalendars: {
1157
+ mutate: (input: CalendarAccountSelectorInput & {
1158
+ calendarIds: string[];
1159
+ }) => Promise<unknown>;
1160
+ };
1161
+ syncCalendarList: {
1162
+ mutate: (input?: CalendarAccountSelectorInput) => Promise<unknown>;
1163
+ };
1164
+ createEvent: {
1165
+ mutate: (input: CalendarCreateEventPayload) => Promise<unknown>;
1166
+ };
1167
+ disconnect: {
1168
+ mutate: (input?: CalendarAccountSelectorInput) => Promise<unknown>;
1169
+ };
1170
+ };
980
1171
  search: {
981
1172
  global: {
982
1173
  query: (input: {
@@ -1069,6 +1260,46 @@ interface TrpcClient {
1069
1260
  }) => Promise<unknown[]>;
1070
1261
  };
1071
1262
  };
1263
+ user: {
1264
+ /** Who the token signs in as — an agent's shadow user for an `exp_agent_…` key. */
1265
+ getCurrentUser: {
1266
+ query: () => Promise<unknown>;
1267
+ };
1268
+ };
1269
+ position: {
1270
+ list: {
1271
+ query: (input: {
1272
+ workspaceId: string;
1273
+ }) => Promise<unknown>;
1274
+ };
1275
+ coverage: {
1276
+ query: (input: {
1277
+ workspaceId: string;
1278
+ }) => Promise<unknown>;
1279
+ };
1280
+ create: {
1281
+ mutate: (input: PositionCreateInput) => Promise<unknown>;
1282
+ };
1283
+ update: {
1284
+ mutate: (input: PositionUpdateInput) => Promise<unknown>;
1285
+ };
1286
+ delete: {
1287
+ mutate: (input: {
1288
+ workspaceId: string;
1289
+ positionId: string;
1290
+ }) => Promise<unknown>;
1291
+ };
1292
+ setHolders: {
1293
+ mutate: (input: {
1294
+ workspaceId: string;
1295
+ positionId: string;
1296
+ userIds: string[];
1297
+ }) => Promise<unknown>;
1298
+ };
1299
+ importMany: {
1300
+ mutate: (input: PositionImportInput) => Promise<unknown>;
1301
+ };
1302
+ };
1072
1303
  goal: {
1073
1304
  getById: {
1074
1305
  query: (input: {
@@ -2300,6 +2531,50 @@ interface TrpcClient {
2300
2531
  }) => Promise<unknown>;
2301
2532
  };
2302
2533
  };
2534
+ cycle: {
2535
+ list: {
2536
+ query: (input: {
2537
+ workspaceId: string;
2538
+ productId?: string;
2539
+ status?: 'PLANNED' | 'ACTIVE' | 'COMPLETED' | 'ARCHIVED';
2540
+ autoCreate?: boolean;
2541
+ }) => Promise<unknown[]>;
2542
+ };
2543
+ getById: {
2544
+ query: (input: {
2545
+ id: string;
2546
+ }) => Promise<unknown>;
2547
+ };
2548
+ create: {
2549
+ mutate: (input: {
2550
+ workspaceId: string;
2551
+ productId?: string;
2552
+ name?: string;
2553
+ slug?: string;
2554
+ description?: string;
2555
+ startDate?: Date;
2556
+ endDate?: Date;
2557
+ cycleGoal?: string;
2558
+ }) => Promise<unknown>;
2559
+ };
2560
+ update: {
2561
+ mutate: (input: {
2562
+ id: string;
2563
+ name?: string;
2564
+ description?: string | null;
2565
+ status?: 'PLANNED' | 'ACTIVE' | 'COMPLETED' | 'ARCHIVED';
2566
+ startDate?: Date | null;
2567
+ endDate?: Date | null;
2568
+ cycleGoal?: string | null;
2569
+ achievements?: string | null;
2570
+ }) => Promise<unknown>;
2571
+ };
2572
+ delete: {
2573
+ mutate: (input: {
2574
+ id: string;
2575
+ }) => Promise<unknown>;
2576
+ };
2577
+ };
2303
2578
  ticket: {
2304
2579
  list: {
2305
2580
  query: (input: {
@@ -5083,6 +5358,347 @@ declare class MeetingsApi {
5083
5358
  appendNotes(id: string, text: string): Promise<Meeting>;
5084
5359
  }
5085
5360
 
5361
+ type CalendarProviderName = 'google' | 'microsoft';
5362
+ /**
5363
+ * One end of an event. Timed events carry `dateTime` (RFC3339); all-day
5364
+ * events carry `date` (YYYY-MM-DD) instead. Exactly one is present.
5365
+ */
5366
+ interface CalendarEventTime {
5367
+ dateTime?: string;
5368
+ date?: string;
5369
+ timeZone?: string;
5370
+ }
5371
+ interface CalendarEventAttendee {
5372
+ email: string;
5373
+ displayName?: string;
5374
+ /** Provider-specific, e.g. "accepted" | "declined" | "tentative" | "needsAction". */
5375
+ responseStatus: string;
5376
+ }
5377
+ interface CalendarEvent {
5378
+ id: string;
5379
+ summary: string;
5380
+ description?: string;
5381
+ start: CalendarEventTime;
5382
+ end: CalendarEventTime;
5383
+ location?: string;
5384
+ attendees?: CalendarEventAttendee[];
5385
+ htmlLink: string;
5386
+ status: string;
5387
+ }
5388
+ /**
5389
+ * An event from `listEvents`/`today`/`upcoming`, tagged with its origin.
5390
+ * The source fields are what make a merged multi-account list readable.
5391
+ */
5392
+ interface CalendarEventWithSource extends CalendarEvent {
5393
+ accountId: string;
5394
+ accountEmail: string | null;
5395
+ calendarId: string;
5396
+ calendarName?: string;
5397
+ calendarColor?: string;
5398
+ provider: CalendarProviderName;
5399
+ }
5400
+ interface CalendarInfo {
5401
+ id: string;
5402
+ summary: string;
5403
+ description?: string;
5404
+ primary: boolean;
5405
+ accessRole: string;
5406
+ backgroundColor?: string;
5407
+ foregroundColor?: string;
5408
+ }
5409
+ /** A connected calendar account, with its calendars and current selection. */
5410
+ interface CalendarAccount {
5411
+ id: string;
5412
+ provider: CalendarProviderName;
5413
+ email: string | null;
5414
+ name: string | null;
5415
+ /** Which of `calendars` currently feed the merged event list. */
5416
+ selectedCalendarIds: string[];
5417
+ calendars: CalendarInfo[];
5418
+ }
5419
+ interface CalendarConnectionStatus {
5420
+ isConnected: boolean;
5421
+ hasCalendarScope: boolean;
5422
+ /** How many accounts for this provider are usably connected. */
5423
+ connectedCount: number;
5424
+ }
5425
+ interface CalendarConnectionStatuses {
5426
+ google: CalendarConnectionStatus;
5427
+ microsoft: CalendarConnectionStatus;
5428
+ }
5429
+ interface CalendarPreferences {
5430
+ selectedCalendarIds: string[];
5431
+ allCalendars: CalendarInfo[];
5432
+ cacheUpdatedAt: Date | null;
5433
+ }
5434
+ interface CreatedCalendarEvent extends CalendarEvent {
5435
+ conferenceData?: {
5436
+ entryPoints?: Array<{
5437
+ uri: string;
5438
+ label?: string;
5439
+ entryPointType: string;
5440
+ }>;
5441
+ conferenceId?: string;
5442
+ };
5443
+ /** Microsoft's equivalent of a Meet link. */
5444
+ onlineMeetingUrl?: string;
5445
+ }
5446
+
5447
+ /** The server clamps `maxResults` to this; exposed so callers can pre-clamp. */
5448
+ declare const CALENDAR_MAX_RESULTS = 100;
5449
+ /** The server keeps at most this many calendars selected per account. */
5450
+ declare const CALENDAR_MAX_SELECTED = 10;
5451
+ interface CalendarListEventsOptions {
5452
+ /** Inclusive lower bound. Omitted means "from now" per the provider. */
5453
+ from?: Date;
5454
+ /** Exclusive upper bound. */
5455
+ to?: Date;
5456
+ /** 1–100, default 50. Applies per account, before the merge. */
5457
+ maxResults?: number;
5458
+ }
5459
+ /** Picks which connected account to act on. `accountId` wins when both are set. */
5460
+ interface CalendarAccountSelector {
5461
+ accountId?: string;
5462
+ /** Falls back to the earliest-connected account for this provider. */
5463
+ provider?: CalendarProviderName;
5464
+ }
5465
+ interface CalendarSelectCalendarsInput extends CalendarAccountSelector {
5466
+ /** At least one. Anything past the first 10 is dropped by the server. */
5467
+ calendarIds: string[];
5468
+ }
5469
+ interface CalendarCreateEventInput {
5470
+ summary: string;
5471
+ description?: string;
5472
+ start: Date;
5473
+ end: Date;
5474
+ /** Attendee email addresses. Invites are sent by the provider. */
5475
+ attendees?: string[];
5476
+ /** Attach a Google Meet link. Google only — Microsoft ignores it. */
5477
+ meet?: boolean;
5478
+ /** Defaults to the account's primary calendar. */
5479
+ calendarId?: string;
5480
+ provider?: CalendarProviderName;
5481
+ /**
5482
+ * IANA zone the times should display in, e.g. "Europe/Lisbon". Defaults to
5483
+ * the host's zone. Times themselves go over the wire as UTC, so this only
5484
+ * affects how the provider renders them.
5485
+ */
5486
+ timeZone?: string;
5487
+ }
5488
+ /**
5489
+ * Connected calendars (Google + Microsoft).
5490
+ *
5491
+ * Reads go through the server's merged multi-calendar view, so `today`,
5492
+ * `upcoming` and `listEvents` all return the same source-tagged shape across
5493
+ * every connected account rather than a single provider's slice.
5494
+ *
5495
+ * Connecting and re-authorizing an account is a browser OAuth flow in the web
5496
+ * app; this API covers everything after that.
5497
+ */
5498
+ declare class CalendarApi {
5499
+ private client;
5500
+ constructor(client: TrpcClient);
5501
+ /** Merged, start-time-sorted events from every connected account. */
5502
+ listEvents(options?: CalendarListEventsOptions): Promise<CalendarEventWithSource[]>;
5503
+ /**
5504
+ * Everything on today's date, in the host's local timezone — including
5505
+ * all-day events and meetings that started before now.
5506
+ */
5507
+ today(options?: {
5508
+ maxResults?: number;
5509
+ }): Promise<CalendarEventWithSource[]>;
5510
+ /** Events from now until `days` days ahead (default 7). */
5511
+ upcoming(options?: {
5512
+ days?: number;
5513
+ maxResults?: number;
5514
+ }): Promise<CalendarEventWithSource[]>;
5515
+ /** Connected accounts, each with its calendars and current selection. */
5516
+ accounts(): Promise<CalendarAccount[]>;
5517
+ /** Per-provider connection state, including accounts needing re-auth. */
5518
+ connectionStatuses(): Promise<CalendarConnectionStatuses>;
5519
+ /** Every calendar on one account, straight from the provider (uncached). */
5520
+ listCalendars(selector?: CalendarAccountSelector): Promise<CalendarInfo[]>;
5521
+ /** One account's selected calendars plus its cached calendar list. */
5522
+ getPreferences(selector?: CalendarAccountSelector): Promise<CalendarPreferences>;
5523
+ /**
5524
+ * Replace which calendars on an account feed the merged event list.
5525
+ * This is a replace, not a merge — pass the full set you want.
5526
+ */
5527
+ selectCalendars(input: CalendarSelectCalendarsInput): Promise<{
5528
+ success: boolean;
5529
+ selectedCalendarIds: string[];
5530
+ }>;
5531
+ /** Re-fetch an account's calendar list from the provider and re-cache it. */
5532
+ syncCalendars(selector?: CalendarAccountSelector): Promise<{
5533
+ success: boolean;
5534
+ calendars: CalendarInfo[];
5535
+ }>;
5536
+ createEvent(input: CalendarCreateEventInput): Promise<CreatedCalendarEvent>;
5537
+ /**
5538
+ * Remove a calendar connection. Deletes the stored tokens and calendar
5539
+ * preferences; it never touches the user's ability to sign in with that
5540
+ * account. Reconnecting means redoing the OAuth flow in the web app.
5541
+ */
5542
+ disconnect(selector?: CalendarAccountSelector): Promise<{
5543
+ success: boolean;
5544
+ message: string;
5545
+ }>;
5546
+ }
5547
+
5548
+ type CycleStatus = 'PLANNED' | 'ACTIVE' | 'COMPLETED' | 'ARCHIVED';
5549
+ interface Cycle {
5550
+ id: string;
5551
+ workspaceId: string;
5552
+ /** Owning product; `null` for a legacy workspace-shared cycle. */
5553
+ productId: string | null;
5554
+ name: string;
5555
+ slug: string;
5556
+ description: string | null;
5557
+ status: CycleStatus;
5558
+ startDate: Date | null;
5559
+ endDate: Date | null;
5560
+ cycleGoal: string | null;
5561
+ achievements: string | null;
5562
+ displayOrder: number;
5563
+ createdById: string;
5564
+ createdAt: Date;
5565
+ updatedAt: Date;
5566
+ _count?: {
5567
+ tickets?: number;
5568
+ retrospectives?: number;
5569
+ };
5570
+ }
5571
+ interface CycleDetail extends Cycle {
5572
+ tickets?: Array<{
5573
+ id: string;
5574
+ title: string;
5575
+ status: string;
5576
+ type: string;
5577
+ points: number | null;
5578
+ assignee?: {
5579
+ id: string;
5580
+ name: string | null;
5581
+ image: string | null;
5582
+ } | null;
5583
+ }>;
5584
+ retrospectives?: Array<{
5585
+ id: string;
5586
+ title: string;
5587
+ conductedAt: Date | null;
5588
+ createdAt: Date;
5589
+ }>;
5590
+ metrics?: unknown;
5591
+ }
5592
+
5593
+ interface CycleListOptions {
5594
+ workspaceId: string;
5595
+ /**
5596
+ * Scope to one product's cycles. The server returns that product's cycles
5597
+ * PLUS legacy workspace-shared ones (`productId: null`), matching what the
5598
+ * product's Cycles tab shows. Takes a product CUID — use
5599
+ * `cycles.current(...)` / `cycles.resolve(...)` if you only have a slug.
5600
+ * Omit to list every cycle in the workspace, across all products.
5601
+ */
5602
+ productId?: string;
5603
+ status?: CycleStatus;
5604
+ /**
5605
+ * The server lazily generates upcoming cycles as a side effect of `list`.
5606
+ * Pass `false` to read without provisioning anything — useful for read-only
5607
+ * callers that should not mutate the workspace just by looking at it.
5608
+ * The server defaults it to `true`, and the generated rows are attributed
5609
+ * to the caller. `current()` and `resolve()` always pass `false`.
5610
+ */
5611
+ autoCreate?: boolean;
5612
+ }
5613
+ interface CycleCreateInput {
5614
+ workspaceId: string;
5615
+ /** Product this cycle belongs to. Omit for a workspace-shared cycle. */
5616
+ productId?: string;
5617
+ /**
5618
+ * Omit to let the server auto-name it (`Cycle N`). Numbering is per-product
5619
+ * (the given product's cycles plus legacy shared ones), so different
5620
+ * products in one workspace can both reach e.g. "Cycle 9".
5621
+ */
5622
+ name?: string;
5623
+ /** Omit to let the server slugify `name`, de-duplicating with a suffix. */
5624
+ slug?: string;
5625
+ description?: string;
5626
+ startDate?: Date;
5627
+ endDate?: Date;
5628
+ cycleGoal?: string;
5629
+ }
5630
+ interface CycleUpdateInput {
5631
+ id: string;
5632
+ name?: string;
5633
+ description?: string | null;
5634
+ status?: CycleStatus;
5635
+ startDate?: Date | null;
5636
+ endDate?: Date | null;
5637
+ cycleGoal?: string | null;
5638
+ achievements?: string | null;
5639
+ }
5640
+ declare class CyclesApi {
5641
+ private client;
5642
+ constructor(client: TrpcClient);
5643
+ /**
5644
+ * List cycles in a workspace, newest start date first. Pass `productId` to
5645
+ * scope to one product's timeline (plus legacy workspace-shared cycles).
5646
+ *
5647
+ * Note this is not a pure read: the server reconciles cycle statuses against
5648
+ * today's date and (unless `autoCreate: false`) provisions upcoming cycles —
5649
+ * scoped to `productId` when given.
5650
+ */
5651
+ list(options: CycleListOptions): Promise<Cycle[]>;
5652
+ get(id: string): Promise<CycleDetail>;
5653
+ /**
5654
+ * The current (`ACTIVE`) cycle, or `null` when none is running (e.g. a gap
5655
+ * between cycles).
5656
+ *
5657
+ * Cycles are product-scoped, so a workspace can have one ACTIVE cycle per
5658
+ * product. Pass `product` (a product CUID or slug) to get that product's
5659
+ * current cycle — a cycle scoped to the product wins over a legacy
5660
+ * workspace-shared one.
5661
+ *
5662
+ * Without `product`, this stays backward compatible for workspaces with a
5663
+ * single timeline: if every ACTIVE cycle belongs to the same product (or all
5664
+ * are workspace-shared), the most recently started wins. If ACTIVE cycles
5665
+ * from different products coexist, it throws rather than silently picking
5666
+ * an arbitrary product's cycle.
5667
+ */
5668
+ current(workspaceId: string, product?: string): Promise<Cycle | null>;
5669
+ /**
5670
+ * Resolve what a user typed to a cycle.
5671
+ *
5672
+ * Accepts, in order of precedence:
5673
+ * - `"current"` / `"active"` → the ACTIVE cycle (see `current()`)
5674
+ * - a cycle CUID
5675
+ * - a cycle slug
5676
+ * - a cycle name (case-insensitive)
5677
+ *
5678
+ * Pass `product` (a product CUID or slug) to scope the lookup to that
5679
+ * product's timeline. Cycle auto-numbering is per-product, so two products
5680
+ * can both have a cycle named "Cycle 9" in one workspace: with `product`
5681
+ * set, a cycle scoped to that product beats a legacy workspace-shared one
5682
+ * of the same name; without it, an ambiguous name throws rather than
5683
+ * silently picking one. Ids and slugs are unique per workspace and never
5684
+ * ambiguous.
5685
+ *
5686
+ * Throws rather than returning null so callers never silently file work
5687
+ * against the wrong cycle — or against none at all.
5688
+ */
5689
+ resolve(workspaceId: string, slugOrIdOrName: string, product?: string): Promise<Cycle>;
5690
+ create(input: CycleCreateInput): Promise<Cycle>;
5691
+ update(input: CycleUpdateInput): Promise<Cycle>;
5692
+ delete(id: string): Promise<{
5693
+ success: boolean;
5694
+ }>;
5695
+ /**
5696
+ * Turn a product reference (CUID or slug) into the CUID the cycle endpoints
5697
+ * expect. CUIDs pass through without a lookup — the server validates access.
5698
+ */
5699
+ private resolveProductId;
5700
+ }
5701
+
5086
5702
  interface KnowledgePage {
5087
5703
  id: string;
5088
5704
  workspaceId: string;
@@ -5949,6 +6565,42 @@ declare class SearchApi {
5949
6565
  knowledge(options: KnowledgeSearchOptions): Promise<KnowledgeSearchOutput>;
5950
6566
  }
5951
6567
 
6568
+ /**
6569
+ * The account a token signs in as (`user.getCurrentUser`).
6570
+ *
6571
+ * An External agent's `exp_agent_…` key resolves to the agent's own shadow
6572
+ * user, so `isAgent` is true and `agent` names the agent and the person who
6573
+ * owns it. That is the account to add to a workspace or a restricted project
6574
+ * when the agent is refused.
6575
+ */
6576
+ interface CurrentUser {
6577
+ id: string;
6578
+ name: string | null;
6579
+ email: string | null;
6580
+ image: string | null;
6581
+ isAgent: boolean;
6582
+ agent: {
6583
+ id: string;
6584
+ name: string;
6585
+ owner: {
6586
+ id: string;
6587
+ name: string | null;
6588
+ };
6589
+ } | null;
6590
+ }
6591
+
6592
+ declare class UsersApi {
6593
+ private client;
6594
+ constructor(client: TrpcClient);
6595
+ /**
6596
+ * The account this client's token signs in as. For an External agent's key
6597
+ * the result is the agent's shadow user: `isAgent` is true and `agent`
6598
+ * carries the agent's name and owner — the identity to grant access to when
6599
+ * a command comes back FORBIDDEN.
6600
+ */
6601
+ me(): Promise<CurrentUser>;
6602
+ }
6603
+
5952
6604
  type TimeEntryStatus = 'PROPOSED' | 'CONFIRMED';
5953
6605
  /**
5954
6606
  * Where an entry came from. `plugin` is the legacy stamp of the in-app Timer
@@ -6332,6 +6984,8 @@ declare class ExponentialClient {
6332
6984
  keyResults: KeyResultsApi;
6333
6985
  projects: ProjectsApi;
6334
6986
  workspaces: WorkspacesApi;
6987
+ /** Positions — a workspace's roles & responsibilities (ADR-0068). */
6988
+ positions: PositionsApi;
6335
6989
  /** Ceremonies and their occurrences (ADR-0059). */
6336
6990
  ceremonies: CeremoniesApi;
6337
6991
  contacts: ContactsApi;
@@ -6346,6 +7000,8 @@ declare class ExponentialClient {
6346
7000
  labels: LabelsApi;
6347
7001
  areas: AreasApi;
6348
7002
  meetings: MeetingsApi;
7003
+ calendar: CalendarApi;
7004
+ cycles: CyclesApi;
6349
7005
  pages: PagesApi;
6350
7006
  /** Databases — typed tables inside pages (ADR-0078). */
6351
7007
  databases: DatabasesApi;
@@ -6353,6 +7009,7 @@ declare class ExponentialClient {
6353
7009
  requirements: RequirementsApi;
6354
7010
  scopes: ScopesApi;
6355
7011
  search: SearchApi;
7012
+ users: UsersApi;
6356
7013
  /** Time entries — the Daily worklog's write path (ADR-0061). */
6357
7014
  time: TimeApi;
6358
7015
  /** Agent runs — the local runner's claim/heartbeat/append/finish (ADR-0067); agent-key only. */
@@ -6363,4 +7020,4 @@ declare class ExponentialClient {
6363
7020
  });
6364
7021
  }
6365
7022
 
6366
- export { type Action, type ActionComment, type ActionCommentAddInput, type ActionCommentUpdateInput, type ActionCreateInput, type ActionOutput, type ActionStatus, type ActionUpdateInput, type ActionUpsertBySourceInput, type ActionUpsertBySourceResult, type ActionsListOutput, type AddInteractionInput, type AddablePropertyType, type AgentRunStatus, AgentRunsApi, type AppendEventsResult, type Area, type AreaCreateInput, type AreaListOptions, CeremoniesApi, type Ceremony, type CeremonyAddAgendaItemInput, type CeremonyAddedOccurrence, type CeremonyAgenda, type CeremonyAgendaItem, type CeremonyAgendaMatrixPost, type CeremonyAgendaRefType, type CeremonyAgendaResult, type CeremonyAgendaSection, type CeremonyAgendaTemplateSection, type CeremonyBackfillResult, type CeremonyBackfillRow, type CeremonyCreateInput, type CeremonyGenerateAgendaResult, type CeremonyImportDefinition, type CeremonyImportInput, type CeremonyImportResult, type CeremonyKind, type CeremonyListOccurrencesInput, type CeremonyMatrixPostResult, type CeremonyMatrixRemoveResult, type CeremonyMeetingAttachment, type CeremonyMeetingUrlMatch, type CeremonyMyUpdate, type CeremonyNamedRef, type CeremonyOccurrence, type CeremonyOccurrenceListRow, type CeremonyOccurrenceRow, type CeremonyOccurrenceStatus, type CeremonyParticipantUpdate, type CeremonyRecord, type CeremonyRecordedMeeting, type CeremonyRescheduledOccurrence, type CeremonySaveMyUpdateInput, type CeremonySkipProposal, type CeremonySkipResult, type CeremonySummary, type CeremonyTemplate, type CeremonyUpdateInput, type CeremonyUpdateQuestion, type CeremonyUpdateSummary, type CeremonyUserRef, type CeremonyWriteResult, type ClaimedRun, type CommentAuthor, type Contact, type ContactCreateInput, type ContactInteraction, type ContactListOutput, type ContactUpdateInput, type ContactsListOptions, type ConversationMessage, type CsvCellError, type CsvColumnTarget, type CsvCommitResult, type CsvMapping, type CsvPreview, type CsvPreviewColumn, type CsvPreviewRow, DEFAULT_GAP_MINUTES, type Database, type DatabaseCreateInput, type DatabaseFilter, type DatabasePropertyResult, type DatabaseRow, type DatabaseRowsPage, type DatabaseUpdateInput, type DatabaseView, type DayReport, type DayReportActionRow, type DayReportEntry, type DayReportProductRow, type Deal, type DealActivity, type DealCreateInput, type DealMoveInput, type DealUpdateInput, type Decision, type DecisionAdrRef, type DecisionChainRef, type DecisionCreateInput, type DecisionDecider, type DecisionDeciderInput, type DecisionEvidenceTurn, type DecisionFeatureRef, type DecisionLink, type DecisionListOptions, type DecisionListRow, type DecisionMeetingRef, type DecisionOccurrenceRef, type DecisionProductRef, type DecisionProjectRef, type DecisionReviewState, type DecisionSetStatusInput, type DecisionSource, type DecisionStatus, type DecisionTicketRef, type DecisionUpdateInput, type DecisionUserRef, type DeletedDatabase, type DraftDecisionsResult, type EnrichContactResult, type Epic, type EpicCreateInput, type EpicListOptions, type EpicPriority, type EpicStatus, type EpicUpdateInput, ExponentialClient, type ExponentialConfig, type Feature, type FeatureComment, type FeatureCommentCreateInput, type FeatureCommentReplyInput, type FeatureCommentThreadInput, type FeatureCommentUpdateInput, type FeatureCreateInput, type FeatureKeyResultLink, type FeatureLinkPageInput, type FeatureListOptions, type FeatureScope, type FeatureScopeStatus, type FeatureStatus, type FeatureUpdateInput, type FilterOp, type FinishInput, type FinishResult, type GlobalSearchOptions, type GlobalSearchOutput, type Goal, type GoalChildSummary, type GoalComment, type GoalCommentAddInput, type GoalCommentUpdateInput, type GoalCreateInput, type GoalHealth, type GoalKeyResultSummary, type GoalLifeDomain, type GoalListOptions, type GoalPeriod, type GoalProjectSummary, type GoalSetParentInput, type GoalSetStatusInput, type GoalStats, type GoalStatsOptions, type GoalStatus, type GoalTreeNode, type GoalTreeOptions, type GoalUpdateInput, type GoalUserSummary, type GoalWritableStatus, type HeartbeatResult, type InteractionDirection, type InteractionType, type KanbanStatus, type KeyResult, type KeyResultByObjectiveOptions, type KeyResultCheckIn, type KeyResultCheckInInput, type KeyResultCreateInput, type KeyResultFeatureLink, type KeyResultListOptions, type KeyResultProjectLink, type KeyResultStatus, type KeyResultUnit, type KeyResultUpdateInput, type KnowledgePage, type KnowledgeSearchOptions, type KnowledgeSearchOutput, type KnowledgeSearchResult, type KnowledgeSourceType, type LabelCreateInput, type LabelListOptions, type ListForEntityInput, type Meeting, type MeetingActionSummary, type MeetingCreateInput, type MeetingDecisions, type MeetingListOptions, type MeetingParticipant, type MeetingParticipantInput, type MeetingProjectRef, type MeetingSourceIntegration, type MeetingTypeFilter, type MeetingUpdateInput, type MeetingWorkspaceRef, type ObjectiveWithKeyResults, type Organization, type OrganizationCreateInput, type OrganizationListOutput, type OrganizationSize, type OrganizationsListOptions, type OverdueCohort, type OverdueTriage, type OverdueTriageRow, type PageComment, type PageCommentCreateInput, type PageCommentUpdateInput, type PageCreateInput, type PageDiff, type PageDiffOptions, type PageDiffSide, type PageGetFormat, type PageGetOptions, type PageHistory, type PageHistoryOptions, type PageListOptions, type PageOutlineEntry, type PageRestoreOptions, type PageRevision, type PageRevisionAuthor, type PageRevisionDetail, type PageRevisionKind, type PageSearchOptions, type PageSearchOutput, type PageSearchResult, type PageUpdateInput, type PillColor, type Pipeline, type PipelineStage, type Priority, type Product, type ProductCreateInput, type ProductUpdateInput, type Project, type ProjectCeremony, type ProjectDetail, type ProjectKeyResultLink, type ProjectOccurrenceRow, type ProjectOutput, type ProjectPriority, type ProjectStatus, type ProjectUpdateInput, type ProjectsListOptions, type ProjectsListOutput, type PropertyAddInput, type PropertyDef, type PropertyRejection, type PropertyType, type PropertyUpdateInput, type PropertyValue, ROUND_MINUTES, type ReadStatus, type RelationConfig, type RelationTargetKind, type Requirement, type RequirementCreateInput, type RequirementKind, type RequirementListOptions, type Resource, type ResourceContentType, type ResourceCreateInput, type ResourceListOptions, type ResourceListResult, type ResourceReadState, type ResourceUpdateInput, type RowListOptions, type RowValuesInput, type RowWriteOptions, type RunMessage, type RunnerEvent, type RunnerEventKind, type ScopeCreateInput, type ScopeListOptions, type ScopeUpdateInput, type SearchResult, type SearchResultType, type SearchResultWorkspace, type SelectOption, type SelectOptionInput, type SetEntityTagsInput, type SetEntityTagsResult, type Tag, type TagEntityType, type TagListResult, type Ticket, type TicketAssignee, type TicketComment, type TicketCommentAddInput, type TicketCommentUpdateInput, type TicketCreateInput, type TicketDependencyEdge, type TicketDetail, type TicketListOptions, type TicketSearchOptions, type TicketStatus, type TicketType, type TicketUpdateInput, TimeApi, type TimeConfirmDayResult, type TimeEntry, type TimeEntrySource, type TimeEntryStatus, type TimeLogBatchResult, type TimeLogInput, type TimeLogOutcome, type TimeLogResult, type TodaysActionRow, type TodaysActions, type TodaysActionsGroup, type UserStory, type UserStoryCreateInput, type UserStoryListOptions, type UserStoryUpdateInput, type WorklogSegment, type Workspace, type WorkspaceMember, type WorkspaceOutput, type WorkspacesListOutput, clearConfig, createConfigStore, getConfigPath, isAuthenticated, isTRPCError, loadConfig, saveConfig, segmentConversation };
7023
+ export { type Action, type ActionComment, type ActionCommentAddInput, type ActionCommentUpdateInput, type ActionCreateInput, type ActionOutput, type ActionStatus, type ActionUpdateInput, type ActionUpsertBySourceInput, type ActionUpsertBySourceResult, type ActionsListOutput, type AddInteractionInput, type AddablePropertyType, type AgentRunStatus, AgentRunsApi, type AppendEventsResult, type Area, type AreaCreateInput, type AreaListOptions, CALENDAR_MAX_RESULTS, CALENDAR_MAX_SELECTED, type CalendarAccount, type CalendarAccountSelector, type CalendarConnectionStatus, type CalendarConnectionStatuses, type CalendarCreateEventInput, type CalendarEvent, type CalendarEventAttendee, type CalendarEventTime, type CalendarEventWithSource, type CalendarInfo, type CalendarListEventsOptions, type CalendarPreferences, type CalendarProviderName, type CalendarSelectCalendarsInput, CeremoniesApi, type Ceremony, type CeremonyAddAgendaItemInput, type CeremonyAddedOccurrence, type CeremonyAgenda, type CeremonyAgendaItem, type CeremonyAgendaMatrixPost, type CeremonyAgendaRefType, type CeremonyAgendaResult, type CeremonyAgendaSection, type CeremonyAgendaTemplateSection, type CeremonyBackfillResult, type CeremonyBackfillRow, type CeremonyCreateInput, type CeremonyGenerateAgendaResult, type CeremonyImportDefinition, type CeremonyImportInput, type CeremonyImportResult, type CeremonyKind, type CeremonyListOccurrencesInput, type CeremonyMatrixPostResult, type CeremonyMatrixRemoveResult, type CeremonyMeetingAttachment, type CeremonyMeetingUrlMatch, type CeremonyMyUpdate, type CeremonyNamedRef, type CeremonyOccurrence, type CeremonyOccurrenceListRow, type CeremonyOccurrenceRow, type CeremonyOccurrenceStatus, type CeremonyParticipantUpdate, type CeremonyRecord, type CeremonyRecordedMeeting, type CeremonyRescheduledOccurrence, type CeremonySaveMyUpdateInput, type CeremonySkipProposal, type CeremonySkipResult, type CeremonySummary, type CeremonyTemplate, type CeremonyUpdateInput, type CeremonyUpdateQuestion, type CeremonyUpdateSummary, type CeremonyUserRef, type CeremonyWriteResult, type ClaimedRun, type CommentAuthor, type Contact, type ContactCreateInput, type ContactInteraction, type ContactListOutput, type ContactUpdateInput, type ContactsListOptions, type ConversationMessage, type CreatedCalendarEvent, type CsvCellError, type CsvColumnTarget, type CsvCommitResult, type CsvMapping, type CsvPreview, type CsvPreviewColumn, type CsvPreviewRow, type CurrentUser, type Cycle, type CycleCreateInput, type CycleDetail, type CycleListOptions, type CycleStatus, type CycleUpdateInput, DEFAULT_GAP_MINUTES, type Database, type DatabaseCreateInput, type DatabaseFilter, type DatabasePropertyResult, type DatabaseRow, type DatabaseRowsPage, type DatabaseUpdateInput, type DatabaseView, type DayReport, type DayReportActionRow, type DayReportEntry, type DayReportProductRow, type Deal, type DealActivity, type DealCreateInput, type DealMoveInput, type DealUpdateInput, type Decision, type DecisionAdrRef, type DecisionChainRef, type DecisionCreateInput, type DecisionDecider, type DecisionDeciderInput, type DecisionEvidenceTurn, type DecisionFeatureRef, type DecisionLink, type DecisionListOptions, type DecisionListRow, type DecisionMeetingRef, type DecisionOccurrenceRef, type DecisionProductRef, type DecisionProjectRef, type DecisionReviewState, type DecisionSetStatusInput, type DecisionSource, type DecisionStatus, type DecisionTicketRef, type DecisionUpdateInput, type DecisionUserRef, type DeletedDatabase, type DraftDecisionsResult, type EnrichContactResult, type Epic, type EpicCreateInput, type EpicListOptions, type EpicPriority, type EpicStatus, type EpicUpdateInput, ExponentialClient, type ExponentialConfig, type Feature, type FeatureComment, type FeatureCommentCreateInput, type FeatureCommentReplyInput, type FeatureCommentThreadInput, type FeatureCommentUpdateInput, type FeatureCreateInput, type FeatureKeyResultLink, type FeatureLinkPageInput, type FeatureListOptions, type FeatureScope, type FeatureScopeStatus, type FeatureStatus, type FeatureUpdateInput, type FilterOp, type FinishInput, type FinishResult, type GlobalSearchOptions, type GlobalSearchOutput, type Goal, type GoalChildSummary, type GoalComment, type GoalCommentAddInput, type GoalCommentUpdateInput, type GoalCreateInput, type GoalHealth, type GoalKeyResultSummary, type GoalLifeDomain, type GoalListOptions, type GoalPeriod, type GoalProjectSummary, type GoalSetParentInput, type GoalSetStatusInput, type GoalStats, type GoalStatsOptions, type GoalStatus, type GoalTreeNode, type GoalTreeOptions, type GoalUpdateInput, type GoalUserSummary, type GoalWritableStatus, type HeartbeatResult, type InteractionDirection, type InteractionType, type KanbanStatus, type KeyResult, type KeyResultByObjectiveOptions, type KeyResultCheckIn, type KeyResultCheckInInput, type KeyResultCreateInput, type KeyResultFeatureLink, type KeyResultListOptions, type KeyResultProjectLink, type KeyResultStatus, type KeyResultUnit, type KeyResultUpdateInput, type KnowledgePage, type KnowledgeSearchOptions, type KnowledgeSearchOutput, type KnowledgeSearchResult, type KnowledgeSourceType, type LabelCreateInput, type LabelListOptions, type ListForEntityInput, type Meeting, type MeetingActionSummary, type MeetingCreateInput, type MeetingDecisions, type MeetingListOptions, type MeetingParticipant, type MeetingParticipantInput, type MeetingProjectRef, type MeetingSourceIntegration, type MeetingTypeFilter, type MeetingUpdateInput, type MeetingWorkspaceRef, type ObjectiveWithKeyResults, type Organization, type OrganizationCreateInput, type OrganizationListOutput, type OrganizationSize, type OrganizationsListOptions, type OverdueCohort, type OverdueTriage, type OverdueTriageRow, type PageComment, type PageCommentCreateInput, type PageCommentUpdateInput, type PageCreateInput, type PageDiff, type PageDiffOptions, type PageDiffSide, type PageGetFormat, type PageGetOptions, type PageHistory, type PageHistoryOptions, type PageListOptions, type PageOutlineEntry, type PageRestoreOptions, type PageRevision, type PageRevisionAuthor, type PageRevisionDetail, type PageRevisionKind, type PageSearchOptions, type PageSearchOutput, type PageSearchResult, type PageUpdateInput, type PillColor, type Pipeline, type PipelineStage, type Position, type PositionCoverage, type PositionCreateInput, type PositionHolder, type PositionImportInput, type PositionImportOutput, type PositionImportResult, type PositionImportRow, type PositionList, type PositionMemberCoverage, type PositionUpdateInput, PositionsApi, type Priority, type Product, type ProductCreateInput, type ProductUpdateInput, type Project, type ProjectCeremony, type ProjectDetail, type ProjectKeyResultLink, type ProjectOccurrenceRow, type ProjectOutput, type ProjectPriority, type ProjectStatus, type ProjectUpdateInput, type ProjectsListOptions, type ProjectsListOutput, type PropertyAddInput, type PropertyDef, type PropertyRejection, type PropertyType, type PropertyUpdateInput, type PropertyValue, ROUND_MINUTES, type ReadStatus, type RelationConfig, type RelationTargetKind, type Requirement, type RequirementCreateInput, type RequirementKind, type RequirementListOptions, type Resource, type ResourceContentType, type ResourceCreateInput, type ResourceListOptions, type ResourceListResult, type ResourceReadState, type ResourceUpdateInput, type RowListOptions, type RowValuesInput, type RowWriteOptions, type RunMessage, type RunnerEvent, type RunnerEventKind, type ScopeCreateInput, type ScopeListOptions, type ScopeUpdateInput, type SearchResult, type SearchResultType, type SearchResultWorkspace, type SelectOption, type SelectOptionInput, type SetEntityTagsInput, type SetEntityTagsResult, type Tag, type TagEntityType, type TagListResult, type Ticket, type TicketAssignee, type TicketComment, type TicketCommentAddInput, type TicketCommentUpdateInput, type TicketCreateInput, type TicketDependencyEdge, type TicketDetail, type TicketListOptions, type TicketSearchOptions, type TicketStatus, type TicketType, type TicketUpdateInput, TimeApi, type TimeConfirmDayResult, type TimeEntry, type TimeEntrySource, type TimeEntryStatus, type TimeLogBatchResult, type TimeLogInput, type TimeLogOutcome, type TimeLogResult, type TodaysActionRow, type TodaysActions, type TodaysActionsGroup, type UserStory, type UserStoryCreateInput, type UserStoryListOptions, type UserStoryUpdateInput, type WorklogSegment, type Workspace, type WorkspaceMember, type WorkspaceOutput, type WorkspacesListOutput, clearConfig, createConfigStore, getConfigPath, isAuthenticated, isTRPCError, loadConfig, saveConfig, segmentConversation };