@ai-matrx/associations 0.2.0 → 0.3.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/CHANGELOG.md +95 -0
- package/README.md +35 -5
- package/dist/core/index.cjs +3 -1
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +13 -0
- package/dist/core/index.d.ts +13 -0
- package/dist/core/index.js +3 -1
- package/dist/core/index.js.map +1 -1
- package/dist/react/index.cjs +3158 -0
- package/dist/react/index.cjs.map +1 -0
- package/dist/react/index.d.cts +1758 -0
- package/dist/react/index.d.ts +1758 -0
- package/dist/react/index.js +3142 -0
- package/dist/react/index.js.map +1 -0
- package/package.json +24 -3
|
@@ -0,0 +1,1758 @@
|
|
|
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
|
+
}
|
|
280
|
+
/** The name of any demanded RPC — the only strings the dataSource port accepts. */
|
|
281
|
+
type DemandedRpcName = keyof DemandedRpcSignatures;
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* EVERY registered entity token (the FK-valid set). Use this for any
|
|
285
|
+
* `source_type` / `target_type` argument so an invalid token is a COMPILE error.
|
|
286
|
+
*/
|
|
287
|
+
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_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" | "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" | "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_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";
|
|
288
|
+
|
|
289
|
+
type AssociationsRpcErrorCode = "unauthorized" | "forbidden_org" | "forbidden_role" | "not_found" | "conflict_in_use" | "invalid_argument" | "version_conflict" | "quota_exceeded"
|
|
290
|
+
/**
|
|
291
|
+
* THE DEMANDED-SCHEMA SCREAM. A PostgREST missing-function error (PGRST202)
|
|
292
|
+
* on any demanded RPC maps to this code: the database this client is
|
|
293
|
+
* pointed at does not run the schema this package demands (README front
|
|
294
|
+
* door). It always reaches the errorSink — one unambiguous scream, never a
|
|
295
|
+
* mystery toast. Probe it at boot with `assertDemandedSchema` (/core, W2).
|
|
296
|
+
*/
|
|
297
|
+
| "demanded_schema_violation" | "internal";
|
|
298
|
+
interface AssociationsRpcError {
|
|
299
|
+
code: AssociationsRpcErrorCode;
|
|
300
|
+
message: string;
|
|
301
|
+
hint?: string;
|
|
302
|
+
detail?: unknown;
|
|
303
|
+
}
|
|
304
|
+
type AssociationsRpcResult<T> = {
|
|
305
|
+
ok: true;
|
|
306
|
+
data: T;
|
|
307
|
+
} | {
|
|
308
|
+
ok: false;
|
|
309
|
+
error: AssociationsRpcError;
|
|
310
|
+
};
|
|
311
|
+
/**
|
|
312
|
+
* The structural shape of a PostgREST failure as supabase-js resolves it: a
|
|
313
|
+
* PLAIN OBJECT parsed from the response body — NOT an `Error` instance.
|
|
314
|
+
* (Reading `.message` off `instanceof Error` discards the real database
|
|
315
|
+
* message on every genuine failure; `/core`'s mapper reads these fields.)
|
|
316
|
+
*/
|
|
317
|
+
interface PgError {
|
|
318
|
+
code?: string | null;
|
|
319
|
+
message: string;
|
|
320
|
+
details?: string | null;
|
|
321
|
+
hint?: string | null;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* The minimal table surface entity-row create/rename needs (a structural
|
|
326
|
+
* subset of supabase-js's query builder). Registry-convention writes go
|
|
327
|
+
* DIRECT to the backing table (they are RLS-gated feature rows, not
|
|
328
|
+
* association edges — there is no RPC for them by design).
|
|
329
|
+
*/
|
|
330
|
+
interface AssociationsTableQuery {
|
|
331
|
+
insert(row: Record<string, unknown>): {
|
|
332
|
+
select(columns: string): {
|
|
333
|
+
single(): PromiseLike<{
|
|
334
|
+
data: unknown;
|
|
335
|
+
error: PgError | null;
|
|
336
|
+
}>;
|
|
337
|
+
};
|
|
338
|
+
};
|
|
339
|
+
update(patch: Record<string, unknown>): {
|
|
340
|
+
eq(column: string, value: string): PromiseLike<{
|
|
341
|
+
error: PgError | null;
|
|
342
|
+
}>;
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* The data seam — a structural subset of `SupabaseClient<Database>`: any
|
|
347
|
+
* client that can answer the demanded RPC families (README § The demanded
|
|
348
|
+
* schema). The package IS data operations; there is no degraded mode without
|
|
349
|
+
* one. `PromiseLike` because supabase-js returns a thenable builder, not a
|
|
350
|
+
* `Promise`.
|
|
351
|
+
*
|
|
352
|
+
* `from`/`schema` are OPTIONAL (W2, additive): only the entity-row
|
|
353
|
+
* create/rename service uses them (generic registry-convention row writes).
|
|
354
|
+
* A dataSource without them still satisfies every RPC operation; calling
|
|
355
|
+
* entity-row create/rename against it returns a screamed `{ok:false}`
|
|
356
|
+
* result naming the missing capability — never a silent no-op. A real
|
|
357
|
+
* supabase-js client satisfies both structurally.
|
|
358
|
+
*/
|
|
359
|
+
interface AssociationsDataSource {
|
|
360
|
+
rpc(fn: DemandedRpcName, args: Record<string, unknown>): PromiseLike<{
|
|
361
|
+
data: unknown;
|
|
362
|
+
error: PgError | null;
|
|
363
|
+
}>;
|
|
364
|
+
from?(table: string): AssociationsTableQuery;
|
|
365
|
+
schema?(name: string): {
|
|
366
|
+
from(table: string): AssociationsTableQuery;
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* The identity seam — today a store-singleton read (`requireUserId`) plus the
|
|
371
|
+
* org resolver `CategoryTagPicker` uses for created rows. `requireUserId`
|
|
372
|
+
* failures stay LOUD (`Not authenticated`) — never silently anonymous.
|
|
373
|
+
*/
|
|
374
|
+
interface AssociationsIdentity {
|
|
375
|
+
requireUserId(): string;
|
|
376
|
+
/** Org for created rows/edges (the CategoryTagPicker create path). */
|
|
377
|
+
ensureOrgId?(): Promise<string>;
|
|
378
|
+
}
|
|
379
|
+
/**
|
|
380
|
+
* The scream seam — REQUIRED: recovery layers must scream somewhere. Every
|
|
381
|
+
* degraded path, every `demanded_schema_violation`, every create-then-attach
|
|
382
|
+
* partial failure reports here regardless of notifier availability.
|
|
383
|
+
*/
|
|
384
|
+
type ErrorSink = (event: {
|
|
385
|
+
code: string;
|
|
386
|
+
message: string;
|
|
387
|
+
context?: object;
|
|
388
|
+
}) => void;
|
|
389
|
+
/**
|
|
390
|
+
* Per-token host overlay — the code-native values the DB registry cannot
|
|
391
|
+
* carry (today: the 804-line ENTITY_OVERLAY literal in matrx-frontend's
|
|
392
|
+
* entityRegistry). EVERY field optional; absence degrades per field:
|
|
393
|
+
* convention columns, default icon, `${label}s`, no door, generic
|
|
394
|
+
* titleColumn candidate read. A `reference_pickable` token with no title
|
|
395
|
+
* column and no override is screamed to the errorSink, never shown broken.
|
|
396
|
+
*/
|
|
397
|
+
interface EntityOverlayEntry {
|
|
398
|
+
/** Icon component (host-supplied; packages never depend on an icon library). */
|
|
399
|
+
Icon?: ElementType;
|
|
400
|
+
/** Plural label; default `${label}s`. */
|
|
401
|
+
labelPlural?: string;
|
|
402
|
+
/** Owner column override; default the "created_by" convention. */
|
|
403
|
+
ownerColumn?: string | null;
|
|
404
|
+
/** Org column override; default the "organization_id" convention. */
|
|
405
|
+
orgColumn?: string | null;
|
|
406
|
+
/** Route for this token's rows; absent → no open door (label renders plain). */
|
|
407
|
+
hrefFor?: (id: string) => string;
|
|
408
|
+
/**
|
|
409
|
+
* Candidate-list override for tokens whose backing table can't be read
|
|
410
|
+
* client-side (e.g. `data_store` — rag.* is not PostgREST-exposed);
|
|
411
|
+
* absent → the generic `reference_search_candidates` titleColumn read.
|
|
412
|
+
*/
|
|
413
|
+
listCandidates?: (args: {
|
|
414
|
+
search?: string;
|
|
415
|
+
limit?: number;
|
|
416
|
+
}) => Promise<{
|
|
417
|
+
ok: true;
|
|
418
|
+
data: {
|
|
419
|
+
id: string;
|
|
420
|
+
title: string;
|
|
421
|
+
}[];
|
|
422
|
+
} | {
|
|
423
|
+
ok: false;
|
|
424
|
+
error: string;
|
|
425
|
+
}>;
|
|
426
|
+
}
|
|
427
|
+
/** The overlay registration map — bound per host, merged over the generated registry. */
|
|
428
|
+
type EntityOverlayMap = Partial<Record<EntityTypeToken, EntityOverlayEntry>>;
|
|
429
|
+
/**
|
|
430
|
+
* The user-notification seam (today: `@/lib/toast` in 6 components).
|
|
431
|
+
* Optional — /react warns once when absent. Every user-facing failure ALSO
|
|
432
|
+
* routes to the errorSink + the component's inline error state, so the
|
|
433
|
+
* create-then-associate loud-outcome law is satisfied structurally, not by
|
|
434
|
+
* toast availability.
|
|
435
|
+
*/
|
|
436
|
+
interface AssociationsNotifier {
|
|
437
|
+
success(msg: string): void;
|
|
438
|
+
error(msg: string, opts?: {
|
|
439
|
+
description?: string;
|
|
440
|
+
action?: {
|
|
441
|
+
label: string;
|
|
442
|
+
onClick(): void;
|
|
443
|
+
};
|
|
444
|
+
}): void;
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* The draggable-window seam (today: `WindowPanel` in AssociationWindow).
|
|
448
|
+
* Absent → the package's internal fixed overlay (non-draggable); behavior
|
|
449
|
+
* identical, chrome plainer.
|
|
450
|
+
*/
|
|
451
|
+
interface WindowShellPort {
|
|
452
|
+
Window: ComponentType<{
|
|
453
|
+
id: string;
|
|
454
|
+
title: string;
|
|
455
|
+
onClose(): void;
|
|
456
|
+
children: ReactNode;
|
|
457
|
+
}>;
|
|
458
|
+
}
|
|
459
|
+
/** Options for {@link CapturePort.requestUpload} (measured: uploadGuardOpeners). */
|
|
460
|
+
interface CaptureUploadOpts {
|
|
461
|
+
files: File[];
|
|
462
|
+
/** Logical cloud-files folder new uploads land in (auto-created). */
|
|
463
|
+
folderPath: string;
|
|
464
|
+
/** Visibility stamped on uploads (host vocabulary, e.g. "personal"). */
|
|
465
|
+
visibility?: string;
|
|
466
|
+
}
|
|
467
|
+
/** Honest outcome of a host upload — created-but-unlinked must be reportable. */
|
|
468
|
+
interface CaptureUploadResult {
|
|
469
|
+
cancelled?: boolean;
|
|
470
|
+
uploaded: string[];
|
|
471
|
+
aliased: {
|
|
472
|
+
existingFileId: string;
|
|
473
|
+
}[];
|
|
474
|
+
failed: {
|
|
475
|
+
name: string;
|
|
476
|
+
error: string;
|
|
477
|
+
}[];
|
|
478
|
+
}
|
|
479
|
+
/** Options for {@link CapturePort.openFilePicker} (measured: cloudFilesPickerOpeners). */
|
|
480
|
+
interface CapturePickOpts {
|
|
481
|
+
multi?: boolean;
|
|
482
|
+
title?: string;
|
|
483
|
+
description?: string;
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* The capture-toolbar seam (today: features/files upload + pickers and
|
|
487
|
+
* features/data-tables imports in AssociationCaptureToolbar). PER-HANDLER
|
|
488
|
+
* optional: the toolbar renders only the chips whose handler exists; zero
|
|
489
|
+
* handlers → the toolbar renders nothing. NEVER dead buttons.
|
|
490
|
+
*/
|
|
491
|
+
interface CapturePort {
|
|
492
|
+
requestUpload?(opts: CaptureUploadOpts): Promise<CaptureUploadResult>;
|
|
493
|
+
/** Resolves with picked file ids, or null/empty on cancel. */
|
|
494
|
+
openFilePicker?(opts: CapturePickOpts): Promise<string[] | null>;
|
|
495
|
+
createDataTable?(opts: {
|
|
496
|
+
name: string;
|
|
497
|
+
}): Promise<{
|
|
498
|
+
id: string;
|
|
499
|
+
} | null>;
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* Props of the generic association picker face — ALSO the contract a
|
|
503
|
+
* per-token override component must implement (today: the hardcoded
|
|
504
|
+
* `token === "file"` → FilePickerWindow branch in AssociationPicker becomes a
|
|
505
|
+
* `registerPickerOverride("file", …)` host binding). Ported verbatim from the
|
|
506
|
+
* measured component.
|
|
507
|
+
*/
|
|
508
|
+
interface AssociationPickerProps {
|
|
509
|
+
open: boolean;
|
|
510
|
+
onOpenChange: (open: boolean) => void;
|
|
511
|
+
token: EntityTypeToken;
|
|
512
|
+
/** Container display label, for the header ("…to Titanium Marketing"). */
|
|
513
|
+
containerLabel?: string;
|
|
514
|
+
/** Org stamped onto rows created by the "+ New" footer. */
|
|
515
|
+
orgId?: string | null;
|
|
516
|
+
/** Resource ids already attached to the container. */
|
|
517
|
+
attachedIds: Set<string>;
|
|
518
|
+
/** Attach a resource (returns ok/err so the row can surface failures). */
|
|
519
|
+
onAttach: (resourceId: string, title: string) => Promise<{
|
|
520
|
+
ok: boolean;
|
|
521
|
+
error?: string;
|
|
522
|
+
}>;
|
|
523
|
+
/** Detach a resource. */
|
|
524
|
+
onDetach: (resourceId: string) => Promise<{
|
|
525
|
+
ok: boolean;
|
|
526
|
+
error?: string;
|
|
527
|
+
}>;
|
|
528
|
+
}
|
|
529
|
+
/** Per-token picker override map — absent tokens use the generic picker sheet. */
|
|
530
|
+
type PickerOverrideMap = Partial<Record<EntityTypeToken, ComponentType<AssociationPickerProps>>>;
|
|
531
|
+
/**
|
|
532
|
+
* Props the entity-doors port's `EntityRef` receives (the measured subset the
|
|
533
|
+
* association faces pass today).
|
|
534
|
+
*/
|
|
535
|
+
interface EntityRefProps {
|
|
536
|
+
token: string;
|
|
537
|
+
id: string;
|
|
538
|
+
name?: string | null;
|
|
539
|
+
showIcon?: boolean;
|
|
540
|
+
openInNewTab?: boolean;
|
|
541
|
+
alwaysShowActions?: boolean;
|
|
542
|
+
className?: string;
|
|
543
|
+
}
|
|
544
|
+
/** Props the entity-doors port's `DoorControls` receives. */
|
|
545
|
+
interface EntityDoorProps {
|
|
546
|
+
token: string;
|
|
547
|
+
id: string;
|
|
548
|
+
name?: string | null;
|
|
549
|
+
className?: string;
|
|
550
|
+
}
|
|
551
|
+
/**
|
|
552
|
+
* The entity-doors seam (today: `EntityRef` / `EntityDoorControls` /
|
|
553
|
+
* access-gate `UnresolvedEntityRef`). Absent → title text plus the overlay's
|
|
554
|
+
* `hrefFor` link when present; unresolved rows render the package's plain
|
|
555
|
+
* "unavailable" chip.
|
|
556
|
+
*/
|
|
557
|
+
interface EntityDoorsPort {
|
|
558
|
+
EntityRef?: ComponentType<EntityRefProps>;
|
|
559
|
+
DoorControls?: ComponentType<EntityDoorProps>;
|
|
560
|
+
UnresolvedRef?: ComponentType<{
|
|
561
|
+
token: string;
|
|
562
|
+
id: string;
|
|
563
|
+
}>;
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* Everything a host binds, once. `createAssociationsStore(cfg)` (/core, W2)
|
|
567
|
+
* throws when a REQUIRED port is missing; every optional port degrades per
|
|
568
|
+
* its own documented contract, never silently.
|
|
569
|
+
*/
|
|
570
|
+
interface AssociationsConfig {
|
|
571
|
+
dataSource: AssociationsDataSource;
|
|
572
|
+
identity: AssociationsIdentity;
|
|
573
|
+
errorSink: ErrorSink;
|
|
574
|
+
entityOverlay?: EntityOverlayMap;
|
|
575
|
+
notifier?: AssociationsNotifier;
|
|
576
|
+
windowShell?: WindowShellPort;
|
|
577
|
+
capture?: CapturePort;
|
|
578
|
+
pickerOverrides?: PickerOverrideMap;
|
|
579
|
+
entityDoors?: EntityDoorsPort;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
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"];
|
|
583
|
+
type AssociationTargetType = (typeof ASSOCIATION_TARGET_TYPES)[number];
|
|
584
|
+
interface AssociationEdge {
|
|
585
|
+
id: string;
|
|
586
|
+
direction: "outgoing" | "incoming";
|
|
587
|
+
otherType: string;
|
|
588
|
+
otherId: string;
|
|
589
|
+
role: string | null;
|
|
590
|
+
label: string | null;
|
|
591
|
+
position: number | null;
|
|
592
|
+
metadata: unknown;
|
|
593
|
+
orgId: string | null;
|
|
594
|
+
createdAt: string;
|
|
595
|
+
}
|
|
596
|
+
interface AssociationTargetEdge {
|
|
597
|
+
id: string;
|
|
598
|
+
targetId: string;
|
|
599
|
+
sourceType: string;
|
|
600
|
+
sourceId: string;
|
|
601
|
+
role: string | null;
|
|
602
|
+
label: string | null;
|
|
603
|
+
position: number | null;
|
|
604
|
+
metadata: unknown;
|
|
605
|
+
orgId: string | null;
|
|
606
|
+
createdAt: string;
|
|
607
|
+
}
|
|
608
|
+
interface AssociationSourceEdge {
|
|
609
|
+
id: string;
|
|
610
|
+
sourceId: string;
|
|
611
|
+
targetType: string;
|
|
612
|
+
targetId: string;
|
|
613
|
+
role: string | null;
|
|
614
|
+
label: string | null;
|
|
615
|
+
position: number | null;
|
|
616
|
+
metadata: unknown;
|
|
617
|
+
orgId: string | null;
|
|
618
|
+
createdAt: string;
|
|
619
|
+
}
|
|
620
|
+
interface AssociationsEntry {
|
|
621
|
+
status: "idle" | "loading" | "ready" | "error";
|
|
622
|
+
edges: AssociationEdge[];
|
|
623
|
+
fetchedAt: number | null;
|
|
624
|
+
error: string | null;
|
|
625
|
+
}
|
|
626
|
+
interface UserEntityState {
|
|
627
|
+
entityType: string;
|
|
628
|
+
entityId: string;
|
|
629
|
+
isFavorite: boolean;
|
|
630
|
+
isPinned: boolean;
|
|
631
|
+
isHidden: boolean;
|
|
632
|
+
lastViewedAt: string | null;
|
|
633
|
+
}
|
|
634
|
+
/** The three boolean dimensions of per-user state, as accepted by `ues_list`. */
|
|
635
|
+
type UserStateKind = "favorite" | "pinned" | "hidden";
|
|
636
|
+
/**
|
|
637
|
+
* The facet a category belongs to. Open vocabulary (new dimensions need no
|
|
638
|
+
* migration — `dimension` is free text in the DB); hosts enumerate their
|
|
639
|
+
* known dimensions as constants.
|
|
640
|
+
*/
|
|
641
|
+
type CategoryDimension = string;
|
|
642
|
+
/** One `platform.categories` row, camelCased (mirrors `cat_list`'s return). */
|
|
643
|
+
interface PlatformCategory {
|
|
644
|
+
id: string;
|
|
645
|
+
/** Owning organization; system/global rows use the Matrx System org. */
|
|
646
|
+
orgId: string | null;
|
|
647
|
+
dimension: CategoryDimension;
|
|
648
|
+
name: string;
|
|
649
|
+
slug: string | null;
|
|
650
|
+
parentId: string | null;
|
|
651
|
+
isSystem: boolean;
|
|
652
|
+
color: string | null;
|
|
653
|
+
icon: string | null;
|
|
654
|
+
position: number | null;
|
|
655
|
+
/**
|
|
656
|
+
* The row's jsonb metadata — category rows CARRY semantics: e.g. a
|
|
657
|
+
* `deal_pipeline` stage stores `{outcome: "won"|"lost", probability: 0..100}`
|
|
658
|
+
* here. Null when empty or when hydrated from an older cache entry.
|
|
659
|
+
*/
|
|
660
|
+
metadata: Record<string, unknown> | null;
|
|
661
|
+
}
|
|
662
|
+
/** Cache entry for one `dimension` — mirrors `AssociationsEntry`. */
|
|
663
|
+
interface CategoriesEntry {
|
|
664
|
+
status: "idle" | "loading" | "ready" | "error";
|
|
665
|
+
categories: PlatformCategory[];
|
|
666
|
+
fetchedAt: number | null;
|
|
667
|
+
error: string | null;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
type ContentRole = "utility" | "source" | "destination" | "hybrid" | "container";
|
|
671
|
+
/**
|
|
672
|
+
* Fully-resolved entity descriptor — generated metadata + host overlay, with
|
|
673
|
+
* safe fallbacks so an un-overlaid token still renders (derived plural, no
|
|
674
|
+
* door, `Icon: null` → the consumer's default) even if it can't be queried
|
|
675
|
+
* for candidates yet.
|
|
676
|
+
*/
|
|
677
|
+
interface EntityInfo {
|
|
678
|
+
token: EntityTypeToken;
|
|
679
|
+
label: string;
|
|
680
|
+
labelPlural: string;
|
|
681
|
+
/** Postgres schema of the backing table (from the generated registry). */
|
|
682
|
+
schema: string;
|
|
683
|
+
/** Backing table name (from the generated registry). */
|
|
684
|
+
table: string;
|
|
685
|
+
/** Title column for the picker, or null when none is registered. */
|
|
686
|
+
titleColumn: string | null;
|
|
687
|
+
/** Ownership column to scope candidate reads to the current user. */
|
|
688
|
+
ownerColumn: string;
|
|
689
|
+
/** Org-scoping column. */
|
|
690
|
+
orgColumn: string;
|
|
691
|
+
/** Host-supplied icon component, or null (consumer renders its default). */
|
|
692
|
+
Icon: EntityOverlayEntry["Icon"] | null;
|
|
693
|
+
hrefFor: ((id: string) => string) | null;
|
|
694
|
+
scopeable: boolean;
|
|
695
|
+
category: string | null;
|
|
696
|
+
/** Knowledge-model grouping bucket (resource surfaces group by this). */
|
|
697
|
+
contentRole: ContentRole;
|
|
698
|
+
/** Candidate-source override (rag-backed tokens etc.); null = generic read. */
|
|
699
|
+
listCandidates: EntityOverlayEntry["listCandidates"] | null;
|
|
700
|
+
/** True when a picker can list real candidates (title column OR override). */
|
|
701
|
+
canListCandidates: boolean;
|
|
702
|
+
}
|
|
703
|
+
interface EntityRegistry {
|
|
704
|
+
/** Merge more overlay entries in (host binding, W4 pickers, tests). */
|
|
705
|
+
registerEntityOverlay(overlay: EntityOverlayMap): void;
|
|
706
|
+
/** Resolve a KNOWN token to its full descriptor. */
|
|
707
|
+
getEntityInfo(token: EntityTypeToken): EntityInfo;
|
|
708
|
+
/** Safe variant for raw strings (e.g. an edge's `otherType`). */
|
|
709
|
+
tryGetEntityInfo(token: string): EntityInfo | null;
|
|
710
|
+
/** Resolve from a live `(schema, table)` pair, or null. */
|
|
711
|
+
tryGetEntityInfoByTable(schema: string, table: string): EntityInfo | null;
|
|
712
|
+
/** Resolve a raw table name only when it maps to exactly one entity. */
|
|
713
|
+
tryGetEntityInfoByUniqueTableName(table: string): EntityInfo | null;
|
|
714
|
+
/**
|
|
715
|
+
* Tokens the DB classifies as knowledge resources via a valid
|
|
716
|
+
* `content_role` AND that can list candidates. The default set for card
|
|
717
|
+
* grids, resource sections, and attach pickers.
|
|
718
|
+
*/
|
|
719
|
+
curatedTokens(): EntityTypeToken[];
|
|
720
|
+
/**
|
|
721
|
+
* Tokens offered as reference "Allowed types" — DB-driven via
|
|
722
|
+
* `platform.entity_types.reference_pickable`. A pickable token with no
|
|
723
|
+
* title column and no candidate override is a config defect: excluded and
|
|
724
|
+
* screamed to the errorSink, never silently shown broken.
|
|
725
|
+
*/
|
|
726
|
+
listableTokens(): EntityTypeToken[];
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
interface ConversationFileLink {
|
|
730
|
+
fileId: string;
|
|
731
|
+
label: string | null;
|
|
732
|
+
metadata: unknown;
|
|
733
|
+
createdAt: string;
|
|
734
|
+
}
|
|
735
|
+
interface AddAssociationArgs {
|
|
736
|
+
sourceType: string;
|
|
737
|
+
sourceId: string;
|
|
738
|
+
targetType: AssociationTargetType;
|
|
739
|
+
targetId: string;
|
|
740
|
+
orgId?: string;
|
|
741
|
+
label?: string;
|
|
742
|
+
metadata?: unknown;
|
|
743
|
+
/**
|
|
744
|
+
* Exact file → conversation updates preserve existing metadata unless the
|
|
745
|
+
* caller explicitly opts into replacement. Invalid for every other pair.
|
|
746
|
+
*/
|
|
747
|
+
replaceMetadata?: boolean;
|
|
748
|
+
role?: string;
|
|
749
|
+
position?: number;
|
|
750
|
+
/**
|
|
751
|
+
* Typed edge payload (Edge Payload System). `payloadKind` must be a
|
|
752
|
+
* registered `platform.edge_payload_kind`; the DB trigger validates
|
|
753
|
+
* `payload` against its JSON Schema and hard-fails on any mismatch. Real
|
|
754
|
+
* logic an edge carries goes HERE — `metadata` is for loose annotations.
|
|
755
|
+
*/
|
|
756
|
+
payloadKind?: string;
|
|
757
|
+
payload?: unknown;
|
|
758
|
+
}
|
|
759
|
+
interface AssociationsServiceApi {
|
|
760
|
+
listForEntity(rawType: string, id: string): Promise<AssociationsRpcResult<{
|
|
761
|
+
edges: AssociationEdge[];
|
|
762
|
+
}>>;
|
|
763
|
+
listConversationFiles(conversationId: string): Promise<AssociationsRpcResult<{
|
|
764
|
+
files: ConversationFileLink[];
|
|
765
|
+
}>>;
|
|
766
|
+
listForTargets(rawTargetType: string, targetIds: string[]): Promise<AssociationsRpcResult<{
|
|
767
|
+
edges: AssociationTargetEdge[];
|
|
768
|
+
}>>;
|
|
769
|
+
listForTargetsVisible(rawTargetType: string, targetIds: string[]): Promise<AssociationsRpcResult<{
|
|
770
|
+
edges: AssociationTargetEdge[];
|
|
771
|
+
}>>;
|
|
772
|
+
listForSources(rawSourceType: string, sourceIds: string[], rawTargetType?: string): Promise<AssociationsRpcResult<{
|
|
773
|
+
edges: AssociationSourceEdge[];
|
|
774
|
+
}>>;
|
|
775
|
+
add(args: AddAssociationArgs): Promise<AssociationsRpcResult<{
|
|
776
|
+
id: string;
|
|
777
|
+
}>>;
|
|
778
|
+
remove(args: {
|
|
779
|
+
sourceType: string;
|
|
780
|
+
sourceId: string;
|
|
781
|
+
targetType: string;
|
|
782
|
+
targetId: string;
|
|
783
|
+
role?: string;
|
|
784
|
+
}): Promise<AssociationsRpcResult<null>>;
|
|
785
|
+
setTargets(args: {
|
|
786
|
+
sourceType: string;
|
|
787
|
+
sourceId: string;
|
|
788
|
+
targetType: AssociationTargetType;
|
|
789
|
+
targetIds: string[];
|
|
790
|
+
orgId?: string;
|
|
791
|
+
role?: string;
|
|
792
|
+
}): Promise<AssociationsRpcResult<null>>;
|
|
793
|
+
addAgentResource(args: {
|
|
794
|
+
agentId: string;
|
|
795
|
+
sourceType: string;
|
|
796
|
+
sourceId: string;
|
|
797
|
+
label?: string;
|
|
798
|
+
metadata?: unknown;
|
|
799
|
+
}): Promise<AssociationsRpcResult<{
|
|
800
|
+
id: string;
|
|
801
|
+
}>>;
|
|
802
|
+
removeAgentResource(args: {
|
|
803
|
+
agentId: string;
|
|
804
|
+
sourceType: string;
|
|
805
|
+
sourceId: string;
|
|
806
|
+
}): Promise<AssociationsRpcResult<null>>;
|
|
807
|
+
removeForEntity(rawType: string, id: string): Promise<AssociationsRpcResult<null>>;
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
interface CategoriesServiceApi {
|
|
811
|
+
list(dimension?: CategoryDimension): Promise<AssociationsRpcResult<{
|
|
812
|
+
categories: PlatformCategory[];
|
|
813
|
+
}>>;
|
|
814
|
+
create(args: {
|
|
815
|
+
dimension: CategoryDimension;
|
|
816
|
+
name: string;
|
|
817
|
+
orgId: string;
|
|
818
|
+
parentId?: string | null;
|
|
819
|
+
color?: string | null;
|
|
820
|
+
icon?: string | null;
|
|
821
|
+
slug?: string | null;
|
|
822
|
+
}): Promise<AssociationsRpcResult<{
|
|
823
|
+
id: string;
|
|
824
|
+
}>>;
|
|
825
|
+
update(args: {
|
|
826
|
+
id: string;
|
|
827
|
+
name: string;
|
|
828
|
+
slug: string | null;
|
|
829
|
+
color: string | null;
|
|
830
|
+
icon: string | null;
|
|
831
|
+
position: number | null;
|
|
832
|
+
}): Promise<AssociationsRpcResult<{
|
|
833
|
+
id: string;
|
|
834
|
+
}>>;
|
|
835
|
+
reparent(args: {
|
|
836
|
+
id: string;
|
|
837
|
+
parentId: string | null;
|
|
838
|
+
}): Promise<AssociationsRpcResult<{
|
|
839
|
+
id: string;
|
|
840
|
+
}>>;
|
|
841
|
+
delete(id: string): Promise<AssociationsRpcResult<{
|
|
842
|
+
id: string;
|
|
843
|
+
}>>;
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
interface FavoritesServiceApi {
|
|
847
|
+
setState(args: {
|
|
848
|
+
entityType: string;
|
|
849
|
+
entityId: string;
|
|
850
|
+
isFavorite?: boolean;
|
|
851
|
+
isPinned?: boolean;
|
|
852
|
+
isHidden?: boolean;
|
|
853
|
+
}): Promise<AssociationsRpcResult<null>>;
|
|
854
|
+
setFavorite(entityType: string, entityId: string, isFavorite: boolean): Promise<AssociationsRpcResult<null>>;
|
|
855
|
+
setPinned(entityType: string, entityId: string, isPinned: boolean): Promise<AssociationsRpcResult<null>>;
|
|
856
|
+
setHidden(entityType: string, entityId: string, isHidden: boolean): Promise<AssociationsRpcResult<null>>;
|
|
857
|
+
list(kind?: UserStateKind): Promise<AssociationsRpcResult<{
|
|
858
|
+
items: UserEntityState[];
|
|
859
|
+
}>>;
|
|
860
|
+
getBulk(entityType: string, entityIds: string[]): Promise<AssociationsRpcResult<{
|
|
861
|
+
items: UserEntityState[];
|
|
862
|
+
}>>;
|
|
863
|
+
touch(entityType: string, entityId: string): Promise<AssociationsRpcResult<null>>;
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
interface CandidateRecord {
|
|
867
|
+
id: string;
|
|
868
|
+
title: string;
|
|
869
|
+
}
|
|
870
|
+
interface ListCandidatesArgs {
|
|
871
|
+
token: EntityTypeToken;
|
|
872
|
+
/** Scope to this owner's rows when the entity declares an owner column. */
|
|
873
|
+
ownerId?: string | null;
|
|
874
|
+
/** Case-insensitive title filter. */
|
|
875
|
+
search?: string;
|
|
876
|
+
limit?: number;
|
|
877
|
+
}
|
|
878
|
+
type CandidatesResult = {
|
|
879
|
+
ok: true;
|
|
880
|
+
data: CandidateRecord[];
|
|
881
|
+
} | {
|
|
882
|
+
ok: false;
|
|
883
|
+
error: string;
|
|
884
|
+
};
|
|
885
|
+
interface UniversalCandidate extends CandidateRecord {
|
|
886
|
+
token: EntityTypeToken;
|
|
887
|
+
}
|
|
888
|
+
interface SearchAcrossTokensArgs {
|
|
889
|
+
/** Tokens to search. Defaults to every curated token in the registry. */
|
|
890
|
+
tokens?: EntityTypeToken[];
|
|
891
|
+
search: string;
|
|
892
|
+
ownerId?: string | null;
|
|
893
|
+
/** Cap per token — a universal search shows a few of everything. */
|
|
894
|
+
perTokenLimit?: number;
|
|
895
|
+
/** Max in-flight token queries. */
|
|
896
|
+
concurrency?: number;
|
|
897
|
+
}
|
|
898
|
+
interface ReferenceSearchCandidatesFn {
|
|
899
|
+
(args: {
|
|
900
|
+
p_token: string;
|
|
901
|
+
p_search?: string;
|
|
902
|
+
p_limit?: number;
|
|
903
|
+
p_ids?: string[];
|
|
904
|
+
}): Promise<{
|
|
905
|
+
data: Array<{
|
|
906
|
+
id: string;
|
|
907
|
+
title: string | null;
|
|
908
|
+
}>;
|
|
909
|
+
error: null;
|
|
910
|
+
} | {
|
|
911
|
+
data: null;
|
|
912
|
+
error: {
|
|
913
|
+
message: string;
|
|
914
|
+
};
|
|
915
|
+
}>;
|
|
916
|
+
}
|
|
917
|
+
interface CandidatesServiceApi {
|
|
918
|
+
/**
|
|
919
|
+
* The universal candidate reader RPC (`public.reference_search_candidates`)
|
|
920
|
+
* — shared by candidate search here and title resolution in titles.ts.
|
|
921
|
+
*/
|
|
922
|
+
callReferenceSearchCandidates: ReferenceSearchCandidatesFn;
|
|
923
|
+
listAssociationCandidates(args: ListCandidatesArgs): Promise<CandidatesResult>;
|
|
924
|
+
/**
|
|
925
|
+
* ONE search over EVERY listable entity type — the "attach anything from
|
|
926
|
+
* anywhere" primitive. Registry-driven client fan-out, capped and
|
|
927
|
+
* concurrency-limited. Per-token failures are screamed and skipped — one
|
|
928
|
+
* broken table never blanks the search.
|
|
929
|
+
*/
|
|
930
|
+
searchCandidatesAcrossTokens(args: SearchAcrossTokensArgs): Promise<UniversalCandidate[]>;
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
interface TitlesServiceApi {
|
|
934
|
+
/** Read the cache synchronously (for render paths after a fetch settled). */
|
|
935
|
+
get(token: string, id: string): string | null;
|
|
936
|
+
/**
|
|
937
|
+
* Push a known-fresh title into the cache (after a rename or a create), so
|
|
938
|
+
* surfaces that resolve through this service never show a stale name.
|
|
939
|
+
*/
|
|
940
|
+
prime(token: string, id: string, title: string): void;
|
|
941
|
+
/** Display fallback when no label and no fetched title exist. */
|
|
942
|
+
fallback(token: string): string;
|
|
943
|
+
/**
|
|
944
|
+
* Resolve titles for `ids` of one token. Returns ONLY the resolved entries
|
|
945
|
+
* (cache + fresh reads); missing rows (deleted, no access) stay absent.
|
|
946
|
+
*/
|
|
947
|
+
fetch(token: string, ids: string[]): Promise<Map<string, string>>;
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
type EntityRowResult = {
|
|
951
|
+
ok: true;
|
|
952
|
+
data: {
|
|
953
|
+
id: string;
|
|
954
|
+
title: string;
|
|
955
|
+
};
|
|
956
|
+
} | {
|
|
957
|
+
ok: false;
|
|
958
|
+
error: string;
|
|
959
|
+
};
|
|
960
|
+
interface CreateEntityRowArgs {
|
|
961
|
+
/** The new row's human name — written to the registry `titleColumn`. */
|
|
962
|
+
title: string;
|
|
963
|
+
/** Org to stamp (skipped when the token has no org column). */
|
|
964
|
+
orgId?: string | null;
|
|
965
|
+
/** Required NOT NULL columns the registry conventions can't know about. */
|
|
966
|
+
extraColumns?: Record<string, unknown>;
|
|
967
|
+
}
|
|
968
|
+
interface EntityRowsServiceApi {
|
|
969
|
+
createEntityRow(token: EntityTypeToken, args: CreateEntityRowArgs): Promise<EntityRowResult>;
|
|
970
|
+
renameEntityRow(token: EntityTypeToken, id: string, title: string): Promise<{
|
|
971
|
+
ok: true;
|
|
972
|
+
} | {
|
|
973
|
+
ok: false;
|
|
974
|
+
error: string;
|
|
975
|
+
}>;
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
/** A typed reference to a single row — `{ type, id }`. */
|
|
979
|
+
interface EntityRef {
|
|
980
|
+
type: EntityTypeToken;
|
|
981
|
+
id: string;
|
|
982
|
+
}
|
|
983
|
+
/** A container reference — the deliberate set an edge may point at. */
|
|
984
|
+
interface ContainerRef {
|
|
985
|
+
type: AssociationTargetType;
|
|
986
|
+
id: string;
|
|
987
|
+
}
|
|
988
|
+
/** Per-edge attributes shared by the link helpers. */
|
|
989
|
+
interface EdgeAttrs {
|
|
990
|
+
orgId?: string;
|
|
991
|
+
label?: string;
|
|
992
|
+
metadata?: unknown;
|
|
993
|
+
role?: string;
|
|
994
|
+
position?: number;
|
|
995
|
+
}
|
|
996
|
+
/** One fully-specified edge for {@link AssociationHelpersApi.linkEdges}. */
|
|
997
|
+
interface EdgeSpec extends EdgeAttrs {
|
|
998
|
+
source: EntityRef;
|
|
999
|
+
target: ContainerRef;
|
|
1000
|
+
}
|
|
1001
|
+
interface AssociationHelpersApi {
|
|
1002
|
+
/**
|
|
1003
|
+
* Add an arbitrary batch of edges in one call (idempotent per edge).
|
|
1004
|
+
* Best-effort: every edge is attempted; the result is `ok` with the
|
|
1005
|
+
* created ids only when ALL succeed, otherwise `err` whose `detail` lists
|
|
1006
|
+
* every failure (the edges that DID succeed remain applied — re-running is
|
|
1007
|
+
* safe via ON CONFLICT).
|
|
1008
|
+
*/
|
|
1009
|
+
linkEdges(edges: EdgeSpec[]): Promise<AssociationsRpcResult<{
|
|
1010
|
+
ids: string[];
|
|
1011
|
+
}>>;
|
|
1012
|
+
/** Attach ONE source to MANY containers in a single shot. */
|
|
1013
|
+
linkOneToMany(args: {
|
|
1014
|
+
source: EntityRef;
|
|
1015
|
+
targets: ContainerRef[];
|
|
1016
|
+
attrs?: EdgeAttrs;
|
|
1017
|
+
}): Promise<AssociationsRpcResult<{
|
|
1018
|
+
ids: string[];
|
|
1019
|
+
}>>;
|
|
1020
|
+
/** Attach MANY sources to ONE container in a single shot. */
|
|
1021
|
+
linkManyToOne(args: {
|
|
1022
|
+
sources: EntityRef[];
|
|
1023
|
+
target: ContainerRef;
|
|
1024
|
+
attrs?: EdgeAttrs;
|
|
1025
|
+
}): Promise<AssociationsRpcResult<{
|
|
1026
|
+
ids: string[];
|
|
1027
|
+
}>>;
|
|
1028
|
+
/**
|
|
1029
|
+
* REPLACE the full set of a source's edges of one container type (adds
|
|
1030
|
+
* missing, removes extras) in one DB transaction — the set-semantics
|
|
1031
|
+
* one-shot. Thin, named pass-through to `assoc_set_targets`.
|
|
1032
|
+
*/
|
|
1033
|
+
replaceTargets(args: {
|
|
1034
|
+
source: EntityRef;
|
|
1035
|
+
targetType: AssociationTargetType;
|
|
1036
|
+
targetIds: string[];
|
|
1037
|
+
orgId?: string;
|
|
1038
|
+
role?: string;
|
|
1039
|
+
}): Promise<AssociationsRpcResult<null>>;
|
|
1040
|
+
/**
|
|
1041
|
+
* Wire edges onto a JUST-CREATED entity. The caller inserts its own row
|
|
1042
|
+
* (entity tables are feature-owned), then passes the new id here to attach
|
|
1043
|
+
* it to any number of containers (orphan-on-partial-fail is harmless and
|
|
1044
|
+
* re-runnable). `created` is the new entity; it becomes the edges' SOURCE.
|
|
1045
|
+
*/
|
|
1046
|
+
linkCreated(args: {
|
|
1047
|
+
created: EntityRef;
|
|
1048
|
+
targets: ContainerRef[];
|
|
1049
|
+
attrs?: EdgeAttrs;
|
|
1050
|
+
}): Promise<AssociationsRpcResult<{
|
|
1051
|
+
ids: string[];
|
|
1052
|
+
}>>;
|
|
1053
|
+
/** Remove an arbitrary batch of edges (best-effort; no-op per missing edge). */
|
|
1054
|
+
unlinkEdges(edges: {
|
|
1055
|
+
source: EntityRef;
|
|
1056
|
+
target: ContainerRef;
|
|
1057
|
+
role?: string;
|
|
1058
|
+
}[]): Promise<AssociationsRpcResult<null>>;
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
interface AssociationWriteResult {
|
|
1062
|
+
ok: boolean;
|
|
1063
|
+
/** Set on a successful single-edge `add`. */
|
|
1064
|
+
id?: string;
|
|
1065
|
+
error?: string;
|
|
1066
|
+
}
|
|
1067
|
+
interface CategoryMutationResult {
|
|
1068
|
+
ok: boolean;
|
|
1069
|
+
/** Set on a successful mutation. */
|
|
1070
|
+
id?: string;
|
|
1071
|
+
error?: string;
|
|
1072
|
+
}
|
|
1073
|
+
interface AssociationsStore {
|
|
1074
|
+
/** Stable, sync read of one endpoint's entry (idle default when uncached). */
|
|
1075
|
+
getEdges(type: string, id: string): AssociationsEntry;
|
|
1076
|
+
/**
|
|
1077
|
+
* Lazy load of every edge touching `${type}:${id}` (both directions).
|
|
1078
|
+
* Deduped per key; `status === "ready"` short-circuits unless `force`.
|
|
1079
|
+
*/
|
|
1080
|
+
load(type: string, id: string, opts?: {
|
|
1081
|
+
force?: boolean;
|
|
1082
|
+
}): Promise<void>;
|
|
1083
|
+
/** External-store contract: notified whenever the key's entry changes. */
|
|
1084
|
+
subscribe(key: string, cb: () => void): () => void;
|
|
1085
|
+
/** Attach source → target; on success reloads BOTH endpoints. */
|
|
1086
|
+
add(args: {
|
|
1087
|
+
sourceType: string;
|
|
1088
|
+
sourceId: string;
|
|
1089
|
+
targetType: AssociationTargetType;
|
|
1090
|
+
targetId: string;
|
|
1091
|
+
orgId?: string;
|
|
1092
|
+
label?: string;
|
|
1093
|
+
role?: string;
|
|
1094
|
+
metadata?: unknown;
|
|
1095
|
+
replaceMetadata?: boolean;
|
|
1096
|
+
}): Promise<AssociationWriteResult>;
|
|
1097
|
+
/** Detach source → target; on success reloads BOTH endpoints. */
|
|
1098
|
+
remove(args: {
|
|
1099
|
+
sourceType: string;
|
|
1100
|
+
sourceId: string;
|
|
1101
|
+
targetType: string;
|
|
1102
|
+
targetId: string;
|
|
1103
|
+
role?: string;
|
|
1104
|
+
}): Promise<AssociationWriteResult>;
|
|
1105
|
+
/** Replace the source's `targetType` edge set; reloads the SOURCE. */
|
|
1106
|
+
setTargets(args: {
|
|
1107
|
+
sourceType: string;
|
|
1108
|
+
sourceId: string;
|
|
1109
|
+
targetType: AssociationTargetType;
|
|
1110
|
+
targetIds: string[];
|
|
1111
|
+
orgId?: string;
|
|
1112
|
+
role?: string;
|
|
1113
|
+
}): Promise<AssociationWriteResult>;
|
|
1114
|
+
/** Reset one endpoint to idle and notify its subscribers. */
|
|
1115
|
+
invalidate(type: string, id: string): void;
|
|
1116
|
+
/** Reset every association endpoint AND every category facet. */
|
|
1117
|
+
invalidateAll(): void;
|
|
1118
|
+
getCategories(dimension: CategoryDimension): CategoriesEntry;
|
|
1119
|
+
loadCategories(dimension: CategoryDimension, opts?: {
|
|
1120
|
+
force?: boolean;
|
|
1121
|
+
}): Promise<void>;
|
|
1122
|
+
subscribeCategories(dimension: CategoryDimension, cb: () => void): () => void;
|
|
1123
|
+
/** Create + echo-insert + authoritative force reload. Returns the new id. */
|
|
1124
|
+
createCategory(args: {
|
|
1125
|
+
dimension: CategoryDimension;
|
|
1126
|
+
name: string;
|
|
1127
|
+
orgId: string;
|
|
1128
|
+
parentId?: string | null;
|
|
1129
|
+
color?: string | null;
|
|
1130
|
+
icon?: string | null;
|
|
1131
|
+
slug?: string | null;
|
|
1132
|
+
}): Promise<CategoryMutationResult>;
|
|
1133
|
+
updateCategory(args: {
|
|
1134
|
+
dimension: CategoryDimension;
|
|
1135
|
+
id: string;
|
|
1136
|
+
name: string;
|
|
1137
|
+
slug: string | null;
|
|
1138
|
+
color: string | null;
|
|
1139
|
+
icon: string | null;
|
|
1140
|
+
position: number | null;
|
|
1141
|
+
}): Promise<CategoryMutationResult>;
|
|
1142
|
+
reparentCategory(args: {
|
|
1143
|
+
dimension: CategoryDimension;
|
|
1144
|
+
id: string;
|
|
1145
|
+
parentId: string | null;
|
|
1146
|
+
}): Promise<CategoryMutationResult>;
|
|
1147
|
+
deleteCategory(args: {
|
|
1148
|
+
dimension: CategoryDimension;
|
|
1149
|
+
id: string;
|
|
1150
|
+
}): Promise<CategoryMutationResult>;
|
|
1151
|
+
/** Batched title resolution + the session cache + prime. */
|
|
1152
|
+
titles: TitlesServiceApi;
|
|
1153
|
+
/** Per-user favorite/pinned/hidden state (`ues_*`). */
|
|
1154
|
+
favorites: FavoritesServiceApi;
|
|
1155
|
+
/** Candidate reads for the pickers. */
|
|
1156
|
+
candidates: CandidatesServiceApi;
|
|
1157
|
+
/** Generic registry-convention row create/rename. */
|
|
1158
|
+
entityRows: EntityRowsServiceApi;
|
|
1159
|
+
/** Composite link helpers over the chokepoint. */
|
|
1160
|
+
helpers: AssociationHelpersApi;
|
|
1161
|
+
/** The registry merge engine (generated metadata + host overlay). */
|
|
1162
|
+
registry: EntityRegistry;
|
|
1163
|
+
/**
|
|
1164
|
+
* The raw chokepoint services — every RPC family, results-enveloped.
|
|
1165
|
+
* `associations` writes here do NOT touch the cache; use the store-level
|
|
1166
|
+
* `add`/`remove`/`setTargets` when a cached surface must stay fresh.
|
|
1167
|
+
*/
|
|
1168
|
+
services: {
|
|
1169
|
+
associations: AssociationsServiceApi;
|
|
1170
|
+
categories: CategoriesServiceApi;
|
|
1171
|
+
};
|
|
1172
|
+
/** Merge more host overlay entries in (icons/routes/candidate loaders). */
|
|
1173
|
+
registerEntityOverlay: EntityRegistry["registerEntityOverlay"];
|
|
1174
|
+
/**
|
|
1175
|
+
* The bound scream seam (W3, additive): /react surfaces route their loud
|
|
1176
|
+
* recoveries here (the originals' console.error sites) without a second
|
|
1177
|
+
* sink binding. Same function the host passed at construction.
|
|
1178
|
+
*/
|
|
1179
|
+
errorSink: AssociationsConfig["errorSink"];
|
|
1180
|
+
/**
|
|
1181
|
+
* The bound identity port (W3, additive): /react hooks that FILTER by the
|
|
1182
|
+
* current user (candidate owner scoping) read it leniently; write paths
|
|
1183
|
+
* keep going through the services, where `requireUserId` failures stay
|
|
1184
|
+
* loud. Same object the host passed at construction.
|
|
1185
|
+
*/
|
|
1186
|
+
identity: AssociationsConfig["identity"];
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
interface AssociationsUiPorts {
|
|
1190
|
+
notifier?: AssociationsNotifier;
|
|
1191
|
+
windowShell?: WindowShellPort;
|
|
1192
|
+
capture?: CapturePort;
|
|
1193
|
+
pickerOverrides?: PickerOverrideMap;
|
|
1194
|
+
entityDoors?: EntityDoorsPort;
|
|
1195
|
+
}
|
|
1196
|
+
interface AssociationsProviderProps extends AssociationsUiPorts {
|
|
1197
|
+
/** The /core store the host constructed with `createAssociationsStore`. */
|
|
1198
|
+
store: AssociationsStore;
|
|
1199
|
+
children: ReactNode;
|
|
1200
|
+
}
|
|
1201
|
+
declare function AssociationsProvider({ store, notifier, windowShell, capture, pickerOverrides, entityDoors, children, }: AssociationsProviderProps): react.JSX.Element;
|
|
1202
|
+
/** The /core store bound by the nearest provider. Throws when unmounted. */
|
|
1203
|
+
declare function useAssociationsStore(): AssociationsStore;
|
|
1204
|
+
/** The five UI ports the host bound (each optional, each degradable). */
|
|
1205
|
+
declare function useAssociationsUiPorts(): AssociationsUiPorts;
|
|
1206
|
+
/**
|
|
1207
|
+
* The notifier, degraded per contract: absent → warn once via errorSink,
|
|
1208
|
+
* then route every user-facing failure to the errorSink so no outcome is
|
|
1209
|
+
* silent. Success messages without a notifier are dropped (the surface's own
|
|
1210
|
+
* state change is the confirmation); failures always scream.
|
|
1211
|
+
*/
|
|
1212
|
+
declare function useNotifier(): AssociationsNotifier;
|
|
1213
|
+
|
|
1214
|
+
interface UseAssociationsArgs {
|
|
1215
|
+
/** The entity whose relationships to read/manage (the cache endpoint). */
|
|
1216
|
+
type: string;
|
|
1217
|
+
id: string | null;
|
|
1218
|
+
/** Disable the auto-load on mount. Defaults to false (auto-load). */
|
|
1219
|
+
autoLoad?: boolean;
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
interface UseAssociationsReturn {
|
|
1223
|
+
/** Every edge touching this entity, both directions. */
|
|
1224
|
+
edges: AssociationEdge[];
|
|
1225
|
+
status: AssociationsEntry["status"];
|
|
1226
|
+
error: string | null;
|
|
1227
|
+
fetchedAt: number | null;
|
|
1228
|
+
/** Attach this entity (as source) → a target. */
|
|
1229
|
+
add: (args: {
|
|
1230
|
+
targetType: AssociationTargetType;
|
|
1231
|
+
targetId: string;
|
|
1232
|
+
orgId?: string;
|
|
1233
|
+
label?: string;
|
|
1234
|
+
/** Typed edge role (e.g. 'theme' for a folder/tag) — omit for a role-less edge. */
|
|
1235
|
+
role?: string;
|
|
1236
|
+
}) => Promise<AssociationWriteResult>;
|
|
1237
|
+
/** Detach this entity (as source) → a target. */
|
|
1238
|
+
remove: (args: {
|
|
1239
|
+
targetType: string;
|
|
1240
|
+
targetId: string;
|
|
1241
|
+
role?: string;
|
|
1242
|
+
}) => Promise<AssociationWriteResult>;
|
|
1243
|
+
/** Replace this entity's edges of one target type with exactly `targetIds`. */
|
|
1244
|
+
setTargets: (args: {
|
|
1245
|
+
targetType: AssociationTargetType;
|
|
1246
|
+
targetIds: string[];
|
|
1247
|
+
orgId?: string;
|
|
1248
|
+
role?: string;
|
|
1249
|
+
}) => Promise<AssociationWriteResult>;
|
|
1250
|
+
/** Force a refetch of this entity's edges. */
|
|
1251
|
+
reload: () => Promise<void>;
|
|
1252
|
+
}
|
|
1253
|
+
declare function useAssociations(args: UseAssociationsArgs): UseAssociationsReturn;
|
|
1254
|
+
/**
|
|
1255
|
+
* Convenience alias — same hook, a name that reads naturally on relationship
|
|
1256
|
+
* surfaces ("the things this entity is related to"). Identical contract.
|
|
1257
|
+
*/
|
|
1258
|
+
declare const useEntityRelationships: typeof useAssociations;
|
|
1259
|
+
|
|
1260
|
+
interface ContainerLink {
|
|
1261
|
+
/** The edge id (for keys / removal). */
|
|
1262
|
+
edgeId: string;
|
|
1263
|
+
/** The attached resource's id (the edge source). */
|
|
1264
|
+
resourceId: string;
|
|
1265
|
+
/** The attached resource's entity token (the edge source type). */
|
|
1266
|
+
token: string;
|
|
1267
|
+
/** The edge role, or null for a plain (role-less) association. */
|
|
1268
|
+
role: string | null;
|
|
1269
|
+
label: string | null;
|
|
1270
|
+
/** Per-edge props from `platform.associations.metadata` (e.g. representation). */
|
|
1271
|
+
metadata: unknown;
|
|
1272
|
+
}
|
|
1273
|
+
interface UseContainerLinksArgs {
|
|
1274
|
+
/** The primary entity — always an association TARGET (container). */
|
|
1275
|
+
containerType: AssociationTargetType;
|
|
1276
|
+
containerId: string | null;
|
|
1277
|
+
/** Org to stamp on new edges (for org-scoped RLS / counts). */
|
|
1278
|
+
orgId?: string | null;
|
|
1279
|
+
}
|
|
1280
|
+
interface UseContainerLinksReturn {
|
|
1281
|
+
status: ReturnType<typeof useAssociations>["status"];
|
|
1282
|
+
error: string | null;
|
|
1283
|
+
reload: () => Promise<void>;
|
|
1284
|
+
/** Total attached resources across every token (all incoming edges). */
|
|
1285
|
+
totalCount: number;
|
|
1286
|
+
/** Live count of attached resources of `token`. */
|
|
1287
|
+
countFor: (token: EntityTypeToken) => number;
|
|
1288
|
+
/** Ids of resources of `token` already attached (for picker "attached" state). */
|
|
1289
|
+
attachedIdsFor: (token: EntityTypeToken) => Set<string>;
|
|
1290
|
+
/** Full link rows of `token` (for listing/removal). */
|
|
1291
|
+
linksFor: (token: EntityTypeToken) => ContainerLink[];
|
|
1292
|
+
/** Attach a resource (source) to this container (target). */
|
|
1293
|
+
attach: (token: EntityTypeToken, resourceId: string, label?: string, metadata?: unknown, options?: {
|
|
1294
|
+
replaceMetadata?: boolean;
|
|
1295
|
+
/**
|
|
1296
|
+
* Semantic edge role (`platform.associations.role`) — e.g. the
|
|
1297
|
+
* Masterwork dump surface stamps `distillation_source`. Omitted = the
|
|
1298
|
+
* canonical role-less edge. Detach with the SAME role to remove it.
|
|
1299
|
+
*/
|
|
1300
|
+
role?: string;
|
|
1301
|
+
}) => Promise<AssociationWriteResult>;
|
|
1302
|
+
/** Detach a resource from this container. */
|
|
1303
|
+
detach: (token: EntityTypeToken, resourceId: string, role?: string) => Promise<AssociationWriteResult>;
|
|
1304
|
+
}
|
|
1305
|
+
declare function useContainerLinks(args: UseContainerLinksArgs): UseContainerLinksReturn;
|
|
1306
|
+
|
|
1307
|
+
interface EntityTitleRef {
|
|
1308
|
+
token: string;
|
|
1309
|
+
id: string;
|
|
1310
|
+
/** The edge label (or any already-known title) — wins when present. */
|
|
1311
|
+
label?: string | null;
|
|
1312
|
+
}
|
|
1313
|
+
interface UseEntityTitlesReturn {
|
|
1314
|
+
/** Resolve the display title for one ref (never a UUID). */
|
|
1315
|
+
titleFor: (ref: EntityTitleRef) => string;
|
|
1316
|
+
/**
|
|
1317
|
+
* True when this ref's target could NOT be resolved after a settled fetch —
|
|
1318
|
+
* the row is gone or the viewer has no access, and `titleFor` is returning a
|
|
1319
|
+
* generic fallback. Surfaces MUST render this loudly (and offer the detach).
|
|
1320
|
+
* Always false for tokens with no registered title column (nothing to
|
|
1321
|
+
* resolve there — silence is correct, not a failure).
|
|
1322
|
+
*/
|
|
1323
|
+
isUnresolved: (ref: EntityTitleRef) => boolean;
|
|
1324
|
+
/** True while any needed titles are still being fetched. */
|
|
1325
|
+
loading: boolean;
|
|
1326
|
+
}
|
|
1327
|
+
declare function useEntityTitles(refs: EntityTitleRef[]): UseEntityTitlesReturn;
|
|
1328
|
+
|
|
1329
|
+
/** Same shape as a mutation result; the create carries the new id. */
|
|
1330
|
+
type CategoryCreateResult = CategoryMutationResult;
|
|
1331
|
+
|
|
1332
|
+
interface UseCategoriesArgs {
|
|
1333
|
+
/** The facet to read/manage (`agent-shortcut`, `skill`, `industry`, …). */
|
|
1334
|
+
dimension: CategoryDimension | null;
|
|
1335
|
+
/** Disable the auto-load on mount. Defaults to false (auto-load). */
|
|
1336
|
+
autoLoad?: boolean;
|
|
1337
|
+
}
|
|
1338
|
+
interface UseCategoriesReturn {
|
|
1339
|
+
/** Every category visible to the caller in this facet (system + their orgs). */
|
|
1340
|
+
categories: PlatformCategory[];
|
|
1341
|
+
status: CategoriesEntry["status"];
|
|
1342
|
+
error: string | null;
|
|
1343
|
+
fetchedAt: number | null;
|
|
1344
|
+
/** Create an org category in this facet. Returns the new id on success. */
|
|
1345
|
+
create: (args: {
|
|
1346
|
+
name: string;
|
|
1347
|
+
orgId: string;
|
|
1348
|
+
parentId?: string | null;
|
|
1349
|
+
color?: string | null;
|
|
1350
|
+
icon?: string | null;
|
|
1351
|
+
slug?: string | null;
|
|
1352
|
+
}) => Promise<CategoryCreateResult>;
|
|
1353
|
+
/** Replace one category's editable scalar fields. */
|
|
1354
|
+
update: (args: {
|
|
1355
|
+
id: string;
|
|
1356
|
+
name: string;
|
|
1357
|
+
slug: string | null;
|
|
1358
|
+
color: string | null;
|
|
1359
|
+
icon: string | null;
|
|
1360
|
+
position: number | null;
|
|
1361
|
+
}) => Promise<CategoryMutationResult>;
|
|
1362
|
+
/** Move a category to the root or directly under a root category. */
|
|
1363
|
+
reparent: (id: string, parentId: string | null) => Promise<CategoryMutationResult>;
|
|
1364
|
+
/** Soft-delete a leaf category. */
|
|
1365
|
+
remove: (id: string) => Promise<CategoryMutationResult>;
|
|
1366
|
+
/** Force a refetch of this facet's categories. */
|
|
1367
|
+
reload: () => Promise<void>;
|
|
1368
|
+
}
|
|
1369
|
+
declare function useCategories(args: UseCategoriesArgs): UseCategoriesReturn;
|
|
1370
|
+
|
|
1371
|
+
interface UseUniversalEntitySearchArgs {
|
|
1372
|
+
query: string;
|
|
1373
|
+
/** Restrict to these tokens; defaults to every listable token. */
|
|
1374
|
+
tokens?: EntityTypeToken[];
|
|
1375
|
+
/** Owner filter for the per-token candidate reads. */
|
|
1376
|
+
ownerId?: string | null;
|
|
1377
|
+
enabled?: boolean;
|
|
1378
|
+
perTokenLimit?: number;
|
|
1379
|
+
/**
|
|
1380
|
+
* What an empty query loads. Universal attach surfaces default to recents;
|
|
1381
|
+
* constrained value pickers use candidates so opening the picker immediately
|
|
1382
|
+
* shows the records that are available to select.
|
|
1383
|
+
*/
|
|
1384
|
+
emptyQueryMode?: "recents" | "candidates";
|
|
1385
|
+
}
|
|
1386
|
+
interface UseUniversalEntitySearchReturn {
|
|
1387
|
+
results: UniversalCandidate[];
|
|
1388
|
+
/** True while the current query's sweep is in flight. */
|
|
1389
|
+
loading: boolean;
|
|
1390
|
+
/** True when `results` are recents (empty query), not search hits. */
|
|
1391
|
+
isRecents: boolean;
|
|
1392
|
+
}
|
|
1393
|
+
declare function useUniversalEntitySearch(args: UseUniversalEntitySearchArgs): UseUniversalEntitySearchReturn;
|
|
1394
|
+
|
|
1395
|
+
interface UseAssociationCandidatesArgs {
|
|
1396
|
+
token: EntityTypeToken;
|
|
1397
|
+
/** Skip fetching (e.g. while the picker is closed). Defaults to true. */
|
|
1398
|
+
enabled?: boolean;
|
|
1399
|
+
search?: string;
|
|
1400
|
+
limit?: number;
|
|
1401
|
+
}
|
|
1402
|
+
interface UseAssociationCandidatesReturn {
|
|
1403
|
+
candidates: CandidateRecord[];
|
|
1404
|
+
loading: boolean;
|
|
1405
|
+
error: string | null;
|
|
1406
|
+
reload: () => void;
|
|
1407
|
+
}
|
|
1408
|
+
declare function useAssociationCandidates(args: UseAssociationCandidatesArgs): UseAssociationCandidatesReturn;
|
|
1409
|
+
|
|
1410
|
+
interface AssociationEntitySelectItem {
|
|
1411
|
+
id: string;
|
|
1412
|
+
title: string;
|
|
1413
|
+
}
|
|
1414
|
+
/**
|
|
1415
|
+
* The read/write seam of the association "name dropdown". This hook is the
|
|
1416
|
+
* default (plain associations container); surfaces with bespoke active/create
|
|
1417
|
+
* semantics implement it themselves — same pattern as AssociationList's
|
|
1418
|
+
* ContainerResourcesAdapter.
|
|
1419
|
+
*/
|
|
1420
|
+
interface AssociationEntitySelectAdapter {
|
|
1421
|
+
/** True while the association list is still hydrating. */
|
|
1422
|
+
loading: boolean;
|
|
1423
|
+
/** Every entity of this token associated with the container. */
|
|
1424
|
+
items: AssociationEntitySelectItem[];
|
|
1425
|
+
activeId: string | null;
|
|
1426
|
+
setActive: (id: string) => void | Promise<unknown>;
|
|
1427
|
+
/**
|
|
1428
|
+
* Create a new entity named `title`, associate it to the container, and
|
|
1429
|
+
* make it active. Resolves to the new id, or null on failure (the adapter
|
|
1430
|
+
* reports its own error detail; the component toasts generically).
|
|
1431
|
+
* Omit when creation isn't name-driven — pass `createSlot` on the component
|
|
1432
|
+
* instead (e.g. a conversation is created by PICKING AN AGENT, not naming).
|
|
1433
|
+
*/
|
|
1434
|
+
createAndAttach?: (title: string) => Promise<string | null>;
|
|
1435
|
+
/** Rename the entity (its real title column). Resolves false on failure. */
|
|
1436
|
+
rename: (id: string, title: string) => Promise<boolean>;
|
|
1437
|
+
/** Optional: unlink an entity from the container (never deletes the row). */
|
|
1438
|
+
detach?: (id: string) => Promise<unknown>;
|
|
1439
|
+
}
|
|
1440
|
+
interface UseAssociationEntitySelectAdapterArgs {
|
|
1441
|
+
token: EntityTypeToken;
|
|
1442
|
+
/** The container the entities are associated with (always the edge TARGET). */
|
|
1443
|
+
container: {
|
|
1444
|
+
type: AssociationTargetType;
|
|
1445
|
+
id: string | null;
|
|
1446
|
+
orgId?: string | null;
|
|
1447
|
+
};
|
|
1448
|
+
/** Controlled active selection; omit to default to the first attached row. */
|
|
1449
|
+
activeId?: string | null;
|
|
1450
|
+
onActiveChange?: (id: string) => void | Promise<unknown>;
|
|
1451
|
+
/** NOT NULL columns the registry conventions can't know (create only). */
|
|
1452
|
+
createColumns?: Record<string, unknown>;
|
|
1453
|
+
}
|
|
1454
|
+
declare function useAssociationEntitySelectAdapter(args: UseAssociationEntitySelectAdapterArgs): AssociationEntitySelectAdapter;
|
|
1455
|
+
|
|
1456
|
+
/** The primary (container) entity a surface is anchored to. */
|
|
1457
|
+
interface PrimaryEntity {
|
|
1458
|
+
/** Container token — must be an association TARGET type. */
|
|
1459
|
+
type: AssociationTargetType;
|
|
1460
|
+
id: string;
|
|
1461
|
+
/** Org to stamp on edges created here (org-scoped RLS / counts). */
|
|
1462
|
+
orgId?: string | null;
|
|
1463
|
+
/** Human label for headings (e.g. the org/scope name). */
|
|
1464
|
+
label?: string;
|
|
1465
|
+
}
|
|
1466
|
+
declare function PrimaryEntityProvider({ value, children, }: {
|
|
1467
|
+
value: PrimaryEntity;
|
|
1468
|
+
children: ReactNode;
|
|
1469
|
+
}): react.JSX.Element;
|
|
1470
|
+
/** Read the surrounding primary entity, or null when unprovided. */
|
|
1471
|
+
declare function usePrimaryEntity(): PrimaryEntity | null;
|
|
1472
|
+
|
|
1473
|
+
interface AssociationWindowProps {
|
|
1474
|
+
/** Controls mount — callers should also gate their JSX on this. */
|
|
1475
|
+
open: boolean;
|
|
1476
|
+
onClose: () => void;
|
|
1477
|
+
/** Human-readable scope for the window id (debugging / tray labels). */
|
|
1478
|
+
scopeId: string;
|
|
1479
|
+
title: string;
|
|
1480
|
+
/** Small leading icon rendered beside the title. */
|
|
1481
|
+
icon?: ReactNode;
|
|
1482
|
+
/**
|
|
1483
|
+
* One-line context under the header ("Attached to Titanium Marketing").
|
|
1484
|
+
* A node, not a string, so the container it names can carry its own door
|
|
1485
|
+
* (THE DOOR LAW) instead of being an unreachable label.
|
|
1486
|
+
*/
|
|
1487
|
+
subtitle?: ReactNode;
|
|
1488
|
+
children: ReactNode;
|
|
1489
|
+
}
|
|
1490
|
+
declare function AssociationWindow({ open, onClose, scopeId, title, icon, subtitle, children, }: AssociationWindowProps): react.JSX.Element | null;
|
|
1491
|
+
|
|
1492
|
+
declare function AssociationPicker(props: AssociationPickerProps): react.JSX.Element | null;
|
|
1493
|
+
interface AssociationCandidateBodyProps {
|
|
1494
|
+
token: EntityTypeToken;
|
|
1495
|
+
/** Load candidates only while true (mirror of the surface's `open`). */
|
|
1496
|
+
enabled: boolean;
|
|
1497
|
+
/** Org stamped onto rows created by the "+ New" footer. */
|
|
1498
|
+
orgId?: string | null | undefined;
|
|
1499
|
+
attachedIds: Set<string>;
|
|
1500
|
+
onAttach: (resourceId: string, title: string) => Promise<{
|
|
1501
|
+
ok: boolean;
|
|
1502
|
+
error?: string;
|
|
1503
|
+
}>;
|
|
1504
|
+
onDetach: (resourceId: string) => Promise<{
|
|
1505
|
+
ok: boolean;
|
|
1506
|
+
error?: string;
|
|
1507
|
+
}>;
|
|
1508
|
+
/** Wired to a per-token browse surface's back affordance. */
|
|
1509
|
+
onClose?: () => void;
|
|
1510
|
+
}
|
|
1511
|
+
/**
|
|
1512
|
+
* The attach/detach body for ONE token — reused by the picker sheet and by
|
|
1513
|
+
* `UniversalAssociationPicker`'s per-token browse mode. Tokens with a
|
|
1514
|
+
* host-registered picker override are routed at the PICKER level (windowed
|
|
1515
|
+
* override component); this body is always the generic registry-driven list.
|
|
1516
|
+
*/
|
|
1517
|
+
declare function AssociationCandidateBody({ token, enabled, orgId, attachedIds, onAttach, onDetach, onClose, }: AssociationCandidateBodyProps): react.JSX.Element;
|
|
1518
|
+
|
|
1519
|
+
interface UniversalAssociationPickerProps {
|
|
1520
|
+
/** Tokens offered. Defaults to every listable token. */
|
|
1521
|
+
tokens?: EntityTypeToken[];
|
|
1522
|
+
/** Ids already attached, keyed `${token}:${id}` — rendered as attached. */
|
|
1523
|
+
attachedKeys: Set<string>;
|
|
1524
|
+
onAttach: (token: EntityTypeToken, resourceId: string, title: string) => Promise<{
|
|
1525
|
+
ok: boolean;
|
|
1526
|
+
error?: string;
|
|
1527
|
+
}>;
|
|
1528
|
+
onDetach: (token: EntityTypeToken, resourceId: string) => Promise<{
|
|
1529
|
+
ok: boolean;
|
|
1530
|
+
error?: string;
|
|
1531
|
+
}>;
|
|
1532
|
+
/** Owner filter for candidate reads (defaults to RLS-only). */
|
|
1533
|
+
ownerId?: string | null;
|
|
1534
|
+
/** Org stamped onto rows created via the per-token "+ New" footer. */
|
|
1535
|
+
orgId?: string | null;
|
|
1536
|
+
className?: string;
|
|
1537
|
+
}
|
|
1538
|
+
declare function attachedKey(token: string, id: string): string;
|
|
1539
|
+
declare function UniversalAssociationPicker(props: UniversalAssociationPickerProps): react.JSX.Element;
|
|
1540
|
+
|
|
1541
|
+
interface AttachedItemsSheetProps {
|
|
1542
|
+
open: boolean;
|
|
1543
|
+
onOpenChange: (open: boolean) => void;
|
|
1544
|
+
token: EntityTypeToken;
|
|
1545
|
+
containerLabel?: string;
|
|
1546
|
+
/**
|
|
1547
|
+
* The container these items are attached to. When given, the "Attached to X"
|
|
1548
|
+
* line puts a door on X — this window can outlive the page it was opened
|
|
1549
|
+
* from, so its container reference must be reachable.
|
|
1550
|
+
*/
|
|
1551
|
+
container?: PrimaryEntity;
|
|
1552
|
+
links: ContainerLink[];
|
|
1553
|
+
/** Opens the attach picker. Omitted when the token cannot list candidates. */
|
|
1554
|
+
onAdd?: () => void;
|
|
1555
|
+
onDetach: (resourceId: string) => Promise<{
|
|
1556
|
+
ok: boolean;
|
|
1557
|
+
error?: string;
|
|
1558
|
+
}>;
|
|
1559
|
+
}
|
|
1560
|
+
declare function AttachedItemsSheet(props: AttachedItemsSheetProps): react.JSX.Element | null;
|
|
1561
|
+
|
|
1562
|
+
interface AssociationCardProps {
|
|
1563
|
+
/** The secondary entity kind this card manages (e.g. "task", "file"). */
|
|
1564
|
+
token: EntityTypeToken;
|
|
1565
|
+
/** Override the page's primary entity. Defaults to PrimaryEntityProvider. */
|
|
1566
|
+
container?: PrimaryEntity;
|
|
1567
|
+
className?: string;
|
|
1568
|
+
}
|
|
1569
|
+
declare function AssociationCard({ token, container: containerProp, className, }: AssociationCardProps): react.JSX.Element | null;
|
|
1570
|
+
|
|
1571
|
+
interface AssociationCardGridProps {
|
|
1572
|
+
/** Tokens to show. Defaults to every registry-listable token. */
|
|
1573
|
+
tokens?: EntityTypeToken[];
|
|
1574
|
+
/** Registry tokens this surface cannot honestly support yet. */
|
|
1575
|
+
excludeTokens?: EntityTypeToken[];
|
|
1576
|
+
className?: string;
|
|
1577
|
+
}
|
|
1578
|
+
declare function AssociationCardGrid({ tokens, excludeTokens, className, }: AssociationCardGridProps): react.JSX.Element;
|
|
1579
|
+
|
|
1580
|
+
/** One attached resource, as the list renders it. Tokens are CANONICAL. */
|
|
1581
|
+
interface ContainerResourceRow {
|
|
1582
|
+
/** Stable row key (edge id or `${token}:${id}`). */
|
|
1583
|
+
key: string;
|
|
1584
|
+
token: string;
|
|
1585
|
+
resourceId: string;
|
|
1586
|
+
label: string | null;
|
|
1587
|
+
/** Exact semantic edge role; null means the canonical role-less edge. */
|
|
1588
|
+
role?: string | null;
|
|
1589
|
+
/** Pinned rows sort first inside their token group. */
|
|
1590
|
+
pinned?: boolean;
|
|
1591
|
+
/** False for inherited rows (e.g. via a thread's anchor) — no detach. */
|
|
1592
|
+
removable: boolean;
|
|
1593
|
+
/** Small annotation for non-removable rows ("via anchor"). */
|
|
1594
|
+
originNote?: string | null;
|
|
1595
|
+
/** Resolvable records that contributed an inherited row. */
|
|
1596
|
+
originRefs?: readonly {
|
|
1597
|
+
token: EntityTypeToken;
|
|
1598
|
+
id: string;
|
|
1599
|
+
label: string;
|
|
1600
|
+
}[];
|
|
1601
|
+
}
|
|
1602
|
+
interface ContainerResourcesAdapter {
|
|
1603
|
+
status: "idle" | "loading" | "ready" | "error";
|
|
1604
|
+
error: string | null;
|
|
1605
|
+
reload: () => void | Promise<void>;
|
|
1606
|
+
rows: ContainerResourceRow[];
|
|
1607
|
+
attach: (token: EntityTypeToken, resourceId: string, title?: string,
|
|
1608
|
+
/**
|
|
1609
|
+
* Extra edge metadata stamped at attach time (label-at-attach-time's
|
|
1610
|
+
* sibling contract). Adapters without metadata support may ignore it.
|
|
1611
|
+
*/
|
|
1612
|
+
opts?: {
|
|
1613
|
+
metadata?: Record<string, unknown> | null;
|
|
1614
|
+
}) => Promise<{
|
|
1615
|
+
ok: boolean;
|
|
1616
|
+
error?: string;
|
|
1617
|
+
}>;
|
|
1618
|
+
detach: (token: EntityTypeToken, resourceId: string, role?: string) => Promise<{
|
|
1619
|
+
ok: boolean;
|
|
1620
|
+
error?: string;
|
|
1621
|
+
}>;
|
|
1622
|
+
/**
|
|
1623
|
+
* Optional pin capability (edge `metadata.pinned`) — pinned resources stay
|
|
1624
|
+
* inline in agent context at every tier. Rows show a pin toggle when set.
|
|
1625
|
+
*/
|
|
1626
|
+
setPinned?: (token: EntityTypeToken, resourceId: string, pinned: boolean) => Promise<{
|
|
1627
|
+
ok: boolean;
|
|
1628
|
+
error?: string;
|
|
1629
|
+
}>;
|
|
1630
|
+
}
|
|
1631
|
+
/** Default adapter — wraps `useContainerLinks` (org/scope/project pages). */
|
|
1632
|
+
declare function useContainerLinksAdapter(container: PrimaryEntity | null, tokens?: readonly EntityTypeToken[]): ContainerResourcesAdapter;
|
|
1633
|
+
interface AssociationListProps {
|
|
1634
|
+
/** Container override; defaults to the surrounding PrimaryEntityProvider. */
|
|
1635
|
+
container?: PrimaryEntity;
|
|
1636
|
+
/** Write/read override (war-room threads etc.). Default: useContainerLinks. */
|
|
1637
|
+
adapter?: ContainerResourcesAdapter;
|
|
1638
|
+
/** Restrict display + attach to these tokens (e.g. one dynamic tab). */
|
|
1639
|
+
tokens?: EntityTypeToken[];
|
|
1640
|
+
/** `full` = role sections + universal search; `compact` = flat token groups. */
|
|
1641
|
+
variant?: "full" | "compact";
|
|
1642
|
+
/** Extra per-token actions (e.g. war-room Upload / New document). */
|
|
1643
|
+
renderSectionActions?: (token: EntityTypeToken) => ReactNode;
|
|
1644
|
+
/** Open a resource. Default: registry `hrefFor` in a new tab. */
|
|
1645
|
+
openEntity?: (token: string, id: string) => void;
|
|
1646
|
+
/**
|
|
1647
|
+
* Per-token row override (return null/undefined to keep the default row) —
|
|
1648
|
+
* for rows that need richer rendering than icon+title. The override owns the
|
|
1649
|
+
* whole row; use `ctx` for the resolved title and the busy/detach/open
|
|
1650
|
+
* wiring.
|
|
1651
|
+
*/
|
|
1652
|
+
renderRow?: (row: ContainerResourceRow, ctx: {
|
|
1653
|
+
title: string;
|
|
1654
|
+
busy: boolean;
|
|
1655
|
+
onDetach: () => void;
|
|
1656
|
+
onOpen: () => void;
|
|
1657
|
+
}) => ReactNode | null | undefined;
|
|
1658
|
+
className?: string;
|
|
1659
|
+
}
|
|
1660
|
+
declare function AssociationList(props: AssociationListProps): react.JSX.Element;
|
|
1661
|
+
|
|
1662
|
+
type IconProps = SVGProps<SVGSVGElement>;
|
|
1663
|
+
/**
|
|
1664
|
+
* The default entity glyph for tokens with no host overlay icon (lucide
|
|
1665
|
+
* `Boxes` — the original registry's DEFAULT_ICON, now a /react concern
|
|
1666
|
+
* because /core ships `Icon: null`).
|
|
1667
|
+
*/
|
|
1668
|
+
declare function DefaultEntityIcon(props: IconProps): react.JSX.Element;
|
|
1669
|
+
|
|
1670
|
+
interface CaptureAttachResult {
|
|
1671
|
+
ok: boolean;
|
|
1672
|
+
/** Human error text — the toolbar screams it. Omit when the host already did. */
|
|
1673
|
+
error?: string;
|
|
1674
|
+
}
|
|
1675
|
+
/**
|
|
1676
|
+
* ONE write callback for every capture verb. Tokens are canonical
|
|
1677
|
+
* (`file` / `udt_document`); the host maps to its own write path (an
|
|
1678
|
+
* association edge, a thread thunk, …) and reports the outcome honestly —
|
|
1679
|
+
* a silent no-op attach is the bug class this contract kills.
|
|
1680
|
+
*/
|
|
1681
|
+
type CaptureAttach = (token: EntityTypeToken, resourceId: string, opts?: {
|
|
1682
|
+
label?: string;
|
|
1683
|
+
}) => Promise<CaptureAttachResult>;
|
|
1684
|
+
interface AssociationCaptureToolbarProps {
|
|
1685
|
+
attach: CaptureAttach;
|
|
1686
|
+
/** Logical cloud-files folder new uploads land in (auto-created). */
|
|
1687
|
+
uploadFolderPath: string;
|
|
1688
|
+
/** Visibility stamped on uploads. Default "personal". */
|
|
1689
|
+
uploadVisibility?: string;
|
|
1690
|
+
/**
|
|
1691
|
+
* Where a created-but-unlinked upload is reported to live, e.g.
|
|
1692
|
+
* "your Files (War Room folder)". Keeps the loud-outcome copy honest.
|
|
1693
|
+
*/
|
|
1694
|
+
uploadLocationLabel: string;
|
|
1695
|
+
/** The retry verb named in loud-outcome copy. Default '"Add file"'. */
|
|
1696
|
+
attachRetryLabel?: string;
|
|
1697
|
+
/** Copy for the existing-files picker dialog. */
|
|
1698
|
+
filePicker?: {
|
|
1699
|
+
title?: string;
|
|
1700
|
+
description?: string;
|
|
1701
|
+
};
|
|
1702
|
+
/** Which built-in actions render (each ALSO gated on its port handler). */
|
|
1703
|
+
showActions?: {
|
|
1704
|
+
upload?: boolean;
|
|
1705
|
+
addFile?: boolean;
|
|
1706
|
+
newDocument?: boolean;
|
|
1707
|
+
};
|
|
1708
|
+
/** Hide the button row (compact variants) — drag-and-drop stays live. */
|
|
1709
|
+
showToolbar?: boolean;
|
|
1710
|
+
/** Extra host-specific buttons appended after the built-ins. */
|
|
1711
|
+
extraActions?: ReactNode;
|
|
1712
|
+
/** Open a freshly created document via the registry door. Default true. */
|
|
1713
|
+
openCreatedDocument?: boolean;
|
|
1714
|
+
className?: string;
|
|
1715
|
+
/** The body the drop target wraps (the list of attached things). */
|
|
1716
|
+
children?: ReactNode;
|
|
1717
|
+
}
|
|
1718
|
+
declare function AssociationCaptureToolbar({ attach, uploadFolderPath, uploadVisibility, uploadLocationLabel, attachRetryLabel, filePicker, showActions, showToolbar, extraActions, openCreatedDocument, className, children, }: AssociationCaptureToolbarProps): react.JSX.Element;
|
|
1719
|
+
/** The dense toolbar button (exported so hosts' extraActions match). */
|
|
1720
|
+
declare function CaptureToolbarAction({ icon: Icon, label, onClick, disabled, spinning, }: {
|
|
1721
|
+
icon: (props: IconProps) => ReactNode;
|
|
1722
|
+
label: string;
|
|
1723
|
+
onClick: () => void;
|
|
1724
|
+
disabled?: boolean;
|
|
1725
|
+
spinning?: boolean;
|
|
1726
|
+
}): react.JSX.Element;
|
|
1727
|
+
|
|
1728
|
+
interface DoorRefExtras {
|
|
1729
|
+
/** Container-owned opener — wins over hrefFor when the host EntityRef is absent. */
|
|
1730
|
+
onOpen?: (() => void) | undefined;
|
|
1731
|
+
}
|
|
1732
|
+
/**
|
|
1733
|
+
* Render an entity's NAME with its doors, degrading per the port table.
|
|
1734
|
+
* The host `EntityRef` receives the measured prop subset when bound.
|
|
1735
|
+
*/
|
|
1736
|
+
declare function DoorRef(props: EntityRefProps & DoorRefExtras): react.JSX.Element;
|
|
1737
|
+
/** The unresolved-target chip, host-supplied or the package's plain one. */
|
|
1738
|
+
declare function UnresolvedRef({ token, id }: {
|
|
1739
|
+
token: string;
|
|
1740
|
+
id: string;
|
|
1741
|
+
}): react.JSX.Element;
|
|
1742
|
+
|
|
1743
|
+
interface ContentRoleMeta {
|
|
1744
|
+
id: ContentRole;
|
|
1745
|
+
/** Section heading. */
|
|
1746
|
+
title: string;
|
|
1747
|
+
/** One-line "what is this bucket". */
|
|
1748
|
+
tagline: string;
|
|
1749
|
+
/** Categorical accent classes (tint only — surfaces stay semantic). */
|
|
1750
|
+
accentText: string;
|
|
1751
|
+
accentBg: string;
|
|
1752
|
+
accentBar: string;
|
|
1753
|
+
}
|
|
1754
|
+
/** Ordered for display: capability, data-in, data-out, both, structure. */
|
|
1755
|
+
declare const CONTENT_ROLES: ContentRoleMeta[];
|
|
1756
|
+
declare function getContentRoleMeta(role: ContentRole): ContentRoleMeta;
|
|
1757
|
+
|
|
1758
|
+
export { AssociationCandidateBody, type AssociationCandidateBodyProps, AssociationCaptureToolbar, type AssociationCaptureToolbarProps, AssociationCard, AssociationCardGrid, type AssociationCardGridProps, type AssociationCardProps, type AssociationEntitySelectAdapter, type AssociationEntitySelectItem, AssociationList, type AssociationListProps, AssociationPicker, type AssociationPickerProps, AssociationWindow, type AssociationWindowProps, type AssociationWriteResult, AssociationsProvider, type AssociationsProviderProps, type AssociationsUiPorts, AttachedItemsSheet, type AttachedItemsSheetProps, CONTENT_ROLES, type CandidateRecord, type CaptureAttach, type CaptureAttachResult, CaptureToolbarAction, type CategoryCreateResult, type CategoryMutationResult, type ContainerLink, type ContainerResourceRow, type ContainerResourcesAdapter, type ContentRoleMeta, DefaultEntityIcon, DoorRef, type EntityTitleRef, type PrimaryEntity, PrimaryEntityProvider, UniversalAssociationPicker, type UniversalAssociationPickerProps, type UniversalCandidate, UnresolvedRef, type UseAssociationCandidatesArgs, type UseAssociationCandidatesReturn, type UseAssociationEntitySelectAdapterArgs, type UseAssociationsArgs, type UseAssociationsReturn, type UseCategoriesArgs, type UseCategoriesReturn, type UseContainerLinksArgs, type UseContainerLinksReturn, type UseEntityTitlesReturn, type UseUniversalEntitySearchArgs, type UseUniversalEntitySearchReturn, attachedKey, getContentRoleMeta, useAssociationCandidates, useAssociationEntitySelectAdapter, useAssociations, useAssociationsStore, useAssociationsUiPorts, useCategories, useContainerLinks, useContainerLinksAdapter, useEntityRelationships, useEntityTitles, useNotifier, usePrimaryEntity, useUniversalEntitySearch };
|