@ai-matrx/associations 0.5.2 → 0.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.
@@ -0,0 +1,1905 @@
1
+ import * as react from 'react';
2
+ import { ComponentType, ReactNode, ElementType, SVGProps } from 'react';
3
+
4
+ /** Per-RPC Args/Returns for every demanded function, straight from the live DB. */
5
+ interface DemandedRpcSignatures {
6
+ assoc_add: {
7
+ Args: {
8
+ p_label?: string;
9
+ p_metadata?: unknown;
10
+ p_org_id?: string;
11
+ p_payload?: unknown;
12
+ p_payload_kind?: string;
13
+ p_position?: number;
14
+ p_role?: string;
15
+ p_source_id: string;
16
+ p_source_type: string;
17
+ p_target_id: string;
18
+ p_target_type: string;
19
+ };
20
+ Returns: string;
21
+ };
22
+ assoc_remove: {
23
+ Args: {
24
+ p_role?: string;
25
+ p_source_id: string;
26
+ p_source_type: string;
27
+ p_target_id: string;
28
+ p_target_type: string;
29
+ };
30
+ Returns: undefined;
31
+ };
32
+ assoc_set_targets: {
33
+ Args: {
34
+ p_org_id?: string;
35
+ p_role?: string;
36
+ p_source_id: string;
37
+ p_source_type: string;
38
+ p_target_ids: string[];
39
+ p_target_type: string;
40
+ };
41
+ Returns: undefined;
42
+ };
43
+ assoc_remove_for_entity: {
44
+ Args: {
45
+ p_id: string;
46
+ p_type: string;
47
+ };
48
+ Returns: undefined;
49
+ };
50
+ assoc_for_entity: {
51
+ Args: {
52
+ p_id: string;
53
+ p_type: string;
54
+ };
55
+ Returns: {
56
+ created_at: string;
57
+ direction: string;
58
+ id: string;
59
+ label: string;
60
+ metadata: unknown;
61
+ organization_id: string;
62
+ other_id: string;
63
+ other_type: string;
64
+ position: number;
65
+ role: string;
66
+ }[];
67
+ };
68
+ assoc_for_targets: {
69
+ Args: {
70
+ p_target_ids: string[];
71
+ p_target_type: string;
72
+ };
73
+ Returns: {
74
+ created_at: string;
75
+ id: string;
76
+ label: string;
77
+ metadata: unknown;
78
+ organization_id: string;
79
+ position: number;
80
+ role: string;
81
+ source_id: string;
82
+ source_type: string;
83
+ target_id: string;
84
+ }[];
85
+ };
86
+ assoc_for_sources: {
87
+ Args: {
88
+ p_source_ids: string[];
89
+ p_source_type: string;
90
+ p_target_type?: string;
91
+ };
92
+ Returns: {
93
+ created_at: string;
94
+ id: string;
95
+ label: string;
96
+ metadata: unknown;
97
+ organization_id: string;
98
+ position: number;
99
+ role: string;
100
+ source_id: string;
101
+ target_id: string;
102
+ target_type: string;
103
+ }[];
104
+ };
105
+ assoc_members_visible: {
106
+ Args: {
107
+ p_target_ids: string[];
108
+ p_target_type: string;
109
+ };
110
+ Returns: {
111
+ created_at: string;
112
+ id: string;
113
+ label: string;
114
+ metadata: unknown;
115
+ organization_id: string;
116
+ position: number;
117
+ role: string;
118
+ source_id: string;
119
+ source_type: string;
120
+ target_id: string;
121
+ }[];
122
+ };
123
+ conversation_file_add: {
124
+ Args: {
125
+ p_conversation_id: string;
126
+ p_file_id: string;
127
+ p_label?: string;
128
+ p_metadata?: unknown;
129
+ p_replace_metadata?: boolean;
130
+ };
131
+ Returns: string;
132
+ };
133
+ conversation_file_remove: {
134
+ Args: {
135
+ p_conversation_id: string;
136
+ p_file_id: string;
137
+ };
138
+ Returns: undefined;
139
+ };
140
+ conversation_files: {
141
+ Args: {
142
+ p_conversation_id: string;
143
+ };
144
+ Returns: {
145
+ created_at: string;
146
+ file_id: string;
147
+ label: string;
148
+ metadata: unknown;
149
+ }[];
150
+ };
151
+ agent_resource_add: {
152
+ Args: {
153
+ p_agent_id: string;
154
+ p_label?: string;
155
+ p_metadata?: unknown;
156
+ p_source_id: string;
157
+ p_source_type: string;
158
+ };
159
+ Returns: string;
160
+ };
161
+ agent_resource_remove: {
162
+ Args: {
163
+ p_agent_id: string;
164
+ p_source_id: string;
165
+ p_source_type: string;
166
+ };
167
+ Returns: undefined;
168
+ };
169
+ cat_list: {
170
+ Args: {
171
+ p_dimension?: string;
172
+ };
173
+ Returns: {
174
+ color: string;
175
+ dimension: string;
176
+ icon: string;
177
+ id: string;
178
+ is_system: boolean;
179
+ metadata: unknown;
180
+ name: string;
181
+ organization_id: string;
182
+ parent_id: string;
183
+ position: number;
184
+ slug: string;
185
+ }[];
186
+ };
187
+ cat_create: {
188
+ Args: {
189
+ p_color?: string;
190
+ p_dimension: string;
191
+ p_icon?: string;
192
+ p_name: string;
193
+ p_org_id: string;
194
+ p_parent_id?: string;
195
+ p_slug?: string;
196
+ };
197
+ Returns: string;
198
+ };
199
+ cat_update: {
200
+ Args: {
201
+ p_category_id: string;
202
+ p_color?: string;
203
+ p_icon?: string;
204
+ p_name: string;
205
+ p_position?: number;
206
+ p_slug?: string;
207
+ };
208
+ Returns: string;
209
+ };
210
+ cat_reparent: {
211
+ Args: {
212
+ p_category_id: string;
213
+ p_parent_id?: string;
214
+ };
215
+ Returns: string;
216
+ };
217
+ cat_delete: {
218
+ Args: {
219
+ p_category_id: string;
220
+ };
221
+ Returns: string;
222
+ };
223
+ ues_set: {
224
+ Args: {
225
+ p_entity_id: string;
226
+ p_entity_type: string;
227
+ p_is_favorite?: boolean;
228
+ p_is_hidden?: boolean;
229
+ p_is_pinned?: boolean;
230
+ };
231
+ Returns: undefined;
232
+ };
233
+ ues_list: {
234
+ Args: {
235
+ p_kind?: string;
236
+ };
237
+ Returns: {
238
+ entity_id: string;
239
+ entity_type: string;
240
+ is_favorite: boolean;
241
+ is_hidden: boolean;
242
+ is_pinned: boolean;
243
+ last_viewed_at: string;
244
+ updated_at: string;
245
+ }[];
246
+ };
247
+ ues_get_bulk: {
248
+ Args: {
249
+ p_entity_ids: string[];
250
+ p_entity_type: string;
251
+ };
252
+ Returns: {
253
+ entity_id: string;
254
+ is_favorite: boolean;
255
+ is_hidden: boolean;
256
+ is_pinned: boolean;
257
+ last_viewed_at: string;
258
+ }[];
259
+ };
260
+ ues_touch: {
261
+ Args: {
262
+ p_entity_id: string;
263
+ p_entity_type: string;
264
+ };
265
+ Returns: undefined;
266
+ };
267
+ reference_search_candidates: {
268
+ Args: {
269
+ p_ids?: string[];
270
+ p_limit?: number;
271
+ p_search?: string;
272
+ p_token: string;
273
+ };
274
+ Returns: {
275
+ id: string;
276
+ title: string;
277
+ }[];
278
+ };
279
+ cmt_list: {
280
+ Args: {
281
+ p_entity_id: string;
282
+ p_entity_type: string;
283
+ };
284
+ Returns: {
285
+ author_avatar_url: string;
286
+ author_display_name: string;
287
+ author_email: string;
288
+ body: string;
289
+ created_at: string;
290
+ created_by: string;
291
+ entity_id: string;
292
+ entity_type: string;
293
+ id: string;
294
+ organization_id: string;
295
+ parent_id: string;
296
+ updated_at: string;
297
+ }[];
298
+ };
299
+ cmt_add: {
300
+ Args: {
301
+ p_body: string;
302
+ p_entity_id: string;
303
+ p_entity_type: string;
304
+ p_org_id?: string;
305
+ p_parent_id?: string;
306
+ };
307
+ Returns: string;
308
+ };
309
+ cmt_edit: {
310
+ Args: {
311
+ p_body: string;
312
+ p_id: string;
313
+ };
314
+ Returns: undefined;
315
+ };
316
+ cmt_delete: {
317
+ Args: {
318
+ p_id: string;
319
+ };
320
+ Returns: undefined;
321
+ };
322
+ }
323
+ /** The name of any demanded RPC — the only strings the dataSource port accepts. */
324
+ type DemandedRpcName = keyof DemandedRpcSignatures;
325
+
326
+ /**
327
+ * EVERY registered entity token (the FK-valid set). Use this for any
328
+ * `source_type` / `target_type` argument so an invalid token is a COMPILE error.
329
+ */
330
+ type EntityTypeToken = "access_request" | "activity" | "agent" | "agent_card" | "agent_definition_version" | "agent_drift_alert" | "agent_exemplar" | "agent_mandate_note" | "agent_prompt_remediation" | "agent_run" | "agent_run_stage" | "agent_shortcut" | "agent_surface_binding" | "agent_template" | "agent_usage" | "ai_api" | "ai_endpoint" | "ai_model" | "ai_model_alias" | "ai_offering" | "ai_provider" | "ai_setting" | "app" | "app_definition_version" | "app_error" | "app_execution" | "app_instance" | "app_log" | "app_rate_limit" | "app_setting" | "app_sync_status" | "approach" | "artifact" | "assessment" | "assessment_item" | "assessment_result" | "assist" | "batch_cost_event" | "batch_provider_batch" | "batch_work_item" | "browser_account_binding" | "browser_action_event" | "browser_authenticator_window" | "browser_capture" | "browser_control_request" | "browser_handoff" | "browser_login_attempt" | "browser_login_recipe" | "browser_profile" | "browser_profile_checkpoint" | "browser_run" | "browser_site_observation" | "browser_site_policy" | "browser_stream_ticket" | "canvas_comment" | "canvas_comment_like" | "canvas_item" | "canvas_item_state" | "canvas_like" | "canvas_score" | "canvas_view" | "category" | "cmp_entry" | "cmp_feedback" | "code_file" | "code_folder" | "code_repository" | "coding_session" | "coding_session_entry" | "comment" | "commerce_asset_allocation" | "commerce_asset_grading" | "commerce_asset_identifier" | "commerce_asset_lot_event" | "commerce_asset_mandate_result" | "commerce_asset_price_factor" | "commerce_asset_reshoot_request" | "commerce_asset_review" | "commerce_asset_unknown" | "commerce_cloud_sync_connection" | "commerce_ebay_business_policy" | "commerce_ebay_category" | "commerce_ebay_category_aspect" | "commerce_ebay_category_tree" | "commerce_ebay_custom_policy" | "commerce_ebay_inventory_item" | "commerce_ebay_inventory_item_group" | "commerce_ebay_inventory_item_group_member" | "commerce_ebay_inventory_location" | "commerce_ebay_listing" | "commerce_ebay_marketplace_policy" | "commerce_ebay_media_asset" | "commerce_ebay_notification_destination" | "commerce_ebay_notification_event" | "commerce_ebay_notification_subscription" | "commerce_ebay_notification_topic" | "commerce_ebay_offer" | "commerce_ebay_order" | "commerce_ebay_order_line_item" | "commerce_ebay_shipping_fulfillment" | "commerce_ebay_store_category" | "commerce_human_correction" | "commerce_intake_artifact" | "commerce_intake_asset" | "commerce_intake_batch" | "commerce_label_batch" | "commerce_label_code" | "commerce_marketplace_account" | "commerce_marketplace_account_deletion_audit" | "commerce_marketplace_api_call" | "commerce_marketplace_rate_budget" | "commerce_marketplace_site" | "commerce_marketplace_sync_run" | "commerce_prediction_outcome" | "commerce_product" | "commerce_product_channel_ref" | "commerce_product_media" | "commerce_product_variant" | "commerce_recall_audit" | "comparison_set" | "contact_medium" | "contact_submission" | "content_ir_kind" | "content_ir_kind_component" | "content_ir_kind_component_incident" | "content_ir_kind_conformance" | "content_ir_kind_edge" | "content_ir_kind_example" | "content_ir_kind_instance" | "content_ir_kind_surface" | "context_item" | "context_item_suggestion" | "conversation" | "conversation_value" | "crm_address" | "crm_affiliation" | "crm_blocklist_entry" | "crm_contact_candidate" | "crm_deal" | "crm_deal_stage_event" | "crm_enrichment_call" | "crm_interaction" | "crm_merge_candidate" | "crm_outreach_list" | "crm_outreach_list_member" | "crm_party_merge" | "crm_registry_ingest_run" | "crm_registry_source" | "crm_saved_view" | "crm_sending_event" | "crm_sending_identity" | "crm_sending_identity_check" | "crm_sending_policy" | "custom_entity_definition" | "custom_field_definition" | "custom_field_target" | "custom_record" | "cx_agent_memory" | "cx_agent_plan" | "cx_agent_task" | "cx_code_edit" | "cx_code_message_file" | "cx_media" | "cx_observational_memory" | "cx_observational_memory_event" | "cx_pending_injection" | "cx_request" | "cx_request_snapshot" | "cx_tool_trace" | "cx_user_request" | "cx_user_todo" | "data_store" | "dataset" | "derive_run" | "dict_setting" | "dm_conversation" | "dm_message" | "dm_participant" | "domain_classification" | "esign_campaign" | "esign_campaign_member" | "esign_consent_disclosure" | "esign_envelope" | "esign_envelope_certificate" | "esign_envelope_document" | "esign_envelope_event" | "esign_envelope_external_ref" | "esign_envelope_signer" | "esign_provider" | "esign_provider_binding" | "esign_signing_key" | "fc_card" | "fc_detail" | "fc_set" | "feature_doc" | "file" | "file_analysis" | "file_entities" | "file_overrides" | "file_page_annotations" | "file_pages" | "file_version" | "flexible_data" | "folder" | "game_badge" | "game_result" | "game_room" | "global_execution" | "global_execution_checkpoint" | "global_execution_event" | "global_meter_entry" | "global_origin" | "global_request" | "growth_loop_event" | "growth_loop_run" | "growth_loop_stage_run" | "guided_checklist_run" | "heatmap_save" | "hindsight_enrollment" | "hindsight_finding" | "hindsight_regression_case" | "hindsight_replay" | "hindsight_replay_step" | "hindsight_review" | "hr_access_audit" | "hr_access_role" | "hr_accommodation_request" | "hr_ai_evidence" | "hr_alert_routing_rule" | "hr_application" | "hr_approval_authority" | "hr_approval_delegation" | "hr_asset" | "hr_asset_assignment" | "hr_attendance_exception" | "hr_auto_close_rule" | "hr_availability" | "hr_background_check" | "hr_benefits_event" | "hr_calculation_snapshot" | "hr_candidate" | "hr_candidate_conversion" | "hr_candidate_message" | "hr_careers_portal" | "hr_checklist_item" | "hr_checklist_run" | "hr_checklist_template" | "hr_checklist_template_item" | "hr_compensation" | "hr_corrective_action" | "hr_course" | "hr_course_version" | "hr_credential" | "hr_crew" | "hr_deduction_code" | "hr_department" | "hr_derived_grant" | "hr_disposition_event" | "hr_earning_code" | "hr_eeo_response" | "hr_emergency_contact" | "hr_employee" | "hr_employee_private" | "hr_employer_profile" | "hr_employment" | "hr_employment_pin" | "hr_engagement" | "hr_establishment" | "hr_external_identity" | "hr_field_policy" | "hr_holiday" | "hr_holiday_calendar" | "hr_i9" | "hr_i9_document" | "hr_incident" | "hr_incident_party" | "hr_interview" | "hr_interview_kit" | "hr_job_title" | "hr_jurisdiction" | "hr_jurisdiction_rule" | "hr_jurisdiction_rule_class" | "hr_jurisdiction_rule_org_decision" | "hr_jurisdiction_rule_test" | "hr_kiosk_device" | "hr_kiosk_session" | "hr_labor_target" | "hr_leave_case" | "hr_leave_enrollment" | "hr_leave_ledger" | "hr_leave_policy" | "hr_leave_request" | "hr_legal_hold" | "hr_legal_hold_item" | "hr_location" | "hr_new_hire_report" | "hr_offer" | "hr_opening" | "hr_overtime_alert" | "hr_overtime_alert_rule" | "hr_overtime_preapproval" | "hr_pay_group" | "hr_pay_period" | "hr_pay_period_employment" | "hr_payroll_export" | "hr_payroll_export_line" | "hr_position_assignment" | "hr_posting" | "hr_posting_publication" | "hr_provider_binding" | "hr_provider_event" | "hr_provisioning_result" | "hr_punch" | "hr_recalculation_batch" | "hr_record_class" | "hr_records_request" | "hr_reference_check" | "hr_reporting_line" | "hr_requisition" | "hr_restricted_note" | "hr_retention_rule" | "hr_role_assignment" | "hr_schedule" | "hr_schedule_change" | "hr_schedule_guidance" | "hr_schedule_template" | "hr_schedule_template_shift" | "hr_scorecard" | "hr_separation" | "hr_shift" | "hr_shift_claim" | "hr_staffing_requirement" | "hr_survey" | "hr_survey_invitation" | "hr_survey_question" | "hr_survey_response" | "hr_tax_registration" | "hr_tax_withholding" | "hr_time_adjustment" | "hr_training_assignment" | "hr_training_attempt" | "hr_transcript_entry" | "hr_verification_letter_request" | "hr_work_interval" | "hr_workflow_binding" | "hr_workflow_decision" | "hr_workflow_definition" | "hr_workflow_event" | "hr_workflow_failure" | "hr_workflow_flow_type" | "hr_workflow_instance" | "hr_workflow_step" | "hr_workflow_step_definition" | "hr_workweek" | "iam_api_key" | "industry_curator" | "interview_document_revision" | "interview_hole" | "interview_question" | "interview_session" | "interview_turn" | "invitation" | "invitation_code" | "invitation_request" | "item_mastery" | "judge_verdict" | "kg_alert" | "kg_suggestion_ack" | "kg_sweep_queue" | "kg_sweep_run" | "kg_sweep_state" | "kg_value_match" | "league_membership" | "learn_doc" | "library_doc" | "mandate" | "mandate_binding" | "mandate_treatment" | "marketing_initiative" | "masterwork_corpus_item" | "masterwork_run" | "membership" | "message" | "message_template" | "ner_shadow" | "note" | "note_folder" | "notification" | "notification_channel_preference" | "notification_event_override" | "notification_event_type" | "notification_preference" | "ops_issue_event" | "ops_proof_check" | "ops_proof_run" | "ops_proof_scenario" | "organization" | "output_feedback" | "page_extraction_job" | "page_extraction_page_run" | "party" | "party_contact_point" | "pc_article" | "pc_episode" | "pc_show" | "pc_studio_run" | "pc_studio_run_asset" | "pdf_redaction_audit" | "plan_cms_fill_item" | "plan_cms_fill_job" | "plan_entity" | "plan_node" | "plan_node_artifact" | "plan_node_step" | "plan_profile" | "platform_actor_session" | "platform_actor_token" | "platform_actor_token_event" | "platform_continued_access" | "platform_outcome_event" | "platform_outsider_consumer" | "platform_saved_view" | "podcast_race" | "processed_document" | "processed_document_page" | "product_capture_file" | "product_capture_item" | "product_capture_payload" | "product_capture_product" | "product_capture_question" | "project" | "provision" | "purpose" | "quiz_session" | "rag_ingest_run" | "redaction_mapping" | "research_analysis" | "research_content" | "research_context_bundle" | "research_document" | "research_keyword" | "research_media" | "research_source" | "research_synthesis" | "research_tag" | "research_template" | "research_topic" | "route_manifest_entry" | "rulebook" | "sandbox_instance" | "sch_agent_task" | "sch_run" | "sch_task" | "sch_trigger" | "scope" | "scope_association_suggestion" | "scope_item_value_suggestion" | "scope_suggestion" | "scope_type" | "seo_ai_visibility_citation" | "seo_ai_visibility_claim" | "seo_ai_visibility_panel" | "seo_ai_visibility_response" | "seo_ai_visibility_signal" | "seo_backlink" | "seo_backlink_change_event" | "seo_backlink_dimension_snapshot" | "seo_backlink_observation" | "seo_backlink_snapshot" | "seo_change_assessment" | "seo_change_event" | "seo_change_item" | "seo_change_metric" | "seo_change_set" | "seo_change_theory" | "seo_collection_run" | "seo_competitor" | "seo_competitor_observation" | "seo_competitor_opportunity" | "seo_coverage_mention" | "seo_coverage_tracker" | "seo_dimension_value_matcher" | "seo_engine_schedule" | "seo_geo_place" | "seo_gsc_dig_rule" | "seo_keyword" | "seo_keyword_class_rule" | "seo_keyword_edge" | "seo_keyword_facet" | "seo_keyword_market" | "seo_keyword_market_observation" | "seo_keyword_place" | "seo_keyword_saved_view" | "seo_keyword_topic" | "seo_landscape_brief" | "seo_link_gap_domain" | "seo_link_gap_match" | "seo_page_measurement_health" | "seo_page_performance" | "seo_provider_call" | "seo_provider_task" | "seo_rank_observation" | "seo_rank_target" | "seo_raw_payload" | "seo_referring_domain_profile" | "seo_reputation_case" | "seo_search_performance_daily" | "seo_serp_mention" | "seo_serp_opportunity" | "seo_serp_result" | "seo_serp_snapshot" | "seo_site_geo_area" | "seo_site_keyword_offering" | "seo_site_keyword_value" | "seo_site_offering_value" | "seo_site_topic_value" | "seo_site_value_combo" | "seo_site_value_worth" | "seo_site_vocabulary" | "seo_source_request" | "seo_starter_pack" | "seo_starter_pack_item" | "seo_story_angle" | "seo_topic" | "seo_web_analytics_daily" | "shared_canvas_item" | "short_link" | "skill" | "skill_render_definition" | "sms_consent" | "sms_conversation" | "sms_message" | "sms_message_media" | "sms_notification" | "sms_notification_preference" | "sms_phone_number" | "structured_list" | "studio_documents" | "studio_recording_chunks" | "studio_recording_segments" | "studio_run" | "studio_session" | "studio_session_settings" | "study_attempt" | "study_goal" | "study_media" | "study_plan" | "study_plan_block" | "study_plan_day" | "study_reminder_context" | "study_reminder_delivery" | "study_session" | "surface" | "system_context_item" | "system_error" | "system_personal_org_failure" | "system_write_failure" | "task" | "thread" | "tool" | "tool_bundle" | "tool_call" | "tool_definition_version" | "tool_test_sample" | "tool_ui" | "tool_ui_incident" | "tool_ui_version" | "transcript" | "udt_dataset_fields" | "udt_dataset_rows" | "udt_document" | "udt_structured_list_items" | "ui_surface_agent_pref" | "ui_surface_config" | "user_achievement" | "user_analysis_preference" | "user_bookmark" | "user_email_preference" | "user_feedback" | "user_form_profile" | "user_markdown_sample" | "user_memory" | "user_preference" | "user_profile" | "user_stat" | "user_surface_state" | "voice" | "war_room" | "wbx_capture" | "wbx_guidance" | "wbx_highlight" | "wbx_pattern" | "wbx_screenshot" | "wbx_seo_audit" | "wc_claim" | "wc_impairment_definition" | "wc_injury" | "wc_report" | "web_analysis_item" | "web_brand" | "web_brand_asset" | "web_brand_offering" | "web_business_fact" | "web_business_location" | "web_crawl_event" | "web_crawl_preset" | "web_crawl_schedule" | "web_crawl_session" | "web_crawl_url" | "web_discovered_item" | "web_finding" | "web_gsc_page_stat" | "web_link_edge" | "web_listing_publisher" | "web_location_listing" | "web_offering_template" | "web_page" | "web_page_content" | "web_page_evidence" | "web_page_sitemap" | "web_property" | "web_provider" | "web_result" | "web_screenshot" | "web_site" | "web_site_endpoint_rule" | "web_site_item_config" | "web_site_offering" | "web_sitemap" | "web_snapshot" | "wf_node_data_slot" | "work_item" | "workbook" | "workflow" | "workflow_card" | "workflow_checkpoint" | "workflow_comparison" | "workflow_definition_version" | "workflow_idempotency" | "workflow_job" | "workflow_node_events" | "workflow_node_outcome" | "workflow_plan" | "workflow_plan_event" | "workflow_plan_sample" | "workflow_recovery_audit" | "workflow_run" | "workflow_run_log" | "workflow_runtime_surface" | "workflow_template" | "workflow_trigger" | "workflow_trigger_fire" | "working_document" | "youtube_search" | "youtube_video";
331
+
332
+ type AssociationsRpcErrorCode = "unauthorized" | "forbidden_org" | "forbidden_role" | "not_found" | "conflict_in_use" | "invalid_argument" | "version_conflict" | "quota_exceeded"
333
+ /**
334
+ * THE DEMANDED-SCHEMA SCREAM. A PostgREST missing-function error (PGRST202)
335
+ * on any demanded RPC maps to this code: the database this client is
336
+ * pointed at does not run the schema this package demands (README front
337
+ * door). It always reaches the errorSink — one unambiguous scream, never a
338
+ * mystery toast. Probe it at boot with `assertDemandedSchema` (/core, W2).
339
+ */
340
+ | "demanded_schema_violation" | "internal";
341
+ interface AssociationsRpcError {
342
+ code: AssociationsRpcErrorCode;
343
+ message: string;
344
+ hint?: string;
345
+ detail?: unknown;
346
+ }
347
+ type AssociationsRpcResult<T> = {
348
+ ok: true;
349
+ data: T;
350
+ } | {
351
+ ok: false;
352
+ error: AssociationsRpcError;
353
+ };
354
+ /**
355
+ * The structural shape of a PostgREST failure as supabase-js resolves it: a
356
+ * PLAIN OBJECT parsed from the response body — NOT an `Error` instance.
357
+ * (Reading `.message` off `instanceof Error` discards the real database
358
+ * message on every genuine failure; `/core`'s mapper reads these fields.)
359
+ */
360
+ interface PgError {
361
+ code?: string | null;
362
+ message: string;
363
+ details?: string | null;
364
+ hint?: string | null;
365
+ }
366
+
367
+ /**
368
+ * The minimal table surface entity-row create/rename needs (a structural
369
+ * subset of supabase-js's query builder). Registry-convention writes go
370
+ * DIRECT to the backing table (they are RLS-gated feature rows, not
371
+ * association edges — there is no RPC for them by design).
372
+ */
373
+ interface AssociationsTableQuery {
374
+ insert(row: Record<string, unknown>): {
375
+ select(columns: string): {
376
+ single(): PromiseLike<{
377
+ data: unknown;
378
+ error: PgError | null;
379
+ }>;
380
+ };
381
+ };
382
+ update(patch: Record<string, unknown>): {
383
+ eq(column: string, value: string): PromiseLike<{
384
+ error: PgError | null;
385
+ }>;
386
+ };
387
+ }
388
+ /**
389
+ * The data seam — a structural subset of `SupabaseClient<Database>`: any
390
+ * client that can answer the demanded RPC families (README § The demanded
391
+ * schema). The package IS data operations; there is no degraded mode without
392
+ * one. `PromiseLike` because supabase-js returns a thenable builder, not a
393
+ * `Promise`.
394
+ *
395
+ * `from`/`schema` are OPTIONAL (W2, additive): only the entity-row
396
+ * create/rename service uses them (generic registry-convention row writes).
397
+ * A dataSource without them still satisfies every RPC operation; calling
398
+ * entity-row create/rename against it returns a screamed `{ok:false}`
399
+ * result naming the missing capability — never a silent no-op. A real
400
+ * supabase-js client satisfies both structurally.
401
+ */
402
+ interface AssociationsDataSource {
403
+ rpc(fn: DemandedRpcName, args: Record<string, unknown>): PromiseLike<{
404
+ data: unknown;
405
+ error: PgError | null;
406
+ }>;
407
+ from?(table: string): AssociationsTableQuery;
408
+ schema?(name: string): {
409
+ from(table: string): AssociationsTableQuery;
410
+ };
411
+ }
412
+ /**
413
+ * The identity seam — today a store-singleton read (`requireUserId`) plus the
414
+ * org resolver `CategoryTagPicker` uses for created rows. `requireUserId`
415
+ * failures stay LOUD (`Not authenticated`) — never silently anonymous.
416
+ */
417
+ interface AssociationsIdentity {
418
+ requireUserId(): string;
419
+ /** Org for created rows/edges (the CategoryTagPicker create path). */
420
+ ensureOrgId?(): Promise<string>;
421
+ }
422
+ /**
423
+ * The scream seam. Every degraded path, every `demanded_schema_violation`,
424
+ * every create-then-attach partial failure reports here regardless of
425
+ * notifier availability.
426
+ *
427
+ * DEFAULT (0.6.0, C23): absent → `createDefaultErrorSink()` — a tagged
428
+ * `console.error` per event that announces ONCE that no sink is bound and
429
+ * names the remedy. A host with a diagnostics surface binds its own.
430
+ */
431
+ type ErrorSink = (event: {
432
+ code: string;
433
+ message: string;
434
+ context?: object;
435
+ }) => void;
436
+ /**
437
+ * Per-token host overlay — the code-native values the DB registry cannot
438
+ * carry (today: the 804-line ENTITY_OVERLAY literal in matrx-frontend's
439
+ * entityRegistry). EVERY field optional; absence degrades per field:
440
+ * convention columns, default icon, `${label}s`, no door, generic
441
+ * titleColumn candidate read. A `reference_pickable` token with no title
442
+ * column and no override is screamed to the errorSink, never shown broken.
443
+ */
444
+ interface EntityOverlayEntry {
445
+ /** Icon component (host-supplied; packages never depend on an icon library). */
446
+ Icon?: ElementType;
447
+ /** Plural label; default `${label}s`. */
448
+ labelPlural?: string;
449
+ /** Owner column override; default the "created_by" convention. */
450
+ ownerColumn?: string | null;
451
+ /** Org column override; default the "organization_id" convention. */
452
+ orgColumn?: string | null;
453
+ /** Route for this token's rows; absent → no open door (label renders plain). */
454
+ hrefFor?: (id: string) => string;
455
+ /**
456
+ * Candidate-list override for tokens whose backing table can't be read
457
+ * client-side (e.g. `data_store` — rag.* is not PostgREST-exposed);
458
+ * absent → the generic `reference_search_candidates` titleColumn read.
459
+ */
460
+ listCandidates?: (args: {
461
+ search?: string;
462
+ limit?: number;
463
+ }) => Promise<{
464
+ ok: true;
465
+ data: {
466
+ id: string;
467
+ title: string;
468
+ }[];
469
+ } | {
470
+ ok: false;
471
+ error: string;
472
+ }>;
473
+ }
474
+ /** The overlay registration map — bound per host, merged over the generated registry. */
475
+ type EntityOverlayMap = Partial<Record<EntityTypeToken, EntityOverlayEntry>>;
476
+ /**
477
+ * The user-notification seam (today: `@/lib/toast` in 6 components).
478
+ * Optional — /react warns once when absent. Every user-facing failure ALSO
479
+ * routes to the errorSink + the component's inline error state, so the
480
+ * create-then-associate loud-outcome law is satisfied structurally, not by
481
+ * toast availability.
482
+ */
483
+ interface AssociationsNotifier {
484
+ success(msg: string): void;
485
+ error(msg: string, opts?: {
486
+ description?: string;
487
+ action?: {
488
+ label: string;
489
+ onClick(): void;
490
+ };
491
+ }): void;
492
+ }
493
+ /**
494
+ * The window seam.
495
+ *
496
+ * DEFAULT (0.6.0, C23): absent → `DefaultWindowShell`, the package's OWN
497
+ * window — draggable, resizable, maximizable, viewport-clamped, portalled,
498
+ * non-modal, mobile bottom-card. Not a degradation; the shipped default.
499
+ * A host binds this port only when its own window MANAGER (tray docking,
500
+ * workspace persistence, cross-window z-order) must own the surface.
501
+ */
502
+ interface WindowShellPort {
503
+ Window: ComponentType<{
504
+ id: string;
505
+ title: string;
506
+ onClose(): void;
507
+ children: ReactNode;
508
+ }>;
509
+ }
510
+ /** Options for {@link CapturePort.requestUpload} (measured: uploadGuardOpeners). */
511
+ interface CaptureUploadOpts {
512
+ files: File[];
513
+ /** Logical cloud-files folder new uploads land in (auto-created). */
514
+ folderPath: string;
515
+ /** Visibility stamped on uploads (host vocabulary, e.g. "personal"). */
516
+ visibility?: string;
517
+ }
518
+ /** Honest outcome of a host upload — created-but-unlinked must be reportable. */
519
+ interface CaptureUploadResult {
520
+ cancelled?: boolean;
521
+ uploaded: string[];
522
+ aliased: {
523
+ existingFileId: string;
524
+ }[];
525
+ failed: {
526
+ name: string;
527
+ error: string;
528
+ }[];
529
+ }
530
+ /** Options for {@link CapturePort.openFilePicker} (measured: cloudFilesPickerOpeners). */
531
+ interface CapturePickOpts {
532
+ multi?: boolean;
533
+ title?: string;
534
+ description?: string;
535
+ }
536
+ /**
537
+ * The capture-toolbar seam. PER-HANDLER optional: the toolbar renders only
538
+ * the chips it can actually honour; a chip with no path behind it is never
539
+ * rendered dead. NEVER dead buttons.
540
+ *
541
+ * THE UPLOAD DEFAULT (0.6.0, C23): a host does NOT have to build an upload
542
+ * flow. Bind the one-file primitive `uploadFile` and the package ships the
543
+ * WHOLE flow over it — the file input, whole-body drag-and-drop, sequential
544
+ * uploads, the stall watchdog, per-file outcomes, and the loud
545
+ * created-but-unattached report. `requestUpload` stays for a host that owns
546
+ * a richer pipeline (duplicate-alias dialogs, progress UI); when both are
547
+ * bound `requestUpload` wins.
548
+ */
549
+ interface CapturePort {
550
+ /**
551
+ * The MINIMAL upload primitive: persist ONE file, answer with its id (or
552
+ * an honest error). Everything else — batching, drag-and-drop, progress
553
+ * state, failure copy — is the package's job.
554
+ */
555
+ uploadFile?(file: File, opts: {
556
+ folderPath: string;
557
+ visibility?: string;
558
+ }): Promise<{
559
+ ok: true;
560
+ id: string;
561
+ } | {
562
+ ok: false;
563
+ error: string;
564
+ }>;
565
+ /** The full host upload pipeline. Wins over `uploadFile` when bound. */
566
+ requestUpload?(opts: CaptureUploadOpts): Promise<CaptureUploadResult>;
567
+ /** Resolves with picked file ids, or null/empty on cancel. */
568
+ openFilePicker?(opts: CapturePickOpts): Promise<string[] | null>;
569
+ createDataTable?(opts: {
570
+ name: string;
571
+ }): Promise<{
572
+ id: string;
573
+ } | null>;
574
+ }
575
+ /**
576
+ * Props of the generic association picker face — ALSO the contract a
577
+ * per-token override component must implement (today: the hardcoded
578
+ * `token === "file"` → FilePickerWindow branch in AssociationPicker becomes a
579
+ * `registerPickerOverride("file", …)` host binding). Ported verbatim from the
580
+ * measured component.
581
+ */
582
+ interface AssociationPickerProps {
583
+ open: boolean;
584
+ onOpenChange: (open: boolean) => void;
585
+ token: EntityTypeToken;
586
+ /** Container display label, for the header ("…to Titanium Marketing"). */
587
+ containerLabel?: string;
588
+ /** Org stamped onto rows created by the "+ New" footer. */
589
+ orgId?: string | null;
590
+ /** Resource ids already attached to the container. */
591
+ attachedIds: Set<string>;
592
+ /** Attach a resource (returns ok/err so the row can surface failures). */
593
+ onAttach: (resourceId: string, title: string) => Promise<{
594
+ ok: boolean;
595
+ error?: string;
596
+ }>;
597
+ /** Detach a resource. */
598
+ onDetach: (resourceId: string) => Promise<{
599
+ ok: boolean;
600
+ error?: string;
601
+ }>;
602
+ }
603
+ /** Per-token picker override map — absent tokens use the generic picker sheet. */
604
+ type PickerOverrideMap = Partial<Record<EntityTypeToken, ComponentType<AssociationPickerProps>>>;
605
+ /**
606
+ * Props the entity-doors port's `EntityRef` receives (the measured subset the
607
+ * association faces pass today).
608
+ */
609
+ interface EntityRefProps {
610
+ token: string;
611
+ id: string;
612
+ name?: string | null;
613
+ showIcon?: boolean;
614
+ openInNewTab?: boolean;
615
+ alwaysShowActions?: boolean;
616
+ className?: string;
617
+ }
618
+ /** Props the entity-doors port's `DoorControls` receives. */
619
+ interface EntityDoorProps {
620
+ token: string;
621
+ id: string;
622
+ name?: string | null;
623
+ className?: string;
624
+ }
625
+ /** What the authorDisplay port receives — one comment's denormalized author. */
626
+ interface AuthorDisplayInput {
627
+ /** The auth user id (`created_by`), or null on an authorless legacy row. */
628
+ userId: string | null;
629
+ email: string | null;
630
+ displayName: string | null;
631
+ avatarUrl: string | null;
632
+ }
633
+ /**
634
+ * The author-display seam (W6 comments UI). The package cannot resolve user
635
+ * profiles itself — `cmt_list` denormalizes email/displayName/avatarUrl per
636
+ * row, and a host with a richer profile store (presence, current names,
637
+ * signed avatar URLs) overrides them here. Return `null` (or omit a field)
638
+ * to keep the denormalized value.
639
+ *
640
+ * DEGRADATION (absent port): the RPC's denormalized fields render as-is;
641
+ * a row with neither displayName nor email shows the package's
642
+ * "Unknown user" label with the default initial avatar. Never blank, never
643
+ * a crash.
644
+ */
645
+ type AuthorDisplayPort = (author: AuthorDisplayInput) => {
646
+ displayName?: string | null;
647
+ avatarUrl?: string | null;
648
+ } | null;
649
+ /**
650
+ * The entity-doors seam (today: `EntityRef` / `EntityDoorControls` /
651
+ * access-gate `UnresolvedEntityRef`). Absent → title text plus the overlay's
652
+ * `hrefFor` link when present; unresolved rows render the package's plain
653
+ * "unavailable" chip.
654
+ */
655
+ interface EntityDoorsPort {
656
+ EntityRef?: ComponentType<EntityRefProps>;
657
+ DoorControls?: ComponentType<EntityDoorProps>;
658
+ UnresolvedRef?: ComponentType<{
659
+ token: string;
660
+ id: string;
661
+ }>;
662
+ }
663
+ /**
664
+ * Everything a host binds, once. `createAssociationsStore(cfg)` (/core)
665
+ * throws when `dataSource` or `identity` is missing — those two ARE the
666
+ * host's app identity and cannot be defaulted. Every other port ships a
667
+ * working default (C23) or degrades per its own documented contract, never
668
+ * silently.
669
+ */
670
+ interface AssociationsConfig {
671
+ dataSource: AssociationsDataSource;
672
+ identity: AssociationsIdentity;
673
+ errorSink?: ErrorSink;
674
+ entityOverlay?: EntityOverlayMap;
675
+ notifier?: AssociationsNotifier;
676
+ windowShell?: WindowShellPort;
677
+ capture?: CapturePort;
678
+ pickerOverrides?: PickerOverrideMap;
679
+ entityDoors?: EntityDoorsPort;
680
+ authorDisplay?: AuthorDisplayPort;
681
+ }
682
+
683
+ declare const ASSOCIATION_TARGET_TYPES: readonly ["organization", "scope", "scope_type", "project", "task", "context_item", "thread", "war_room", "category", "conversation", "fc_set", "fc_card", "study_media", "assessment", "note", "file", "quiz_session", "agent", "research_tag", "skill", "surface", "plan_entity", "plan_node", "web_site", "seo_topic", "seo_keyword", "web_page", "web_screenshot", "party", "crm_outreach_list", "crm_deal", "rulebook"];
684
+ type AssociationTargetType = (typeof ASSOCIATION_TARGET_TYPES)[number];
685
+ interface AssociationEdge {
686
+ id: string;
687
+ direction: "outgoing" | "incoming";
688
+ otherType: string;
689
+ otherId: string;
690
+ role: string | null;
691
+ label: string | null;
692
+ position: number | null;
693
+ metadata: unknown;
694
+ orgId: string | null;
695
+ createdAt: string;
696
+ }
697
+ interface AssociationTargetEdge {
698
+ id: string;
699
+ targetId: string;
700
+ sourceType: string;
701
+ sourceId: string;
702
+ role: string | null;
703
+ label: string | null;
704
+ position: number | null;
705
+ metadata: unknown;
706
+ orgId: string | null;
707
+ createdAt: string;
708
+ }
709
+ interface AssociationSourceEdge {
710
+ id: string;
711
+ sourceId: string;
712
+ targetType: string;
713
+ targetId: string;
714
+ role: string | null;
715
+ label: string | null;
716
+ position: number | null;
717
+ metadata: unknown;
718
+ orgId: string | null;
719
+ createdAt: string;
720
+ }
721
+ interface AssociationsEntry {
722
+ status: "idle" | "loading" | "ready" | "error";
723
+ edges: AssociationEdge[];
724
+ fetchedAt: number | null;
725
+ error: string | null;
726
+ }
727
+ interface UserEntityState {
728
+ entityType: string;
729
+ entityId: string;
730
+ isFavorite: boolean;
731
+ isPinned: boolean;
732
+ isHidden: boolean;
733
+ lastViewedAt: string | null;
734
+ }
735
+ /** The three boolean dimensions of per-user state, as accepted by `ues_list`. */
736
+ type UserStateKind = "favorite" | "pinned" | "hidden";
737
+ /**
738
+ * The facet a category belongs to. Open vocabulary (new dimensions need no
739
+ * migration — `dimension` is free text in the DB); hosts enumerate their
740
+ * known dimensions as constants.
741
+ */
742
+ type CategoryDimension = string;
743
+ /** One `platform.categories` row, camelCased (mirrors `cat_list`'s return). */
744
+ interface PlatformCategory {
745
+ id: string;
746
+ /** Owning organization; system/global rows use the Matrx System org. */
747
+ orgId: string | null;
748
+ dimension: CategoryDimension;
749
+ name: string;
750
+ slug: string | null;
751
+ parentId: string | null;
752
+ isSystem: boolean;
753
+ color: string | null;
754
+ icon: string | null;
755
+ position: number | null;
756
+ /**
757
+ * The row's jsonb metadata — category rows CARRY semantics: e.g. a
758
+ * `deal_pipeline` stage stores `{outcome: "won"|"lost", probability: 0..100}`
759
+ * here. Null when empty or when hydrated from an older cache entry.
760
+ */
761
+ metadata: Record<string, unknown> | null;
762
+ }
763
+ /** Cache entry for one `dimension` — mirrors `AssociationsEntry`. */
764
+ interface CategoriesEntry {
765
+ status: "idle" | "loading" | "ready" | "error";
766
+ categories: PlatformCategory[];
767
+ fetchedAt: number | null;
768
+ error: string | null;
769
+ }
770
+
771
+ /** The author of a comment, denormalized by `cmt_list` from the auth user. */
772
+ interface CommentAuthor {
773
+ email: string | null;
774
+ displayName: string | null;
775
+ avatarUrl: string | null;
776
+ }
777
+ /**
778
+ * One `platform.comments` row, camelCased (mirrors `cmt_list`'s return).
779
+ * Threading is by `parentId`: a top-level comment has `parentId === null`;
780
+ * a reply points at its parent. `cmt_list` returns rows oldest→newest so
781
+ * callers can build the thread in one pass.
782
+ */
783
+ interface PlatformComment {
784
+ id: string;
785
+ orgId: string | null;
786
+ entityType: string;
787
+ entityId: string;
788
+ parentId: string | null;
789
+ body: string;
790
+ createdAt: string;
791
+ updatedAt: string;
792
+ createdBy: string | null;
793
+ author: CommentAuthor;
794
+ }
795
+ /**
796
+ * One cached comment thread (per `${entityType}:${entityId}` endpoint) — the
797
+ * same lifecycle shape as `AssociationsEntry`/`CategoriesEntry`: pending
798
+ * keeps previous comments AND the visible error; `fetchedAt` is the last
799
+ * successful load.
800
+ */
801
+ interface CommentsEntry {
802
+ status: "idle" | "loading" | "ready" | "error";
803
+ comments: readonly PlatformComment[];
804
+ fetchedAt: number | null;
805
+ error: string | null;
806
+ }
807
+
808
+ type ContentRole = "utility" | "source" | "destination" | "hybrid" | "container";
809
+ /**
810
+ * Fully-resolved entity descriptor — generated metadata + host overlay, with
811
+ * safe fallbacks so an un-overlaid token still renders (derived plural, no
812
+ * door, `Icon: null` → the consumer's default) even if it can't be queried
813
+ * for candidates yet.
814
+ */
815
+ interface EntityInfo {
816
+ token: EntityTypeToken;
817
+ label: string;
818
+ labelPlural: string;
819
+ /** Postgres schema of the backing table (from the generated registry). */
820
+ schema: string;
821
+ /** Backing table name (from the generated registry). */
822
+ table: string;
823
+ /** Title column for the picker, or null when none is registered. */
824
+ titleColumn: string | null;
825
+ /** Ownership column to scope candidate reads to the current user. */
826
+ ownerColumn: string;
827
+ /** Org-scoping column. */
828
+ orgColumn: string;
829
+ /** Host-supplied icon component, or null (consumer renders its default). */
830
+ Icon: EntityOverlayEntry["Icon"] | null;
831
+ hrefFor: ((id: string) => string) | null;
832
+ scopeable: boolean;
833
+ category: string | null;
834
+ /** Knowledge-model grouping bucket (resource surfaces group by this). */
835
+ contentRole: ContentRole;
836
+ /** Candidate-source override (rag-backed tokens etc.); null = generic read. */
837
+ listCandidates: EntityOverlayEntry["listCandidates"] | null;
838
+ /** True when a picker can list real candidates (title column OR override). */
839
+ canListCandidates: boolean;
840
+ }
841
+ interface EntityRegistry {
842
+ /** Merge more overlay entries in (host binding, W4 pickers, tests). */
843
+ registerEntityOverlay(overlay: EntityOverlayMap): void;
844
+ /** Resolve a KNOWN token to its full descriptor. */
845
+ getEntityInfo(token: EntityTypeToken): EntityInfo;
846
+ /** Safe variant for raw strings (e.g. an edge's `otherType`). */
847
+ tryGetEntityInfo(token: string): EntityInfo | null;
848
+ /** Resolve from a live `(schema, table)` pair, or null. */
849
+ tryGetEntityInfoByTable(schema: string, table: string): EntityInfo | null;
850
+ /** Resolve a raw table name only when it maps to exactly one entity. */
851
+ tryGetEntityInfoByUniqueTableName(table: string): EntityInfo | null;
852
+ /**
853
+ * Tokens the DB classifies as knowledge resources via a valid
854
+ * `content_role` AND that can list candidates. The default set for card
855
+ * grids, resource sections, and attach pickers.
856
+ */
857
+ curatedTokens(): EntityTypeToken[];
858
+ /**
859
+ * Tokens offered as reference "Allowed types" — DB-driven via
860
+ * `platform.entity_types.reference_pickable`. A pickable token with no
861
+ * title column and no candidate override is a config defect: excluded and
862
+ * screamed to the errorSink, never silently shown broken.
863
+ */
864
+ listableTokens(): EntityTypeToken[];
865
+ }
866
+
867
+ interface ConversationFileLink {
868
+ fileId: string;
869
+ label: string | null;
870
+ metadata: unknown;
871
+ createdAt: string;
872
+ }
873
+ interface AddAssociationArgs {
874
+ sourceType: string;
875
+ sourceId: string;
876
+ targetType: AssociationTargetType;
877
+ targetId: string;
878
+ orgId?: string;
879
+ label?: string;
880
+ metadata?: unknown;
881
+ /**
882
+ * Exact file → conversation updates preserve existing metadata unless the
883
+ * caller explicitly opts into replacement. Invalid for every other pair.
884
+ */
885
+ replaceMetadata?: boolean;
886
+ role?: string;
887
+ position?: number;
888
+ /**
889
+ * Typed edge payload (Edge Payload System). `payloadKind` must be a
890
+ * registered `platform.edge_payload_kind`; the DB trigger validates
891
+ * `payload` against its JSON Schema and hard-fails on any mismatch. Real
892
+ * logic an edge carries goes HERE — `metadata` is for loose annotations.
893
+ */
894
+ payloadKind?: string;
895
+ payload?: unknown;
896
+ }
897
+ interface AssociationsServiceApi {
898
+ listForEntity(rawType: string, id: string): Promise<AssociationsRpcResult<{
899
+ edges: AssociationEdge[];
900
+ }>>;
901
+ listConversationFiles(conversationId: string): Promise<AssociationsRpcResult<{
902
+ files: ConversationFileLink[];
903
+ }>>;
904
+ listForTargets(rawTargetType: string, targetIds: string[]): Promise<AssociationsRpcResult<{
905
+ edges: AssociationTargetEdge[];
906
+ }>>;
907
+ listForTargetsVisible(rawTargetType: string, targetIds: string[]): Promise<AssociationsRpcResult<{
908
+ edges: AssociationTargetEdge[];
909
+ }>>;
910
+ listForSources(rawSourceType: string, sourceIds: string[], rawTargetType?: string): Promise<AssociationsRpcResult<{
911
+ edges: AssociationSourceEdge[];
912
+ }>>;
913
+ add(args: AddAssociationArgs): Promise<AssociationsRpcResult<{
914
+ id: string;
915
+ }>>;
916
+ remove(args: {
917
+ sourceType: string;
918
+ sourceId: string;
919
+ targetType: string;
920
+ targetId: string;
921
+ role?: string;
922
+ }): Promise<AssociationsRpcResult<null>>;
923
+ setTargets(args: {
924
+ sourceType: string;
925
+ sourceId: string;
926
+ targetType: AssociationTargetType;
927
+ targetIds: string[];
928
+ orgId?: string;
929
+ role?: string;
930
+ }): Promise<AssociationsRpcResult<null>>;
931
+ addAgentResource(args: {
932
+ agentId: string;
933
+ sourceType: string;
934
+ sourceId: string;
935
+ label?: string;
936
+ metadata?: unknown;
937
+ }): Promise<AssociationsRpcResult<{
938
+ id: string;
939
+ }>>;
940
+ removeAgentResource(args: {
941
+ agentId: string;
942
+ sourceType: string;
943
+ sourceId: string;
944
+ }): Promise<AssociationsRpcResult<null>>;
945
+ removeForEntity(rawType: string, id: string): Promise<AssociationsRpcResult<null>>;
946
+ }
947
+
948
+ interface CategoriesServiceApi {
949
+ list(dimension?: CategoryDimension): Promise<AssociationsRpcResult<{
950
+ categories: PlatformCategory[];
951
+ }>>;
952
+ create(args: {
953
+ dimension: CategoryDimension;
954
+ name: string;
955
+ orgId: string;
956
+ parentId?: string | null;
957
+ color?: string | null;
958
+ icon?: string | null;
959
+ slug?: string | null;
960
+ }): Promise<AssociationsRpcResult<{
961
+ id: string;
962
+ }>>;
963
+ update(args: {
964
+ id: string;
965
+ name: string;
966
+ slug: string | null;
967
+ color: string | null;
968
+ icon: string | null;
969
+ position: number | null;
970
+ }): Promise<AssociationsRpcResult<{
971
+ id: string;
972
+ }>>;
973
+ reparent(args: {
974
+ id: string;
975
+ parentId: string | null;
976
+ }): Promise<AssociationsRpcResult<{
977
+ id: string;
978
+ }>>;
979
+ delete(id: string): Promise<AssociationsRpcResult<{
980
+ id: string;
981
+ }>>;
982
+ }
983
+
984
+ interface FavoritesServiceApi {
985
+ setState(args: {
986
+ entityType: string;
987
+ entityId: string;
988
+ isFavorite?: boolean;
989
+ isPinned?: boolean;
990
+ isHidden?: boolean;
991
+ }): Promise<AssociationsRpcResult<null>>;
992
+ setFavorite(entityType: string, entityId: string, isFavorite: boolean): Promise<AssociationsRpcResult<null>>;
993
+ setPinned(entityType: string, entityId: string, isPinned: boolean): Promise<AssociationsRpcResult<null>>;
994
+ setHidden(entityType: string, entityId: string, isHidden: boolean): Promise<AssociationsRpcResult<null>>;
995
+ list(kind?: UserStateKind): Promise<AssociationsRpcResult<{
996
+ items: UserEntityState[];
997
+ }>>;
998
+ getBulk(entityType: string, entityIds: string[]): Promise<AssociationsRpcResult<{
999
+ items: UserEntityState[];
1000
+ }>>;
1001
+ touch(entityType: string, entityId: string): Promise<AssociationsRpcResult<null>>;
1002
+ }
1003
+
1004
+ interface CandidateRecord {
1005
+ id: string;
1006
+ title: string;
1007
+ }
1008
+ interface ListCandidatesArgs {
1009
+ token: EntityTypeToken;
1010
+ /** Scope to this owner's rows when the entity declares an owner column. */
1011
+ ownerId?: string | null;
1012
+ /** Case-insensitive title filter. */
1013
+ search?: string;
1014
+ limit?: number;
1015
+ }
1016
+ type CandidatesResult = {
1017
+ ok: true;
1018
+ data: CandidateRecord[];
1019
+ } | {
1020
+ ok: false;
1021
+ error: string;
1022
+ };
1023
+ interface UniversalCandidate extends CandidateRecord {
1024
+ token: EntityTypeToken;
1025
+ }
1026
+ interface SearchAcrossTokensArgs {
1027
+ /** Tokens to search. Defaults to every curated token in the registry. */
1028
+ tokens?: EntityTypeToken[];
1029
+ search: string;
1030
+ ownerId?: string | null;
1031
+ /** Cap per token — a universal search shows a few of everything. */
1032
+ perTokenLimit?: number;
1033
+ /** Max in-flight token queries. */
1034
+ concurrency?: number;
1035
+ }
1036
+ interface ReferenceSearchCandidatesFn {
1037
+ (args: {
1038
+ p_token: string;
1039
+ p_search?: string;
1040
+ p_limit?: number;
1041
+ p_ids?: string[];
1042
+ }): Promise<{
1043
+ data: Array<{
1044
+ id: string;
1045
+ title: string | null;
1046
+ }>;
1047
+ error: null;
1048
+ } | {
1049
+ data: null;
1050
+ error: {
1051
+ message: string;
1052
+ };
1053
+ }>;
1054
+ }
1055
+ interface CandidatesServiceApi {
1056
+ /**
1057
+ * The universal candidate reader RPC (`public.reference_search_candidates`)
1058
+ * — shared by candidate search here and title resolution in titles.ts.
1059
+ */
1060
+ callReferenceSearchCandidates: ReferenceSearchCandidatesFn;
1061
+ listAssociationCandidates(args: ListCandidatesArgs): Promise<CandidatesResult>;
1062
+ /**
1063
+ * ONE search over EVERY listable entity type — the "attach anything from
1064
+ * anywhere" primitive. Registry-driven client fan-out, capped and
1065
+ * concurrency-limited. Per-token failures are screamed and skipped — one
1066
+ * broken table never blanks the search.
1067
+ */
1068
+ searchCandidatesAcrossTokens(args: SearchAcrossTokensArgs): Promise<UniversalCandidate[]>;
1069
+ }
1070
+
1071
+ interface TitlesServiceApi {
1072
+ /** Read the cache synchronously (for render paths after a fetch settled). */
1073
+ get(token: string, id: string): string | null;
1074
+ /**
1075
+ * Push a known-fresh title into the cache (after a rename or a create), so
1076
+ * surfaces that resolve through this service never show a stale name.
1077
+ */
1078
+ prime(token: string, id: string, title: string): void;
1079
+ /** Display fallback when no label and no fetched title exist. */
1080
+ fallback(token: string): string;
1081
+ /**
1082
+ * Resolve titles for `ids` of one token. Returns ONLY the resolved entries
1083
+ * (cache + fresh reads); missing rows (deleted, no access) stay absent.
1084
+ */
1085
+ fetch(token: string, ids: string[]): Promise<Map<string, string>>;
1086
+ }
1087
+
1088
+ type EntityRowResult = {
1089
+ ok: true;
1090
+ data: {
1091
+ id: string;
1092
+ title: string;
1093
+ };
1094
+ } | {
1095
+ ok: false;
1096
+ error: string;
1097
+ };
1098
+ interface CreateEntityRowArgs {
1099
+ /** The new row's human name — written to the registry `titleColumn`. */
1100
+ title: string;
1101
+ /** Org to stamp (skipped when the token has no org column). */
1102
+ orgId?: string | null;
1103
+ /** Required NOT NULL columns the registry conventions can't know about. */
1104
+ extraColumns?: Record<string, unknown>;
1105
+ }
1106
+ interface EntityRowsServiceApi {
1107
+ createEntityRow(token: EntityTypeToken, args: CreateEntityRowArgs): Promise<EntityRowResult>;
1108
+ renameEntityRow(token: EntityTypeToken, id: string, title: string): Promise<{
1109
+ ok: true;
1110
+ } | {
1111
+ ok: false;
1112
+ error: string;
1113
+ }>;
1114
+ }
1115
+
1116
+ /** A typed reference to a single row — `{ type, id }`. */
1117
+ interface EntityRef {
1118
+ type: EntityTypeToken;
1119
+ id: string;
1120
+ }
1121
+ /** A container reference — the deliberate set an edge may point at. */
1122
+ interface ContainerRef {
1123
+ type: AssociationTargetType;
1124
+ id: string;
1125
+ }
1126
+ /** Per-edge attributes shared by the link helpers. */
1127
+ interface EdgeAttrs {
1128
+ orgId?: string;
1129
+ label?: string;
1130
+ metadata?: unknown;
1131
+ role?: string;
1132
+ position?: number;
1133
+ }
1134
+ /** One fully-specified edge for {@link AssociationHelpersApi.linkEdges}. */
1135
+ interface EdgeSpec extends EdgeAttrs {
1136
+ source: EntityRef;
1137
+ target: ContainerRef;
1138
+ }
1139
+ interface AssociationHelpersApi {
1140
+ /**
1141
+ * Add an arbitrary batch of edges in one call (idempotent per edge).
1142
+ * Best-effort: every edge is attempted; the result is `ok` with the
1143
+ * created ids only when ALL succeed, otherwise `err` whose `detail` lists
1144
+ * every failure (the edges that DID succeed remain applied — re-running is
1145
+ * safe via ON CONFLICT).
1146
+ */
1147
+ linkEdges(edges: EdgeSpec[]): Promise<AssociationsRpcResult<{
1148
+ ids: string[];
1149
+ }>>;
1150
+ /** Attach ONE source to MANY containers in a single shot. */
1151
+ linkOneToMany(args: {
1152
+ source: EntityRef;
1153
+ targets: ContainerRef[];
1154
+ attrs?: EdgeAttrs;
1155
+ }): Promise<AssociationsRpcResult<{
1156
+ ids: string[];
1157
+ }>>;
1158
+ /** Attach MANY sources to ONE container in a single shot. */
1159
+ linkManyToOne(args: {
1160
+ sources: EntityRef[];
1161
+ target: ContainerRef;
1162
+ attrs?: EdgeAttrs;
1163
+ }): Promise<AssociationsRpcResult<{
1164
+ ids: string[];
1165
+ }>>;
1166
+ /**
1167
+ * REPLACE the full set of a source's edges of one container type (adds
1168
+ * missing, removes extras) in one DB transaction — the set-semantics
1169
+ * one-shot. Thin, named pass-through to `assoc_set_targets`.
1170
+ */
1171
+ replaceTargets(args: {
1172
+ source: EntityRef;
1173
+ targetType: AssociationTargetType;
1174
+ targetIds: string[];
1175
+ orgId?: string;
1176
+ role?: string;
1177
+ }): Promise<AssociationsRpcResult<null>>;
1178
+ /**
1179
+ * Wire edges onto a JUST-CREATED entity. The caller inserts its own row
1180
+ * (entity tables are feature-owned), then passes the new id here to attach
1181
+ * it to any number of containers (orphan-on-partial-fail is harmless and
1182
+ * re-runnable). `created` is the new entity; it becomes the edges' SOURCE.
1183
+ */
1184
+ linkCreated(args: {
1185
+ created: EntityRef;
1186
+ targets: ContainerRef[];
1187
+ attrs?: EdgeAttrs;
1188
+ }): Promise<AssociationsRpcResult<{
1189
+ ids: string[];
1190
+ }>>;
1191
+ /** Remove an arbitrary batch of edges (best-effort; no-op per missing edge). */
1192
+ unlinkEdges(edges: {
1193
+ source: EntityRef;
1194
+ target: ContainerRef;
1195
+ role?: string;
1196
+ }[]): Promise<AssociationsRpcResult<null>>;
1197
+ }
1198
+
1199
+ interface AddCommentArgs {
1200
+ /** Registered entity-type token the comment hangs on (writes-strict, C18). */
1201
+ entityType: string;
1202
+ entityId: string;
1203
+ body: string;
1204
+ /** Reply target — an existing comment's id. Top-level when omitted. */
1205
+ parentId?: string | null;
1206
+ /** Org override; the RPC resolves task-org/personal-org when omitted. */
1207
+ orgId?: string | null;
1208
+ }
1209
+ interface CommentsServiceApi {
1210
+ listForEntity(entityType: string, entityId: string): Promise<AssociationsRpcResult<{
1211
+ comments: PlatformComment[];
1212
+ }>>;
1213
+ add(args: AddCommentArgs): Promise<AssociationsRpcResult<{
1214
+ id: string;
1215
+ }>>;
1216
+ edit(id: string, body: string): Promise<AssociationsRpcResult<null>>;
1217
+ remove(id: string): Promise<AssociationsRpcResult<null>>;
1218
+ }
1219
+
1220
+ interface AssociationWriteResult {
1221
+ ok: boolean;
1222
+ /** Set on a successful single-edge `add`. */
1223
+ id?: string;
1224
+ error?: string;
1225
+ }
1226
+ interface CategoryMutationResult {
1227
+ ok: boolean;
1228
+ /** Set on a successful mutation. */
1229
+ id?: string;
1230
+ error?: string;
1231
+ }
1232
+ interface CommentMutationResult {
1233
+ ok: boolean;
1234
+ /** Set on a successful `addComment`. */
1235
+ id?: string;
1236
+ error?: string;
1237
+ }
1238
+ interface AssociationsStore {
1239
+ /** Stable, sync read of one endpoint's entry (idle default when uncached). */
1240
+ getEdges(type: string, id: string): AssociationsEntry;
1241
+ /**
1242
+ * Lazy load of every edge touching `${type}:${id}` (both directions).
1243
+ * Deduped per key; `status === "ready"` short-circuits unless `force`.
1244
+ */
1245
+ load(type: string, id: string, opts?: {
1246
+ force?: boolean;
1247
+ }): Promise<void>;
1248
+ /** External-store contract: notified whenever the key's entry changes. */
1249
+ subscribe(key: string, cb: () => void): () => void;
1250
+ /** Attach source → target; on success reloads BOTH endpoints. */
1251
+ add(args: {
1252
+ sourceType: string;
1253
+ sourceId: string;
1254
+ targetType: AssociationTargetType;
1255
+ targetId: string;
1256
+ orgId?: string;
1257
+ label?: string;
1258
+ role?: string;
1259
+ metadata?: unknown;
1260
+ replaceMetadata?: boolean;
1261
+ }): Promise<AssociationWriteResult>;
1262
+ /** Detach source → target; on success reloads BOTH endpoints. */
1263
+ remove(args: {
1264
+ sourceType: string;
1265
+ sourceId: string;
1266
+ targetType: string;
1267
+ targetId: string;
1268
+ role?: string;
1269
+ }): Promise<AssociationWriteResult>;
1270
+ /** Replace the source's `targetType` edge set; reloads the SOURCE. */
1271
+ setTargets(args: {
1272
+ sourceType: string;
1273
+ sourceId: string;
1274
+ targetType: AssociationTargetType;
1275
+ targetIds: string[];
1276
+ orgId?: string;
1277
+ role?: string;
1278
+ }): Promise<AssociationWriteResult>;
1279
+ /** Reset one endpoint to idle and notify its subscribers. */
1280
+ invalidate(type: string, id: string): void;
1281
+ /** Reset every association endpoint, category facet, and comment thread. */
1282
+ invalidateAll(): void;
1283
+ getCategories(dimension: CategoryDimension): CategoriesEntry;
1284
+ loadCategories(dimension: CategoryDimension, opts?: {
1285
+ force?: boolean;
1286
+ }): Promise<void>;
1287
+ subscribeCategories(dimension: CategoryDimension, cb: () => void): () => void;
1288
+ /** Create + echo-insert + authoritative force reload. Returns the new id. */
1289
+ createCategory(args: {
1290
+ dimension: CategoryDimension;
1291
+ name: string;
1292
+ orgId: string;
1293
+ parentId?: string | null;
1294
+ color?: string | null;
1295
+ icon?: string | null;
1296
+ slug?: string | null;
1297
+ }): Promise<CategoryMutationResult>;
1298
+ updateCategory(args: {
1299
+ dimension: CategoryDimension;
1300
+ id: string;
1301
+ name: string;
1302
+ slug: string | null;
1303
+ color: string | null;
1304
+ icon: string | null;
1305
+ position: number | null;
1306
+ }): Promise<CategoryMutationResult>;
1307
+ reparentCategory(args: {
1308
+ dimension: CategoryDimension;
1309
+ id: string;
1310
+ parentId: string | null;
1311
+ }): Promise<CategoryMutationResult>;
1312
+ deleteCategory(args: {
1313
+ dimension: CategoryDimension;
1314
+ id: string;
1315
+ }): Promise<CategoryMutationResult>;
1316
+ /** Stable, sync read of one entity's comment thread (idle when uncached). */
1317
+ getComments(type: string, id: string): CommentsEntry;
1318
+ /**
1319
+ * Lazy load of every comment on `${type}:${id}` (oldest→newest; thread by
1320
+ * `parentId`). Deduped per key; `status === "ready"` short-circuits unless
1321
+ * `force`.
1322
+ */
1323
+ loadComments(type: string, id: string, opts?: {
1324
+ force?: boolean;
1325
+ }): Promise<void>;
1326
+ /** External-store contract for one entity's comment thread. */
1327
+ subscribeComments(key: string, cb: () => void): () => void;
1328
+ /** Post a comment (or a reply); on success force-reloads the thread. */
1329
+ addComment(args: {
1330
+ entityType: string;
1331
+ entityId: string;
1332
+ body: string;
1333
+ parentId?: string | null;
1334
+ orgId?: string | null;
1335
+ }): Promise<CommentMutationResult>;
1336
+ /** Edit a comment body (author-only in the RPC); reloads the thread. */
1337
+ editComment(args: {
1338
+ entityType: string;
1339
+ entityId: string;
1340
+ id: string;
1341
+ body: string;
1342
+ }): Promise<CommentMutationResult>;
1343
+ /** Soft-delete a comment (author/org member in the RPC); reloads the thread. */
1344
+ deleteComment(args: {
1345
+ entityType: string;
1346
+ entityId: string;
1347
+ id: string;
1348
+ }): Promise<CommentMutationResult>;
1349
+ /** Reset one entity's comment thread to idle and notify its subscribers. */
1350
+ invalidateComments(type: string, id: string): void;
1351
+ /** Batched title resolution + the session cache + prime. */
1352
+ titles: TitlesServiceApi;
1353
+ /** Per-user favorite/pinned/hidden state (`ues_*`). */
1354
+ favorites: FavoritesServiceApi;
1355
+ /** Candidate reads for the pickers. */
1356
+ candidates: CandidatesServiceApi;
1357
+ /** Generic registry-convention row create/rename. */
1358
+ entityRows: EntityRowsServiceApi;
1359
+ /** Composite link helpers over the chokepoint. */
1360
+ helpers: AssociationHelpersApi;
1361
+ /** The registry merge engine (generated metadata + host overlay). */
1362
+ registry: EntityRegistry;
1363
+ /**
1364
+ * The raw chokepoint services — every RPC family, results-enveloped.
1365
+ * `associations` writes here do NOT touch the cache; use the store-level
1366
+ * `add`/`remove`/`setTargets` when a cached surface must stay fresh.
1367
+ */
1368
+ services: {
1369
+ associations: AssociationsServiceApi;
1370
+ categories: CategoriesServiceApi;
1371
+ comments: CommentsServiceApi;
1372
+ };
1373
+ /** Merge more host overlay entries in (icons/routes/candidate loaders). */
1374
+ registerEntityOverlay: EntityRegistry["registerEntityOverlay"];
1375
+ /**
1376
+ * The bound scream seam (W3, additive): /react surfaces route their loud
1377
+ * recoveries here (the originals' console.error sites) without a second
1378
+ * sink binding. Same function the host passed at construction.
1379
+ */
1380
+ errorSink: ErrorSink;
1381
+ /**
1382
+ * The bound data seam (0.6.0, additive): the provider's demanded-schema
1383
+ * boot probe reads it so hosts stop re-exporting their dataSource just to
1384
+ * run a check the package owns.
1385
+ */
1386
+ dataSource: AssociationsDataSource;
1387
+ /**
1388
+ * The bound identity port (W3, additive): /react hooks that FILTER by the
1389
+ * current user (candidate owner scoping) read it leniently; write paths
1390
+ * keep going through the services, where `requireUserId` failures stay
1391
+ * loud. Same object the host passed at construction.
1392
+ */
1393
+ identity: AssociationsConfig["identity"];
1394
+ }
1395
+
1396
+ interface UseAssociationsArgs {
1397
+ /** The entity whose relationships to read/manage (the cache endpoint). */
1398
+ type: string;
1399
+ id: string | null;
1400
+ /** Disable the auto-load on mount. Defaults to false (auto-load). */
1401
+ autoLoad?: boolean;
1402
+ }
1403
+
1404
+ interface UseAssociationsReturn {
1405
+ /** Every edge touching this entity, both directions. */
1406
+ edges: AssociationEdge[];
1407
+ status: AssociationsEntry["status"];
1408
+ error: string | null;
1409
+ fetchedAt: number | null;
1410
+ /** Attach this entity (as source) → a target. */
1411
+ add: (args: {
1412
+ targetType: AssociationTargetType;
1413
+ targetId: string;
1414
+ orgId?: string;
1415
+ label?: string;
1416
+ /** Typed edge role (e.g. 'theme' for a folder/tag) — omit for a role-less edge. */
1417
+ role?: string;
1418
+ }) => Promise<AssociationWriteResult>;
1419
+ /** Detach this entity (as source) → a target. */
1420
+ remove: (args: {
1421
+ targetType: string;
1422
+ targetId: string;
1423
+ role?: string;
1424
+ }) => Promise<AssociationWriteResult>;
1425
+ /** Replace this entity's edges of one target type with exactly `targetIds`. */
1426
+ setTargets: (args: {
1427
+ targetType: AssociationTargetType;
1428
+ targetIds: string[];
1429
+ orgId?: string;
1430
+ role?: string;
1431
+ }) => Promise<AssociationWriteResult>;
1432
+ /** Force a refetch of this entity's edges. */
1433
+ reload: () => Promise<void>;
1434
+ }
1435
+ declare function useAssociations(args: UseAssociationsArgs): UseAssociationsReturn;
1436
+ /**
1437
+ * Convenience alias — same hook, a name that reads naturally on relationship
1438
+ * surfaces ("the things this entity is related to"). Identical contract.
1439
+ */
1440
+ declare const useEntityRelationships: typeof useAssociations;
1441
+
1442
+ interface ContainerLink {
1443
+ /** The edge id (for keys / removal). */
1444
+ edgeId: string;
1445
+ /** The attached resource's id (the edge source). */
1446
+ resourceId: string;
1447
+ /** The attached resource's entity token (the edge source type). */
1448
+ token: string;
1449
+ /** The edge role, or null for a plain (role-less) association. */
1450
+ role: string | null;
1451
+ label: string | null;
1452
+ /** Per-edge props from `platform.associations.metadata` (e.g. representation). */
1453
+ metadata: unknown;
1454
+ }
1455
+ interface UseContainerLinksArgs {
1456
+ /** The primary entity — always an association TARGET (container). */
1457
+ containerType: AssociationTargetType;
1458
+ containerId: string | null;
1459
+ /** Org to stamp on new edges (for org-scoped RLS / counts). */
1460
+ orgId?: string | null;
1461
+ }
1462
+ interface UseContainerLinksReturn {
1463
+ status: ReturnType<typeof useAssociations>["status"];
1464
+ error: string | null;
1465
+ reload: () => Promise<void>;
1466
+ /** Total attached resources across every token (all incoming edges). */
1467
+ totalCount: number;
1468
+ /** Live count of attached resources of `token`. */
1469
+ countFor: (token: EntityTypeToken) => number;
1470
+ /** Ids of resources of `token` already attached (for picker "attached" state). */
1471
+ attachedIdsFor: (token: EntityTypeToken) => Set<string>;
1472
+ /** Full link rows of `token` (for listing/removal). */
1473
+ linksFor: (token: EntityTypeToken) => ContainerLink[];
1474
+ /** Attach a resource (source) to this container (target). */
1475
+ attach: (token: EntityTypeToken, resourceId: string, label?: string, metadata?: unknown, options?: {
1476
+ replaceMetadata?: boolean;
1477
+ /**
1478
+ * Semantic edge role (`platform.associations.role`) — e.g. the
1479
+ * Masterwork dump surface stamps `distillation_source`. Omitted = the
1480
+ * canonical role-less edge. Detach with the SAME role to remove it.
1481
+ */
1482
+ role?: string;
1483
+ }) => Promise<AssociationWriteResult>;
1484
+ /** Detach a resource from this container. */
1485
+ detach: (token: EntityTypeToken, resourceId: string, role?: string) => Promise<AssociationWriteResult>;
1486
+ }
1487
+ declare function useContainerLinks(args: UseContainerLinksArgs): UseContainerLinksReturn;
1488
+
1489
+ interface AssociationEntitySelectItem {
1490
+ id: string;
1491
+ title: string;
1492
+ }
1493
+ /**
1494
+ * The read/write seam of the association "name dropdown". This hook is the
1495
+ * default (plain associations container); surfaces with bespoke active/create
1496
+ * semantics implement it themselves — same pattern as AssociationList's
1497
+ * ContainerResourcesAdapter.
1498
+ */
1499
+ interface AssociationEntitySelectAdapter {
1500
+ /** True while the association list is still hydrating. */
1501
+ loading: boolean;
1502
+ /** Every entity of this token associated with the container. */
1503
+ items: AssociationEntitySelectItem[];
1504
+ activeId: string | null;
1505
+ setActive: (id: string) => void | Promise<unknown>;
1506
+ /**
1507
+ * Create a new entity named `title`, associate it to the container, and
1508
+ * make it active. Resolves to the new id, or null on failure (the adapter
1509
+ * reports its own error detail; the component toasts generically).
1510
+ * Omit when creation isn't name-driven — pass `createSlot` on the component
1511
+ * instead (e.g. a conversation is created by PICKING AN AGENT, not naming).
1512
+ */
1513
+ createAndAttach?: (title: string) => Promise<string | null>;
1514
+ /** Rename the entity (its real title column). Resolves false on failure. */
1515
+ rename: (id: string, title: string) => Promise<boolean>;
1516
+ /** Optional: unlink an entity from the container (never deletes the row). */
1517
+ detach?: (id: string) => Promise<unknown>;
1518
+ }
1519
+ interface UseAssociationEntitySelectAdapterArgs {
1520
+ token: EntityTypeToken;
1521
+ /** The container the entities are associated with (always the edge TARGET). */
1522
+ container: {
1523
+ type: AssociationTargetType;
1524
+ id: string | null;
1525
+ orgId?: string | null;
1526
+ };
1527
+ /** Controlled active selection; omit to default to the first attached row. */
1528
+ activeId?: string | null;
1529
+ onActiveChange?: (id: string) => void | Promise<unknown>;
1530
+ /** NOT NULL columns the registry conventions can't know (create only). */
1531
+ createColumns?: Record<string, unknown>;
1532
+ }
1533
+ declare function useAssociationEntitySelectAdapter(args: UseAssociationEntitySelectAdapterArgs): AssociationEntitySelectAdapter;
1534
+
1535
+ /** The primary (container) entity a surface is anchored to. */
1536
+ interface PrimaryEntity {
1537
+ /** Container token — must be an association TARGET type. */
1538
+ type: AssociationTargetType;
1539
+ id: string;
1540
+ /** Org to stamp on edges created here (org-scoped RLS / counts). */
1541
+ orgId?: string | null;
1542
+ /** Human label for headings (e.g. the org/scope name). */
1543
+ label?: string;
1544
+ }
1545
+ declare function PrimaryEntityProvider({ value, children, }: {
1546
+ value: PrimaryEntity;
1547
+ children: ReactNode;
1548
+ }): react.JSX.Element;
1549
+ /** Read the surrounding primary entity, or null when unprovided. */
1550
+ declare function usePrimaryEntity(): PrimaryEntity | null;
1551
+
1552
+ interface AssociationWindowProps {
1553
+ /** Controls mount — callers should also gate their JSX on this. */
1554
+ open: boolean;
1555
+ onClose: () => void;
1556
+ /** Human-readable scope for the window id (debugging / tray labels). */
1557
+ scopeId: string;
1558
+ title: string;
1559
+ /** Small leading icon rendered beside the title. */
1560
+ icon?: ReactNode;
1561
+ /**
1562
+ * One-line context under the header ("Attached to Titanium Marketing").
1563
+ * A node, not a string, so the container it names can carry its own door
1564
+ * (THE DOOR LAW) instead of being an unreachable label.
1565
+ */
1566
+ subtitle?: ReactNode;
1567
+ children: ReactNode;
1568
+ }
1569
+ declare function AssociationWindow({ open, onClose, scopeId, title, icon, subtitle, children, }: AssociationWindowProps): react.JSX.Element | null;
1570
+
1571
+ interface UniversalAssociationPickerProps {
1572
+ /** Tokens offered. Defaults to every listable token. */
1573
+ tokens?: EntityTypeToken[];
1574
+ /** Ids already attached, keyed `${token}:${id}` — rendered as attached. */
1575
+ attachedKeys: Set<string>;
1576
+ onAttach: (token: EntityTypeToken, resourceId: string, title: string) => Promise<{
1577
+ ok: boolean;
1578
+ error?: string;
1579
+ }>;
1580
+ onDetach: (token: EntityTypeToken, resourceId: string) => Promise<{
1581
+ ok: boolean;
1582
+ error?: string;
1583
+ }>;
1584
+ /** Owner filter for candidate reads (defaults to RLS-only). */
1585
+ ownerId?: string | null;
1586
+ /** Org stamped onto rows created via the per-token "+ New" footer. */
1587
+ orgId?: string | null;
1588
+ className?: string;
1589
+ }
1590
+ declare function attachedKey(token: string, id: string): string;
1591
+ declare function UniversalAssociationPicker(props: UniversalAssociationPickerProps): react.JSX.Element;
1592
+
1593
+ interface AttachedItemsSheetProps {
1594
+ open: boolean;
1595
+ onOpenChange: (open: boolean) => void;
1596
+ token: EntityTypeToken;
1597
+ containerLabel?: string;
1598
+ /**
1599
+ * The container these items are attached to. When given, the "Attached to X"
1600
+ * line puts a door on X — this window can outlive the page it was opened
1601
+ * from, so its container reference must be reachable.
1602
+ */
1603
+ container?: PrimaryEntity;
1604
+ links: ContainerLink[];
1605
+ /** Opens the attach picker. Omitted when the token cannot list candidates. */
1606
+ onAdd?: () => void;
1607
+ onDetach: (resourceId: string) => Promise<{
1608
+ ok: boolean;
1609
+ error?: string;
1610
+ }>;
1611
+ }
1612
+ declare function AttachedItemsSheet(props: AttachedItemsSheetProps): react.JSX.Element | null;
1613
+
1614
+ interface AssociationCardProps {
1615
+ /** The secondary entity kind this card manages (e.g. "task", "file"). */
1616
+ token: EntityTypeToken;
1617
+ /** Override the page's primary entity. Defaults to PrimaryEntityProvider. */
1618
+ container?: PrimaryEntity;
1619
+ className?: string;
1620
+ }
1621
+ declare function AssociationCard({ token, container: containerProp, className, }: AssociationCardProps): react.JSX.Element | null;
1622
+
1623
+ interface AssociationCardGridProps {
1624
+ /** Tokens to show. Defaults to every registry-listable token. */
1625
+ tokens?: EntityTypeToken[];
1626
+ /** Registry tokens this surface cannot honestly support yet. */
1627
+ excludeTokens?: EntityTypeToken[];
1628
+ className?: string;
1629
+ }
1630
+ declare function AssociationCardGrid({ tokens, excludeTokens, className, }: AssociationCardGridProps): react.JSX.Element;
1631
+
1632
+ /** One attached resource, as the list renders it. Tokens are CANONICAL. */
1633
+ interface ContainerResourceRow {
1634
+ /** Stable row key (edge id or `${token}:${id}`). */
1635
+ key: string;
1636
+ token: string;
1637
+ resourceId: string;
1638
+ label: string | null;
1639
+ /** Exact semantic edge role; null means the canonical role-less edge. */
1640
+ role?: string | null;
1641
+ /** Pinned rows sort first inside their token group. */
1642
+ pinned?: boolean;
1643
+ /** False for inherited rows (e.g. via a thread's anchor) — no detach. */
1644
+ removable: boolean;
1645
+ /** Small annotation for non-removable rows ("via anchor"). */
1646
+ originNote?: string | null;
1647
+ /** Resolvable records that contributed an inherited row. */
1648
+ originRefs?: readonly {
1649
+ token: EntityTypeToken;
1650
+ id: string;
1651
+ label: string;
1652
+ }[];
1653
+ }
1654
+ interface ContainerResourcesAdapter {
1655
+ status: "idle" | "loading" | "ready" | "error";
1656
+ error: string | null;
1657
+ reload: () => void | Promise<void>;
1658
+ rows: ContainerResourceRow[];
1659
+ attach: (token: EntityTypeToken, resourceId: string, title?: string,
1660
+ /**
1661
+ * Extra edge metadata stamped at attach time (label-at-attach-time's
1662
+ * sibling contract). Adapters without metadata support may ignore it.
1663
+ */
1664
+ opts?: {
1665
+ metadata?: Record<string, unknown> | null;
1666
+ }) => Promise<{
1667
+ ok: boolean;
1668
+ error?: string;
1669
+ }>;
1670
+ detach: (token: EntityTypeToken, resourceId: string, role?: string) => Promise<{
1671
+ ok: boolean;
1672
+ error?: string;
1673
+ }>;
1674
+ /**
1675
+ * Optional pin capability (edge `metadata.pinned`) — pinned resources stay
1676
+ * inline in agent context at every tier. Rows show a pin toggle when set.
1677
+ */
1678
+ setPinned?: (token: EntityTypeToken, resourceId: string, pinned: boolean) => Promise<{
1679
+ ok: boolean;
1680
+ error?: string;
1681
+ }>;
1682
+ }
1683
+ /** Default adapter — wraps `useContainerLinks` (org/scope/project pages). */
1684
+ declare function useContainerLinksAdapter(container: PrimaryEntity | null, tokens?: readonly EntityTypeToken[]): ContainerResourcesAdapter;
1685
+ interface AssociationListProps {
1686
+ /** Container override; defaults to the surrounding PrimaryEntityProvider. */
1687
+ container?: PrimaryEntity;
1688
+ /** Write/read override (war-room threads etc.). Default: useContainerLinks. */
1689
+ adapter?: ContainerResourcesAdapter;
1690
+ /** Restrict display + attach to these tokens (e.g. one dynamic tab). */
1691
+ tokens?: EntityTypeToken[];
1692
+ /** `full` = role sections + universal search; `compact` = flat token groups. */
1693
+ variant?: "full" | "compact";
1694
+ /** Extra per-token actions (e.g. war-room Upload / New document). */
1695
+ renderSectionActions?: (token: EntityTypeToken) => ReactNode;
1696
+ /** Open a resource. Default: registry `hrefFor` in a new tab. */
1697
+ openEntity?: (token: string, id: string) => void;
1698
+ /**
1699
+ * Per-token row override (return null/undefined to keep the default row) —
1700
+ * for rows that need richer rendering than icon+title. The override owns the
1701
+ * whole row; use `ctx` for the resolved title and the busy/detach/open
1702
+ * wiring.
1703
+ */
1704
+ renderRow?: (row: ContainerResourceRow, ctx: {
1705
+ title: string;
1706
+ busy: boolean;
1707
+ onDetach: () => void;
1708
+ onOpen: () => void;
1709
+ }) => ReactNode | null | undefined;
1710
+ className?: string;
1711
+ }
1712
+ declare function AssociationList(props: AssociationListProps): react.JSX.Element;
1713
+
1714
+ type IconProps = SVGProps<SVGSVGElement>;
1715
+ /**
1716
+ * The default entity glyph for tokens with no host overlay icon (lucide
1717
+ * `Boxes` — the original registry's DEFAULT_ICON, now a /react concern
1718
+ * because /core ships `Icon: null`).
1719
+ */
1720
+ declare function DefaultEntityIcon(props: IconProps): react.JSX.Element;
1721
+
1722
+ interface CaptureAttachResult {
1723
+ ok: boolean;
1724
+ /** Human error text — the toolbar screams it. Omit when the host already did. */
1725
+ error?: string;
1726
+ }
1727
+ /**
1728
+ * ONE write callback for every capture verb. Tokens are canonical
1729
+ * (`file` / `udt_document`); the host maps to its own write path (an
1730
+ * association edge, a thread thunk, …) and reports the outcome honestly —
1731
+ * a silent no-op attach is the bug class this contract kills.
1732
+ */
1733
+ type CaptureAttach = (token: EntityTypeToken, resourceId: string, opts?: {
1734
+ label?: string;
1735
+ }) => Promise<CaptureAttachResult>;
1736
+ interface AssociationCaptureToolbarProps {
1737
+ attach: CaptureAttach;
1738
+ /** Logical cloud-files folder new uploads land in (auto-created). */
1739
+ uploadFolderPath: string;
1740
+ /** Visibility stamped on uploads. Default "personal". */
1741
+ uploadVisibility?: string;
1742
+ /**
1743
+ * Where a created-but-unlinked upload is reported to live, e.g.
1744
+ * "your Files (War Room folder)". Keeps the loud-outcome copy honest.
1745
+ */
1746
+ uploadLocationLabel: string;
1747
+ /** The retry verb named in loud-outcome copy. Default '"Add file"'. */
1748
+ attachRetryLabel?: string;
1749
+ /** Copy for the existing-files picker dialog. */
1750
+ filePicker?: {
1751
+ title?: string;
1752
+ description?: string;
1753
+ };
1754
+ /** Which built-in actions render (each ALSO gated on its port handler). */
1755
+ showActions?: {
1756
+ upload?: boolean;
1757
+ addFile?: boolean;
1758
+ newDocument?: boolean;
1759
+ };
1760
+ /** Hide the button row (compact variants) — drag-and-drop stays live. */
1761
+ showToolbar?: boolean;
1762
+ /** Extra host-specific buttons appended after the built-ins. */
1763
+ extraActions?: ReactNode;
1764
+ /** Open a freshly created document via the registry door. Default true. */
1765
+ openCreatedDocument?: boolean;
1766
+ className?: string;
1767
+ /** The body the drop target wraps (the list of attached things). */
1768
+ children?: ReactNode;
1769
+ }
1770
+ declare function AssociationCaptureToolbar({ attach, uploadFolderPath, uploadVisibility, uploadLocationLabel, attachRetryLabel, filePicker, showActions, showToolbar, extraActions, openCreatedDocument, className, children, }: AssociationCaptureToolbarProps): react.JSX.Element;
1771
+ /** The dense toolbar button (exported so hosts' extraActions match). */
1772
+ declare function CaptureToolbarAction({ icon: Icon, label, onClick, disabled, spinning, }: {
1773
+ icon: (props: IconProps) => ReactNode;
1774
+ label: string;
1775
+ onClick: () => void;
1776
+ disabled?: boolean;
1777
+ spinning?: boolean;
1778
+ }): react.JSX.Element;
1779
+
1780
+ interface AssociationEntitySelectProps {
1781
+ token: EntityTypeToken;
1782
+ adapter: AssociationEntitySelectAdapter;
1783
+ className?: string;
1784
+ /** Label sizing/typography override (defaults to toolbar-dense text-xs). */
1785
+ labelClassName?: string;
1786
+ align?: "start" | "end";
1787
+ showIcon?: boolean;
1788
+ /** How the name enters inline edit. Default "click". */
1789
+ renameActivation?: "click" | "doubleClick";
1790
+ /** Shown while no entity is active yet. Defaults to the plural label. */
1791
+ emptyLabel?: string;
1792
+ /** Icon color accent (e.g. "text-yellow-500" for notes). */
1793
+ iconClassName?: string;
1794
+ /**
1795
+ * Replaces the default "+ New <Entity>" name-input footer with a custom
1796
+ * creator (e.g. an agent picker that starts a new chat). Function form
1797
+ * receives `close` so the creator can dismiss the dropdown when done.
1798
+ */
1799
+ createSlot?: React.ReactNode | ((close: () => void) => React.ReactNode);
1800
+ }
1801
+ declare function AssociationEntitySelect({ token, adapter, className, labelClassName, align, showIcon, renameActivation, emptyLabel, iconClassName, createSlot, }: AssociationEntitySelectProps): react.JSX.Element;
1802
+
1803
+ interface CategorySelectProps {
1804
+ dimension: CategoryDimension;
1805
+ value: string | null;
1806
+ onChange: (id: string | null) => void;
1807
+ placeholder: string;
1808
+ allowNone?: boolean;
1809
+ disabled?: boolean;
1810
+ /**
1811
+ * Offer "Create «what you typed»". On by default — a closed category list is
1812
+ * a defect, so turning this off needs a reason a person would accept.
1813
+ */
1814
+ allowCreate?: boolean;
1815
+ /**
1816
+ * Org for an inline-created category. Defaults to the identity port's
1817
+ * `ensureOrgId()`; with neither, create refuses loudly.
1818
+ */
1819
+ orgId?: string | null;
1820
+ /** What one of these is called, for the create affordance ("stage", "folder"). */
1821
+ noun?: string;
1822
+ }
1823
+ declare function CategorySelect({ dimension, value, onChange, placeholder, allowNone, disabled, allowCreate, orgId, noun, }: CategorySelectProps): react.JSX.Element;
1824
+
1825
+ /** Structural stand-in for the host's `LucideIcon` on the `icon` prop. */
1826
+ type TagPickerIcon = ComponentType<{
1827
+ className?: string;
1828
+ }>;
1829
+ interface CategoryTagPickerProps {
1830
+ /** The tagged entity's registered association type (e.g. "fc_set", "party"). */
1831
+ entityType: string;
1832
+ entityId: string;
1833
+ /** The `platform.categories` facet the picker offers. */
1834
+ dimension: CategoryDimension;
1835
+ /** The typed edge role the assignment edges carry (e.g. "theme", "member"). */
1836
+ edgeRole: string;
1837
+ /**
1838
+ * Org for the edge write and for inline-created categories. Defaults to the
1839
+ * identity port's `ensureOrgId()` (create only) — pass the owning entity's
1840
+ * org when it has one.
1841
+ */
1842
+ orgId?: string | null;
1843
+ /** Trigger label while nothing is selected. */
1844
+ addLabel?: string;
1845
+ /** Trigger icon. */
1846
+ icon?: TagPickerIcon;
1847
+ /** Offer "Create <term>" for unmatched search terms. Default true. */
1848
+ allowCreate?: boolean;
1849
+ /**
1850
+ * Force the two-level face on or off. Omit to detect it from parentId rows,
1851
+ * which leaves every existing flat facet visually unchanged.
1852
+ */
1853
+ hierarchical?: boolean;
1854
+ emptyText?: string;
1855
+ }
1856
+ /**
1857
+ * Multi-select combobox: badges for the entity's current tags in `dimension`,
1858
+ * a popover to toggle existing categories, optional inline create. Fully
1859
+ * self-contained — mount it once per entity and it reads/writes the edges.
1860
+ */
1861
+ declare function CategoryTagPicker({ entityType, entityId, dimension, edgeRole, orgId, addLabel, icon: Icon, allowCreate, hierarchical, emptyText, }: CategoryTagPickerProps): react.JSX.Element;
1862
+
1863
+ interface CommentThreadProps {
1864
+ /** Entity-type token of the commented-on entity. */
1865
+ token: EntityTypeToken;
1866
+ /** The entity's row id. */
1867
+ id: string;
1868
+ /** Org override forwarded to `cmt_add` (the RPC resolves one when omitted). */
1869
+ orgId?: string | null;
1870
+ /** Hide the slim "Comments · n" header row. Defaults to shown. */
1871
+ showHeader?: boolean;
1872
+ className?: string;
1873
+ }
1874
+ interface CommentComposerProps {
1875
+ /** Post the body; resolve `{ok:false}` to keep the text + show the error. */
1876
+ onSubmit: (body: string) => Promise<{
1877
+ ok: boolean;
1878
+ error?: string;
1879
+ }>;
1880
+ placeholder?: string;
1881
+ submitLabel?: string;
1882
+ /** Initial body (the edit flow seeds the current text). */
1883
+ initialValue?: string;
1884
+ /** Rendered right of the submit button (the Cancel affordance). */
1885
+ trailing?: ReactNode;
1886
+ autoFocus?: boolean;
1887
+ }
1888
+ /**
1889
+ * The one composer every comment write goes through (new comment, reply,
1890
+ * edit). Submit on the button or Cmd/Ctrl+Enter; the text survives a failed
1891
+ * submit alongside the inline error (input is never lost).
1892
+ */
1893
+ declare function CommentComposer({ onSubmit, placeholder, submitLabel, initialValue, trailing, autoFocus, }: CommentComposerProps): react.JSX.Element;
1894
+ /**
1895
+ * Build the parent→children index. A reply whose parent is missing from the
1896
+ * list (soft-deleted parent, partial page) is promoted to top level rather
1897
+ * than dropped — every visible comment stays reachable.
1898
+ */
1899
+ declare function buildCommentTree(comments: readonly PlatformComment[]): {
1900
+ roots: PlatformComment[];
1901
+ childrenOf: Map<string, PlatformComment[]>;
1902
+ };
1903
+ declare function CommentThread({ token, id, orgId, showHeader, className, }: CommentThreadProps): react.JSX.Element;
1904
+
1905
+ export { DefaultEntityIcon as $, type AssociationCaptureToolbarProps as A, AssociationCaptureToolbar as B, type CategorySelectProps as C, AssociationCard as D, type EntityDoorsPort as E, AssociationCardGrid as F, AssociationEntitySelect as G, type AssociationEntitySelectAdapter as H, type AssociationEntitySelectItem as I, AssociationList as J, AssociationWindow as K, type AssociationWriteResult as L, AttachedItemsSheet as M, type CaptureAttach as N, type CaptureAttachResult as O, type PickerOverrideMap as P, CaptureToolbarAction as Q, CategorySelect as R, CategoryTagPicker as S, CommentComposer as T, type UniversalAssociationPickerProps as U, type CommentComposerProps as V, type WindowShellPort as W, CommentThread as X, type ContainerLink as Y, type ContainerResourceRow as Z, type ContainerResourcesAdapter as _, type AssociationCardProps as a, type PrimaryEntity as a0, PrimaryEntityProvider as a1, type TagPickerIcon as a2, UniversalAssociationPicker as a3, type UseAssociationEntitySelectAdapterArgs as a4, type UseAssociationsArgs as a5, type UseAssociationsReturn as a6, type UseContainerLinksArgs as a7, type UseContainerLinksReturn as a8, attachedKey as a9, buildCommentTree as aa, useAssociationEntitySelectAdapter as ab, useAssociations as ac, useContainerLinks as ad, useContainerLinksAdapter as ae, useEntityRelationships as af, usePrimaryEntity as ag, type AssociationCardGridProps as b, type AssociationEntitySelectProps as c, type AssociationListProps as d, type AssociationPickerProps as e, type AssociationWindowProps as f, type AttachedItemsSheetProps as g, type CategoryTagPickerProps as h, type CommentThreadProps as i, type AssociationsNotifier as j, type CapturePort as k, type AuthorDisplayPort as l, type AssociationsStore as m, type CategoryMutationResult as n, type CategoryDimension as o, type PlatformCategory as p, type CategoriesEntry as q, type EntityTypeToken as r, type UniversalCandidate as s, type CandidateRecord as t, type PlatformComment as u, type CommentsEntry as v, type CommentMutationResult as w, type EntityDoorProps as x, type EntityRefProps as y, type ContentRole as z };