@proteos/sdk 0.39.0 → 0.41.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proteos/sdk",
3
- "version": "0.39.0",
3
+ "version": "0.41.0",
4
4
  "license": "Apache-2.0",
5
5
  "description": "TypeScript SDK for the Proteos platform",
6
6
  "repository": {
@@ -66,8 +66,8 @@
66
66
  "tsup": "^8.3.0",
67
67
  "typescript": "^5.7.0",
68
68
  "vitest": "^3.0.0",
69
- "@proteos/biome-config": "0.0.0",
70
- "@proteos/tsconfig": "0.0.0"
69
+ "@proteos/tsconfig": "0.0.0",
70
+ "@proteos/biome-config": "0.0.0"
71
71
  },
72
72
  "scripts": {
73
73
  "build": "tsup",
@@ -132,6 +132,7 @@ export type {
132
132
  SkillVersion,
133
133
  StartMcpOAuthResponse,
134
134
  PlatformBinding,
135
+ QueryBinding,
135
136
  Tool,
136
137
  ToolBinding,
137
138
  ToolKind,
@@ -224,8 +224,15 @@ export interface StopReason {
224
224
  }
225
225
 
226
226
  /**
227
- * Emitted when a turn ends. `event_ids` carries the tool_use event ids awaiting a
228
- * client response when `stop_reason.type` is `user_action_required`.
227
+ * Ends a turn published once per turn by the server, not an echo of the upstream
228
+ * provider's session status (which flips idle/running once per server-side tool
229
+ * round, mid-turn).
230
+ *
231
+ * `event_ids` is set only with `stop_reason.type: 'user_action_required'`, and lists
232
+ * the tool_use events still OUTSTANDING — the ones a client must answer. Tools the
233
+ * server executes itself are resolved before this event exists, so seeing this event
234
+ * at all means the turn cannot continue without you: answer each id with a
235
+ * `user.tool_result`.
229
236
  */
230
237
  export interface SessionIdlePayload {
231
238
  stop_reason: StopReason
@@ -217,8 +217,10 @@ export type ListSkillsOptions = AgentResourceListOptions
217
217
  * - `client` is a host-provided builtin and carries no binding.
218
218
  * - `platform` binds to one tool of the platform MCP server (mcp-service),
219
219
  * executed server-side as the acting user.
220
+ * - `query` stores a SQL query with declared params, executed server-side
221
+ * against data-service as the acting user.
220
222
  */
221
- export type ToolKind = 'action' | 'mcp' | 'client' | 'platform'
223
+ export type ToolKind = 'action' | 'mcp' | 'client' | 'platform' | 'query'
222
224
 
223
225
  /** Binds to a function-service Action by its key (kind=action). */
224
226
  export interface ActionBinding {
@@ -240,8 +242,19 @@ export interface PlatformBinding {
240
242
  tool_name: string
241
243
  }
242
244
 
245
+ /**
246
+ * Stores a SELECT-only SQL query (data-service dialect) whose `{{param}}`
247
+ * placeholders are filled from the declared `params` at execution time
248
+ * (kind=query). Params are scalar attribute definitions (string, number,
249
+ * integer, boolean, datetime, enum); they generate the tool's input schema.
250
+ */
251
+ export interface QueryBinding {
252
+ sql: string
253
+ params?: Attribute[]
254
+ }
255
+
243
256
  /** Kind-discriminated binding payload. `kind=client` carries no binding. */
244
- export type ToolBinding = ActionBinding | McpBinding | PlatformBinding
257
+ export type ToolBinding = ActionBinding | McpBinding | PlatformBinding | QueryBinding
245
258
 
246
259
  /**
247
260
  * A thin registry entry over one of three binding sources. `key` is the wire
@@ -8,6 +8,7 @@ import type {
8
8
  Contact,
9
9
  ContactAddress,
10
10
  ContactErasureRequest,
11
+ ContactGroup,
11
12
  ContactMergeProposal,
12
13
  Conversation,
13
14
  ConversationFilter,
@@ -15,16 +16,20 @@ import type {
15
16
  ConversationType,
16
17
  CreateAgentListenerRequest,
17
18
  CreateConnectionRequest,
19
+ CreateContactGroupRequest,
18
20
  CreateConversationFilterRequest,
19
21
  CreateConversationTypeRequest,
20
22
  CreateGlossaryTermRequest,
23
+ CreateToneProfileSetupRequest,
21
24
  CreateTranscriptionRequest,
25
+ DeleteConnectionQuery,
22
26
  DispatchMeetingBotRequest,
23
27
  GlossaryTerm,
24
28
  InstallConnectionResponse,
25
29
  ListAgentListenersQuery,
26
30
  ListConnectionsQuery,
27
31
  ListContactAddressesQuery,
32
+ ListContactGroupsQuery,
28
33
  ListContactMergeProposalsQuery,
29
34
  ListContactsQuery,
30
35
  ListConversationFilterEventsQuery,
@@ -37,6 +42,8 @@ import type {
37
42
  ListReactionsResponse,
38
43
  ListResponse,
39
44
  ListRoomsQuery,
45
+ ListToneProfileSetupsQuery,
46
+ ListToneProfilesQuery,
40
47
  ListTranscriptionsQuery,
41
48
  MaterializeTranscriptionRequest,
42
49
  MergeContactsRequest,
@@ -44,13 +51,17 @@ import type {
44
51
  MistranscribedTerm,
45
52
  Reaction,
46
53
  RecordPermissionEventRequest,
54
+ ResolveToneProfileQuery,
47
55
  Room,
48
56
  SendMessageRequest,
49
57
  SyncConnectionRequest,
58
+ ToneProfile,
59
+ ToneProfileSetup,
50
60
  Transcription,
51
61
  UnreadCounts,
52
62
  UpdateAgentListenerRequest,
53
63
  UpdateConnectionRequest,
64
+ UpdateContactGroupRequest,
54
65
  UpdateContactRequest,
55
66
  UpdateConversationFilterRequest,
56
67
  UpdateConversationRequest,
@@ -86,6 +97,10 @@ export class ConversationClient {
86
97
  readonly glossaryTerms: GlossaryTermService
87
98
  /** Conversation taxonomy: the types the pre-summary classifier assigns. */
88
99
  readonly conversationTypes: ConversationTypeService
100
+ /** Generic audience taxonomy; membership lives on the contact. */
101
+ readonly contactGroups: ContactGroupService
102
+ /** Tone-of-voice synthesis: per-user setups + the generated profiles. */
103
+ readonly toneProfiles: ToneProfileService
89
104
  readonly transcriptions: TranscriptionService
90
105
  /** Review-pass findings: likely misheard terms awaiting accept/reject. */
91
106
  readonly mistranscribedTerms: MistranscribedTermService
@@ -103,6 +118,8 @@ export class ConversationClient {
103
118
  this.conversationFilters = new ConversationFilterServiceImpl(client)
104
119
  this.glossaryTerms = new GlossaryTermServiceImpl(client)
105
120
  this.conversationTypes = new ConversationTypeServiceImpl(client)
121
+ this.contactGroups = new ContactGroupServiceImpl(client)
122
+ this.toneProfiles = new ToneProfileServiceImpl(client)
106
123
  this.transcriptions = new TranscriptionServiceImpl(client)
107
124
  this.mistranscribedTerms = new MistranscribedTermServiceImpl(client)
108
125
  this.meetings = new MeetingServiceImpl(client)
@@ -164,7 +181,14 @@ export interface ConnectionService {
164
181
  get(id: string): Promise<Connection>
165
182
  create(request: CreateConnectionRequest): Promise<Connection>
166
183
  update(id: string, request: UpdateConnectionRequest): Promise<Connection>
167
- delete(id: string): Promise<void>
184
+ /**
185
+ * Delete a connection. The connector first releases its provider-side
186
+ * registration (a Recall calendar and the OAuth grant behind it); when that
187
+ * fails the delete is refused with a `connector_uninstall_failed` 502 rather
188
+ * than orphaning it. Pass `{ is_forced: true }` to drop the row anyway and
189
+ * clean up at the provider by hand.
190
+ */
191
+ delete(id: string, query?: DeleteConnectionQuery): Promise<void>
168
192
  /** Begin the connector's install flow; open the returned URL in a popup. */
169
193
  install(id: string): Promise<InstallConnectionResponse>
170
194
  /**
@@ -211,10 +235,11 @@ class ConnectionServiceImpl implements ConnectionService {
211
235
  )
212
236
  }
213
237
 
214
- async delete(id: string): Promise<void> {
215
- await this.client.request(
238
+ async delete(id: string, query: DeleteConnectionQuery = {}): Promise<void> {
239
+ await this.client.requestWithQuery(
216
240
  'DELETE',
217
241
  `${CONVERSATION_BASE_PATH}/connections/${encodeURIComponent(id)}`,
242
+ query,
218
243
  )
219
244
  }
220
245
 
@@ -392,6 +417,11 @@ export interface ConversationService {
392
417
  /** Patch the user-editable surface (subject, summary, status, metadata). */
393
418
  update(id: string, request: UpdateConversationRequest): Promise<Conversation>
394
419
  end(id: string): Promise<Conversation>
420
+ /**
421
+ * Hard-delete the conversation, its thread children, and every dependent
422
+ * row (messages, attachments, read markers, transcriptions). Irreversible.
423
+ */
424
+ delete(id: string): Promise<void>
395
425
  /** Upsert the requesting user's read marker to now (open a conversation). */
396
426
  markRead(id: string): Promise<void>
397
427
  /** Remove the marker — the conversation reads as unread again. */
@@ -429,6 +459,13 @@ class ConversationServiceImpl implements ConversationService {
429
459
  )
430
460
  }
431
461
 
462
+ delete(id: string): Promise<void> {
463
+ return this.client.request(
464
+ 'DELETE',
465
+ `${CONVERSATION_BASE_PATH}/conversations/${encodeURIComponent(id)}`,
466
+ )
467
+ }
468
+
432
469
  markRead(id: string): Promise<void> {
433
470
  return this.client.request(
434
471
  'POST',
@@ -781,6 +818,136 @@ class ConversationTypeServiceImpl implements ConversationTypeService {
781
818
  }
782
819
  }
783
820
 
821
+ /**
822
+ * Contact groups: the generic org-shared audience taxonomy. Membership lives
823
+ * on the contact (`Contact.group_key`, one group per contact — assign via
824
+ * `contacts.update`); tone-of-voice synthesis reads the groups and
825
+ * auto-assigns ungrouped correspondents. Keyed by `key` (not id); `upsert` is
826
+ * the idempotent module-deploy door. Deleting a group clears its members'
827
+ * membership and purges its tone profile rows.
828
+ */
829
+ export interface ContactGroupService {
830
+ list(query?: ListContactGroupsQuery): Promise<ListResponse<ContactGroup>>
831
+ get(key: string): Promise<ContactGroup>
832
+ create(request: CreateContactGroupRequest): Promise<ContactGroup>
833
+ update(key: string, request: UpdateContactGroupRequest): Promise<ContactGroup>
834
+ /** Idempotent create-or-update by key (PUT) — what `pro module deploy` calls. */
835
+ upsert(key: string, request: CreateContactGroupRequest): Promise<ContactGroup>
836
+ delete(key: string): Promise<void>
837
+ }
838
+
839
+ class ContactGroupServiceImpl implements ContactGroupService {
840
+ constructor(private readonly client: ProteosClient) {}
841
+
842
+ list(query: ListContactGroupsQuery = {}): Promise<ListResponse<ContactGroup>> {
843
+ return this.client.requestWithQuery('GET', `${CONVERSATION_BASE_PATH}/contact-groups`, query)
844
+ }
845
+
846
+ get(key: string): Promise<ContactGroup> {
847
+ return this.client.request(
848
+ 'GET',
849
+ `${CONVERSATION_BASE_PATH}/contact-groups/${encodeURIComponent(key)}`,
850
+ )
851
+ }
852
+
853
+ create(request: CreateContactGroupRequest): Promise<ContactGroup> {
854
+ return this.client.request('POST', `${CONVERSATION_BASE_PATH}/contact-groups`, request)
855
+ }
856
+
857
+ update(key: string, request: UpdateContactGroupRequest): Promise<ContactGroup> {
858
+ return this.client.request(
859
+ 'PATCH',
860
+ `${CONVERSATION_BASE_PATH}/contact-groups/${encodeURIComponent(key)}`,
861
+ request,
862
+ )
863
+ }
864
+
865
+ upsert(key: string, request: CreateContactGroupRequest): Promise<ContactGroup> {
866
+ return this.client.request(
867
+ 'PUT',
868
+ `${CONVERSATION_BASE_PATH}/contact-groups/${encodeURIComponent(key)}`,
869
+ { ...request, key },
870
+ )
871
+ }
872
+
873
+ async delete(key: string): Promise<void> {
874
+ await this.client.request(
875
+ 'DELETE',
876
+ `${CONVERSATION_BASE_PATH}/contact-groups/${encodeURIComponent(key)}`,
877
+ )
878
+ }
879
+ }
880
+
881
+ /**
882
+ * Tone-of-voice synthesis. A setup opts one platform user in (only set-up
883
+ * users are swept); `synthesize` triggers a whole-user run immediately (202;
884
+ * 409 `synthesis_in_progress` while one is live). Generated profiles form a
885
+ * specificity hierarchy — fetch a user's rows with `listProfiles`, or let the
886
+ * server pick the single most-specific row for a drafting context with
887
+ * `resolve` (each row is self-contained; never concatenate tiers).
888
+ */
889
+ export interface ToneProfileService {
890
+ listSetups(query?: ListToneProfileSetupsQuery): Promise<ListResponse<ToneProfileSetup>>
891
+ createSetup(request: CreateToneProfileSetupRequest): Promise<ToneProfileSetup>
892
+ /** Removes the setup AND the user's generated profiles. */
893
+ deleteSetup(id: string): Promise<void>
894
+ /** Kicks a whole-user synthesis run off-request (bypasses cadence checks). */
895
+ synthesize(setupId: string): Promise<void>
896
+ listProfiles(query?: ListToneProfilesQuery): Promise<ListResponse<ToneProfile>>
897
+ getProfile(id: string): Promise<ToneProfile>
898
+ /** The single most-specific profile for a drafting context; 404 when none. */
899
+ resolve(query: ResolveToneProfileQuery): Promise<ToneProfile>
900
+ }
901
+
902
+ class ToneProfileServiceImpl implements ToneProfileService {
903
+ constructor(private readonly client: ProteosClient) {}
904
+
905
+ listSetups(query: ListToneProfileSetupsQuery = {}): Promise<ListResponse<ToneProfileSetup>> {
906
+ return this.client.requestWithQuery(
907
+ 'GET',
908
+ `${CONVERSATION_BASE_PATH}/tone-profile-setups`,
909
+ query,
910
+ )
911
+ }
912
+
913
+ createSetup(request: CreateToneProfileSetupRequest): Promise<ToneProfileSetup> {
914
+ return this.client.request('POST', `${CONVERSATION_BASE_PATH}/tone-profile-setups`, request)
915
+ }
916
+
917
+ async deleteSetup(id: string): Promise<void> {
918
+ await this.client.request(
919
+ 'DELETE',
920
+ `${CONVERSATION_BASE_PATH}/tone-profile-setups/${encodeURIComponent(id)}`,
921
+ )
922
+ }
923
+
924
+ async synthesize(setupId: string): Promise<void> {
925
+ await this.client.request(
926
+ 'POST',
927
+ `${CONVERSATION_BASE_PATH}/tone-profile-setups/${encodeURIComponent(setupId)}/synthesize`,
928
+ )
929
+ }
930
+
931
+ listProfiles(query: ListToneProfilesQuery = {}): Promise<ListResponse<ToneProfile>> {
932
+ return this.client.requestWithQuery('GET', `${CONVERSATION_BASE_PATH}/tone-profiles`, query)
933
+ }
934
+
935
+ getProfile(id: string): Promise<ToneProfile> {
936
+ return this.client.request(
937
+ 'GET',
938
+ `${CONVERSATION_BASE_PATH}/tone-profiles/${encodeURIComponent(id)}`,
939
+ )
940
+ }
941
+
942
+ resolve(query: ResolveToneProfileQuery): Promise<ToneProfile> {
943
+ return this.client.requestWithQuery(
944
+ 'GET',
945
+ `${CONVERSATION_BASE_PATH}/tone-profiles/resolve`,
946
+ query,
947
+ )
948
+ }
949
+ }
950
+
784
951
  /** Batch transcription of stored audio files + materialization. */
785
952
  export interface TranscriptionService {
786
953
  /**
@@ -716,6 +716,131 @@ export interface ListConversationTypesQuery extends PaginationQuery {
716
716
  module_slug?: string
717
717
  }
718
718
 
719
+ /** Who assigned a contact's group membership. */
720
+ export type ContactGroupSource = 'manual' | 'model'
721
+
722
+ /**
723
+ * A generic org-shared audience taxonomy entry ("external-client",
724
+ * "internal-colleague", …) — NOT tone-specific. Membership lives on the
725
+ * contact (`Contact.group_key`, one group per contact) and is assignable by
726
+ * any flow; tone-of-voice synthesis both reads and auto-assigns groups.
727
+ * Module-deployable (contact-groups/<key>.json).
728
+ */
729
+ export interface ContactGroup {
730
+ org_id: string
731
+ /** Immutable identity within the org — what models answer with. */
732
+ key: string
733
+ name: string
734
+ /** Who belongs in the group — injected verbatim into the synthesis prompt. */
735
+ description?: string
736
+ /** True when tone synthesis proposed the group. Server-owned. */
737
+ is_auto_created: boolean
738
+ /** Module that deployed the group; absent when not module-owned. */
739
+ module_slug?: string
740
+ created_at: string
741
+ created_by: UserRef
742
+ updated_at: string
743
+ updated_by: UserRef
744
+ }
745
+
746
+ export interface CreateContactGroupRequest {
747
+ /** Lowercase kebab/snake/camel handle — no spaces. */
748
+ key: string
749
+ name: string
750
+ description?: string
751
+ module_slug?: string
752
+ }
753
+
754
+ export interface UpdateContactGroupRequest {
755
+ name?: string
756
+ description?: string
757
+ }
758
+
759
+ export interface ListContactGroupsQuery extends PaginationQuery {
760
+ /** Case-insensitive substring match on key or name. */
761
+ search?: string
762
+ module_slug?: string
763
+ }
764
+
765
+ /** The whole-user synthesis lifecycle on a tone profile setup. */
766
+ export type ToneProfileSetupStatus = 'empty' | 'processing' | 'ready'
767
+
768
+ /** A tone profile row's tier — derived, most specific wins at read time. */
769
+ export type ToneProfileScope = 'user' | 'channel' | 'group' | 'contact'
770
+
771
+ /**
772
+ * The per-user opt-in for tone-of-voice synthesis: only set-up users are
773
+ * swept. Also carries the whole-user synthesis claim (status/started_at).
774
+ */
775
+ export interface ToneProfileSetup {
776
+ id: string
777
+ org_id: string
778
+ /** The profiled platform user. */
779
+ owned_by: UserRef
780
+ status: ToneProfileSetupStatus
781
+ started_at?: string
782
+ last_synthesized_at?: string
783
+ created_at: string
784
+ created_by: UserRef
785
+ updated_at: string
786
+ updated_by: UserRef
787
+ }
788
+
789
+ /**
790
+ * One generated tone-of-voice instruction row. Rows form a specificity
791
+ * hierarchy — user aggregate (the constant voice), per-channel base, per
792
+ * contact-group, per individual contact — and every row is SELF-CONTAINED: a
793
+ * drafting consumer injects exactly one row's `instructions` verbatim (use
794
+ * the resolve endpoint), never a concatenation of tiers.
795
+ */
796
+ export interface ToneProfile {
797
+ id: string
798
+ org_id: string
799
+ /** The profiled platform user. */
800
+ owned_by: UserRef
801
+ /** Absent = the cross-channel user aggregate (the voice proper). */
802
+ channel?: Channel
803
+ /** Scopes the row to one contact group; absent = the (user, channel) base. */
804
+ contact_group_key?: string
805
+ /** Scopes the row to one individual contact within the group. */
806
+ contact_id?: string
807
+ scope: ToneProfileScope
808
+ /** COMPLETE markdown instruction set, served verbatim to a drafting model. */
809
+ instructions: string
810
+ /** Short delta vs the tier above — what a human scans; empty on root tiers. */
811
+ differences?: string
812
+ sample_count: number
813
+ last_message_at?: string
814
+ last_synthesized_at?: string
815
+ created_at: string
816
+ created_by: UserRef
817
+ updated_at: string
818
+ updated_by: UserRef
819
+ }
820
+
821
+ export interface CreateToneProfileSetupRequest {
822
+ /** Bare platform user id; the service resolves the full ref. */
823
+ owned_by_id: string
824
+ }
825
+
826
+ export type ListToneProfileSetupsQuery = PaginationQuery
827
+
828
+ export interface ListToneProfilesQuery extends PaginationQuery {
829
+ owned_by_id?: string
830
+ channel?: Channel
831
+ scope?: ToneProfileScope
832
+ }
833
+
834
+ /**
835
+ * A drafting context to resolve the single most-specific profile for:
836
+ * contact → group → channel base → user aggregate.
837
+ */
838
+ export interface ResolveToneProfileQuery {
839
+ owned_by_id: string
840
+ channel?: Channel
841
+ contact_id?: string
842
+ }
843
+
719
844
  export interface PaginationQuery {
720
845
  page?: number
721
846
  page_size?: number
@@ -730,6 +855,17 @@ export interface ListConnectionsQuery extends PaginationQuery {
730
855
  status?: string
731
856
  }
732
857
 
858
+ /**
859
+ * The delete's escape hatch. A connection delete makes the connector release
860
+ * its provider-side registration first and refuses with a 502
861
+ * `connector_uninstall_failed` when that fails — the row is the only handle on
862
+ * that state. `is_forced` drops the row anyway, leaving the provider-side
863
+ * leftovers as a manual cleanup.
864
+ */
865
+ export interface DeleteConnectionQuery {
866
+ is_forced?: boolean
867
+ }
868
+
733
869
  export interface ListConversationsQuery extends PaginationQuery {
734
870
  channel?: string
735
871
  status?: string
@@ -783,18 +919,33 @@ export interface ListAgentListenersQuery extends PaginationQuery {
783
919
  }
784
920
 
785
921
  /**
786
- * Conversation filters: ingest-time rules that drop matching inbound messages
787
- * BEFORE persistence (no message, no contact — only a content-free audit
788
- * event). Scope-first evaluation: connection-scoped rules are final when one
789
- * matches; global rules apply otherwise. Specificity within a scope:
790
- * address > domain > role_based > automated > internal_conversations > all,
791
- * allow beats block within a class.
922
+ * Conversation filters: rules that drop matching inbound messages BEFORE
923
+ * persistence (no message, no contact — only a content-free audit event) and,
924
+ * on meeting calendar connections, gate whether the meeting bot is scheduled
925
+ * at all (pre-join enforcement of the same rules — earliest possible point).
926
+ * Scope-first evaluation: connection-scoped rules are final when one matches;
927
+ * global rules apply otherwise. Specificity within a scope:
928
+ * address > domain > title_keyword > role_based > automated >
929
+ * self_originated > internal_participant > internal_conversations > all,
930
+ * allow beats block within a class; an allow match is a final keep, which is
931
+ * the auto-join composition mechanism (e.g. "organized by me" = a
932
+ * connection-scoped all-block plus a self_originated allow).
933
+ *
934
+ * Channel matrix: address/self_originated/all act on every channel;
935
+ * domain/title_keyword/internal_participant/internal_conversations act on
936
+ * email + meeting connections; role_based/automated are email-only. A
937
+ * connection-scoped rule of a type inert on that connection's channel is
938
+ * rejected (invalid_filter_config); global rules are unrestricted and stay
939
+ * inert where their facts are missing.
792
940
  */
793
941
  export type ConversationFilterType =
794
942
  | 'address'
795
943
  | 'domain'
944
+ | 'title_keyword'
796
945
  | 'role_based'
797
946
  | 'automated'
947
+ | 'self_originated'
948
+ | 'internal_participant'
798
949
  | 'internal_conversations'
799
950
  | 'all'
800
951
  export type ConversationFilterAction = 'block' | 'allow'
@@ -827,6 +978,16 @@ export interface RoleBasedFilterConfig {
827
978
  export interface AutomatedFilterConfig {
828
979
  signals?: AutomatedSignal[]
829
980
  }
981
+ /** Title/subject contains any keyword (case-insensitive substring; stored lowercased). */
982
+ export interface TitleKeywordFilterConfig {
983
+ keywords: string[]
984
+ }
985
+ /** Conversation originates from the connection owner (meeting organizer / self sender). Empty config. */
986
+ export type SelfOriginatedFilterConfig = Record<string, never>
987
+ /** ≥1 participant OTHER than the connection self is on one of these domains (any-internal). */
988
+ export interface InternalParticipantFilterConfig {
989
+ domains: string[]
990
+ }
830
991
  /** Drops only when sender AND every recipient are on these domains. Always block. */
831
992
  export interface InternalConversationsFilterConfig {
832
993
  domains: string[]
@@ -837,8 +998,11 @@ export type AllFilterConfig = Record<string, never>
837
998
  export type ConversationFilterConfig =
838
999
  | AddressFilterConfig
839
1000
  | DomainFilterConfig
1001
+ | TitleKeywordFilterConfig
840
1002
  | RoleBasedFilterConfig
841
1003
  | AutomatedFilterConfig
1004
+ | SelfOriginatedFilterConfig
1005
+ | InternalParticipantFilterConfig
842
1006
  | InternalConversationsFilterConfig
843
1007
  | AllFilterConfig
844
1008
 
@@ -954,6 +1118,13 @@ export interface Contact {
954
1118
  /** Merge tombstone redirect (set when status is 'merged'). */
955
1119
  merged_into_contact_id?: string
956
1120
  source: ContactSource
1121
+ /** ContactGroup membership (one group per contact); absent = unassigned. */
1122
+ group_key?: string
1123
+ /**
1124
+ * Who assigned the group: 'manual' assignments are authoritative (tone
1125
+ * synthesis never overrides them), 'model' ones may be reassigned by a run.
1126
+ */
1127
+ group_source?: ContactGroupSource
957
1128
  has_manual_edits: boolean
958
1129
  /** The contact's reachable endpoints, embedded on reads. */
959
1130
  addresses?: ContactAddress[]
@@ -1066,12 +1237,19 @@ export interface ListContactsQuery extends PaginationQuery {
1066
1237
  /** Free-text needle matched against contact name + address values. */
1067
1238
  q?: string
1068
1239
  status?: ContactStatus
1240
+ /** Members of one contact group (drives group-member lists). */
1241
+ group_key?: string
1069
1242
  }
1070
1243
 
1071
1244
  export interface UpdateContactRequest {
1072
1245
  name?: string
1073
1246
  status?: 'active' | 'archived'
1074
1247
  has_legal_hold?: boolean
1248
+ /**
1249
+ * Assigns the contact to a contact group ('' clears). A PATCH assignment is
1250
+ * stamped group_source='manual' — tone synthesis never overrides it.
1251
+ */
1252
+ group_key?: string
1075
1253
  }
1076
1254
 
1077
1255
  export interface AttachContactAddressRequest {
package/src/index.ts CHANGED
@@ -100,6 +100,7 @@ export type {
100
100
  StopReason,
101
101
  TextBlock,
102
102
  PlatformBinding,
103
+ QueryBinding,
103
104
  Tool,
104
105
  ToolBinding,
105
106
  ToolConfirmationPayload,
@@ -220,6 +221,9 @@ export type {
220
221
  ContactAddressKind,
221
222
  ContactAddressSource,
222
223
  ContactErasureRequest,
224
+ ContactGroup,
225
+ ContactGroupService,
226
+ ContactGroupSource,
223
227
  ContactMergeProposal,
224
228
  ContactRef,
225
229
  ContactService,
@@ -243,9 +247,11 @@ export type {
243
247
  ConversationTypeService,
244
248
  CreateAgentListenerRequest,
245
249
  CreateConnectionRequest,
250
+ CreateContactGroupRequest,
246
251
  CreateConversationFilterRequest,
247
252
  CreateConversationTypeRequest,
248
253
  CreateGlossaryTermRequest,
254
+ CreateToneProfileSetupRequest,
249
255
  DispatchMeetingBotRequest,
250
256
  DomainFilterConfig,
251
257
  ErasureRequestStatus,
@@ -257,6 +263,7 @@ export type {
257
263
  ListAgentListenersQuery,
258
264
  ListConnectionsQuery,
259
265
  ListContactAddressesQuery,
266
+ ListContactGroupsQuery,
260
267
  ListContactMergeProposalsQuery,
261
268
  ListContactsQuery,
262
269
  ListConversationFilterEventsQuery,
@@ -270,6 +277,8 @@ export type {
270
277
  // PageIterator-based ListResult used by the other modules.
271
278
  ListResponse,
272
279
  ListRoomsQuery,
280
+ ListToneProfileSetupsQuery,
281
+ ListToneProfilesQuery,
273
282
  MeetingService,
274
283
  MergeContactsRequest,
275
284
  MergeProposalStatus,
@@ -292,11 +301,17 @@ export type {
292
301
  RecipientKind,
293
302
  RecipientRole,
294
303
  RecordPermissionEventRequest,
304
+ ResolveToneProfileQuery,
295
305
  RoleBasedFilterConfig,
296
306
  Room,
297
307
  SendMessageRequest,
298
308
  SendRecipient,
299
309
  SyncConnectionRequest,
310
+ ToneProfile,
311
+ ToneProfileScope,
312
+ ToneProfileService,
313
+ ToneProfileSetup,
314
+ ToneProfileSetupStatus,
300
315
  TranscribeStreamOptions,
301
316
  Transcription,
302
317
  TranscriptionReviewStatus,
@@ -306,6 +321,7 @@ export type {
306
321
  UnreadCounts,
307
322
  UpdateAgentListenerRequest,
308
323
  UpdateConnectionRequest,
324
+ UpdateContactGroupRequest,
309
325
  UpdateContactRequest,
310
326
  UpdateConversationFilterRequest,
311
327
  UpdateConversationTypeRequest,