robosystems-client 0.2.15__py3-none-any.whl → 0.2.16__py3-none-any.whl

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.

Potentially problematic release.


This version of robosystems-client might be problematic. Click here for more details.

Files changed (371) hide show
  1. robosystems_client/api/agent/auto_select_agent.py +23 -27
  2. robosystems_client/api/agent/batch_process_queries.py +13 -13
  3. robosystems_client/api/agent/execute_specific_agent.py +23 -27
  4. robosystems_client/api/agent/get_agent_metadata.py +13 -13
  5. robosystems_client/api/agent/list_agents.py +23 -23
  6. robosystems_client/api/agent/recommend_agent.py +13 -13
  7. robosystems_client/api/auth/check_password_strength.py +17 -17
  8. robosystems_client/api/auth/complete_sso_auth.py +17 -17
  9. robosystems_client/api/auth/forgot_password.py +17 -23
  10. robosystems_client/api/auth/generate_sso_token.py +26 -26
  11. robosystems_client/api/auth/get_captcha_config.py +6 -6
  12. robosystems_client/api/auth/get_current_auth_user.py +17 -17
  13. robosystems_client/api/auth/get_password_policy.py +10 -10
  14. robosystems_client/api/auth/login_user.py +17 -17
  15. robosystems_client/api/auth/logout_user.py +10 -10
  16. robosystems_client/api/auth/refresh_auth_session.py +17 -17
  17. robosystems_client/api/auth/register_user.py +17 -17
  18. robosystems_client/api/auth/resend_verification_email.py +17 -29
  19. robosystems_client/api/auth/reset_password.py +17 -17
  20. robosystems_client/api/auth/sso_token_exchange.py +17 -17
  21. robosystems_client/api/auth/validate_reset_token.py +17 -17
  22. robosystems_client/api/auth/verify_email.py +17 -17
  23. robosystems_client/api/backup/create_backup.py +13 -13
  24. robosystems_client/api/backup/get_backup_download_url.py +22 -22
  25. robosystems_client/api/backup/get_backup_stats.py +13 -13
  26. robosystems_client/api/backup/list_backups.py +31 -31
  27. robosystems_client/api/backup/restore_backup.py +13 -13
  28. robosystems_client/api/billing/cancel_org_subscription.py +13 -13
  29. robosystems_client/api/billing/create_checkout_session.py +13 -13
  30. robosystems_client/api/billing/create_portal_session.py +13 -13
  31. robosystems_client/api/billing/get_checkout_status.py +13 -13
  32. robosystems_client/api/billing/get_org_billing_customer.py +13 -13
  33. robosystems_client/api/billing/get_org_subscription.py +13 -13
  34. robosystems_client/api/billing/get_org_upcoming_invoice.py +16 -16
  35. robosystems_client/api/billing/list_org_invoices.py +22 -22
  36. robosystems_client/api/billing/list_org_subscriptions.py +13 -13
  37. robosystems_client/api/connections/create_connection.py +13 -13
  38. robosystems_client/api/connections/create_link_token.py +13 -13
  39. robosystems_client/api/connections/delete_connection.py +13 -13
  40. robosystems_client/api/connections/exchange_link_token.py +13 -13
  41. robosystems_client/api/connections/get_connection.py +13 -13
  42. robosystems_client/api/connections/get_connection_options.py +13 -13
  43. robosystems_client/api/connections/init_o_auth.py +13 -13
  44. robosystems_client/api/connections/list_connections.py +33 -33
  45. robosystems_client/api/connections/oauth_callback.py +13 -13
  46. robosystems_client/api/connections/sync_connection.py +13 -19
  47. robosystems_client/api/credits_/check_credit_balance.py +38 -45
  48. robosystems_client/api/credits_/check_storage_limits.py +13 -13
  49. robosystems_client/api/credits_/get_credit_summary.py +13 -13
  50. robosystems_client/api/credits_/get_storage_usage.py +28 -28
  51. robosystems_client/api/credits_/list_credit_transactions.py +71 -71
  52. robosystems_client/api/files/__init__.py +1 -0
  53. robosystems_client/api/files/create_file_upload.py +311 -0
  54. robosystems_client/api/files/delete_file.py +354 -0
  55. robosystems_client/api/files/get_file.py +329 -0
  56. robosystems_client/api/files/list_files.py +346 -0
  57. robosystems_client/api/files/update_file.py +320 -0
  58. robosystems_client/api/graph_health/get_database_health.py +13 -13
  59. robosystems_client/api/graph_info/get_database_info.py +13 -13
  60. robosystems_client/api/graph_limits/get_graph_limits.py +13 -13
  61. robosystems_client/api/graphs/create_graph.py +13 -13
  62. robosystems_client/api/graphs/get_available_extensions.py +13 -13
  63. robosystems_client/api/graphs/get_available_graph_tiers.py +22 -22
  64. robosystems_client/api/graphs/get_graphs.py +13 -13
  65. robosystems_client/api/graphs/select_graph.py +13 -13
  66. robosystems_client/api/materialization/__init__.py +1 -0
  67. robosystems_client/api/materialization/get_materialization_status.py +272 -0
  68. robosystems_client/api/materialization/materialize_graph.py +416 -0
  69. robosystems_client/api/mcp/call_mcp_tool.py +32 -32
  70. robosystems_client/api/mcp/list_mcp_tools.py +13 -13
  71. robosystems_client/api/operations/cancel_operation.py +13 -13
  72. robosystems_client/api/operations/get_operation_status.py +13 -25
  73. robosystems_client/api/operations/stream_operation_events.py +41 -41
  74. robosystems_client/api/org/create_org.py +13 -13
  75. robosystems_client/api/org/get_org.py +13 -13
  76. robosystems_client/api/org/list_org_graphs.py +13 -13
  77. robosystems_client/api/org/list_user_orgs.py +6 -6
  78. robosystems_client/api/org/update_org.py +13 -13
  79. robosystems_client/api/org_members/invite_org_member.py +13 -13
  80. robosystems_client/api/org_members/list_org_members.py +13 -13
  81. robosystems_client/api/org_members/remove_org_member.py +13 -13
  82. robosystems_client/api/org_members/update_org_member_role.py +13 -13
  83. robosystems_client/api/org_usage/get_org_limits.py +13 -13
  84. robosystems_client/api/org_usage/get_org_usage.py +22 -22
  85. robosystems_client/api/query/execute_cypher_query.py +74 -62
  86. robosystems_client/api/schema/export_graph_schema.py +35 -35
  87. robosystems_client/api/schema/get_graph_schema.py +13 -13
  88. robosystems_client/api/schema/validate_schema.py +13 -13
  89. robosystems_client/api/service_offerings/get_service_offerings.py +17 -17
  90. robosystems_client/api/status/get_service_status.py +10 -10
  91. robosystems_client/api/subgraphs/create_subgraph.py +64 -28
  92. robosystems_client/api/subgraphs/delete_subgraph.py +13 -13
  93. robosystems_client/api/subgraphs/get_subgraph_info.py +13 -13
  94. robosystems_client/api/subgraphs/get_subgraph_quota.py +13 -13
  95. robosystems_client/api/subgraphs/list_subgraphs.py +13 -13
  96. robosystems_client/api/subscriptions/create_repository_subscription.py +13 -13
  97. robosystems_client/api/subscriptions/get_graph_subscription.py +13 -13
  98. robosystems_client/api/subscriptions/upgrade_subscription.py +13 -13
  99. robosystems_client/api/tables/list_tables.py +13 -13
  100. robosystems_client/api/tables/query_tables.py +13 -13
  101. robosystems_client/api/usage/get_graph_metrics.py +13 -13
  102. robosystems_client/api/usage/get_graph_usage_analytics.py +66 -66
  103. robosystems_client/api/user/create_user_api_key.py +13 -13
  104. robosystems_client/api/user/get_current_user.py +6 -6
  105. robosystems_client/api/user/list_user_api_keys.py +6 -6
  106. robosystems_client/api/user/revoke_user_api_key.py +13 -13
  107. robosystems_client/api/user/update_user.py +13 -13
  108. robosystems_client/api/user/update_user_api_key.py +13 -13
  109. robosystems_client/api/user/update_user_password.py +13 -13
  110. robosystems_client/api/views/__init__.py +1 -0
  111. robosystems_client/api/views/create_view.py +245 -0
  112. robosystems_client/api/views/save_view.py +299 -0
  113. robosystems_client/client.py +13 -13
  114. robosystems_client/extensions/__init__.py +39 -0
  115. robosystems_client/extensions/element_mapping_client.py +585 -0
  116. robosystems_client/extensions/subgraph_workspace_client.py +744 -0
  117. robosystems_client/extensions/table_ingest_client.py +24 -23
  118. robosystems_client/extensions/view_builder_client.py +617 -0
  119. robosystems_client/models/__init__.py +34 -10
  120. robosystems_client/models/account_info.py +2 -0
  121. robosystems_client/models/agent_list_response.py +3 -1
  122. robosystems_client/models/agent_list_response_agents.py +5 -3
  123. robosystems_client/models/agent_list_response_agents_additional_property.py +2 -0
  124. robosystems_client/models/agent_message.py +9 -7
  125. robosystems_client/models/agent_metadata_response.py +11 -9
  126. robosystems_client/models/agent_recommendation.py +8 -6
  127. robosystems_client/models/agent_recommendation_request.py +9 -7
  128. robosystems_client/models/agent_recommendation_request_context_type_0.py +2 -0
  129. robosystems_client/models/agent_recommendation_response.py +4 -2
  130. robosystems_client/models/agent_request.py +41 -40
  131. robosystems_client/models/agent_request_context_type_0.py +2 -0
  132. robosystems_client/models/agent_response.py +42 -44
  133. robosystems_client/models/agent_response_error_details_type_0.py +2 -0
  134. robosystems_client/models/agent_response_metadata_type_0.py +2 -0
  135. robosystems_client/models/agent_response_tokens_used_type_0.py +2 -0
  136. robosystems_client/models/api_key_info.py +18 -16
  137. robosystems_client/models/api_keys_response.py +4 -2
  138. robosystems_client/models/auth_response.py +26 -24
  139. robosystems_client/models/auth_response_org_type_0.py +2 -0
  140. robosystems_client/models/auth_response_user.py +2 -0
  141. robosystems_client/models/available_extension.py +5 -3
  142. robosystems_client/models/available_extensions_response.py +4 -2
  143. robosystems_client/models/available_graph_tiers_response.py +4 -2
  144. robosystems_client/models/backup_create_request.py +18 -16
  145. robosystems_client/models/backup_download_url_response.py +2 -0
  146. robosystems_client/models/backup_limits.py +2 -0
  147. robosystems_client/models/backup_list_response.py +4 -2
  148. robosystems_client/models/backup_response.py +13 -11
  149. robosystems_client/models/backup_restore_request.py +7 -6
  150. robosystems_client/models/backup_stats_response.py +9 -7
  151. robosystems_client/models/backup_stats_response_backup_formats.py +2 -0
  152. robosystems_client/models/batch_agent_request.py +7 -5
  153. robosystems_client/models/batch_agent_response.py +4 -2
  154. robosystems_client/models/billing_customer.py +10 -8
  155. robosystems_client/models/cancel_operation_response_canceloperation.py +2 -0
  156. robosystems_client/models/check_credit_balance_response_checkcreditbalance.py +2 -0
  157. robosystems_client/models/checkout_response.py +22 -20
  158. robosystems_client/models/checkout_status_response.py +19 -17
  159. robosystems_client/models/connection_options_response.py +4 -2
  160. robosystems_client/models/connection_provider_info.py +26 -24
  161. robosystems_client/models/connection_response.py +14 -12
  162. robosystems_client/models/connection_response_metadata.py +2 -0
  163. robosystems_client/models/copy_operation_limits.py +2 -0
  164. robosystems_client/models/create_api_key_request.py +13 -11
  165. robosystems_client/models/create_api_key_response.py +3 -1
  166. robosystems_client/models/create_checkout_request.py +3 -1
  167. robosystems_client/models/create_checkout_request_resource_config.py +2 -0
  168. robosystems_client/models/create_connection_request.py +21 -21
  169. robosystems_client/models/create_graph_request.py +25 -25
  170. robosystems_client/models/create_org_request.py +7 -5
  171. robosystems_client/models/create_repository_subscription_request.py +2 -0
  172. robosystems_client/models/create_subgraph_request.py +30 -19
  173. robosystems_client/models/create_subgraph_request_metadata_type_0.py +2 -0
  174. robosystems_client/models/create_view_request.py +141 -0
  175. robosystems_client/models/credit_limits.py +2 -0
  176. robosystems_client/models/credit_summary.py +3 -1
  177. robosystems_client/models/credit_summary_operation_breakdown.py +2 -0
  178. robosystems_client/models/credit_summary_response.py +8 -6
  179. robosystems_client/models/custom_schema_definition.py +39 -33
  180. robosystems_client/models/custom_schema_definition_metadata.py +2 -0
  181. robosystems_client/models/custom_schema_definition_nodes_item.py +2 -0
  182. robosystems_client/models/custom_schema_definition_relationships_item.py +2 -0
  183. robosystems_client/models/cypher_query_request.py +15 -13
  184. robosystems_client/models/cypher_query_request_parameters_type_0.py +2 -0
  185. robosystems_client/models/database_health_response.py +21 -19
  186. robosystems_client/models/database_info_response.py +13 -11
  187. robosystems_client/models/delete_file_response.py +54 -1
  188. robosystems_client/models/delete_subgraph_request.py +12 -10
  189. robosystems_client/models/delete_subgraph_response.py +13 -11
  190. robosystems_client/models/detailed_transactions_response.py +6 -4
  191. robosystems_client/models/detailed_transactions_response_date_range.py +2 -0
  192. robosystems_client/models/detailed_transactions_response_summary.py +5 -3
  193. robosystems_client/models/email_verification_request.py +2 -0
  194. robosystems_client/models/enhanced_credit_transaction_response.py +24 -22
  195. robosystems_client/models/enhanced_credit_transaction_response_metadata.py +2 -0
  196. robosystems_client/models/enhanced_file_status_layers.py +83 -0
  197. robosystems_client/models/error_response.py +19 -17
  198. robosystems_client/models/exchange_token_request.py +9 -7
  199. robosystems_client/models/exchange_token_request_metadata_type_0.py +2 -0
  200. robosystems_client/models/execute_cypher_query_response_200.py +25 -21
  201. robosystems_client/models/execute_cypher_query_response_200_data_item.py +2 -0
  202. robosystems_client/models/fact_detail.py +109 -0
  203. robosystems_client/models/file_info.py +18 -16
  204. robosystems_client/models/file_layer_status.py +123 -0
  205. robosystems_client/models/file_status_update.py +14 -0
  206. robosystems_client/models/file_upload_request.py +25 -3
  207. robosystems_client/models/file_upload_response.py +2 -0
  208. robosystems_client/models/forgot_password_request.py +2 -0
  209. robosystems_client/models/forgot_password_response_forgotpassword.py +2 -0
  210. robosystems_client/models/get_current_auth_user_response_getcurrentauthuser.py +2 -0
  211. robosystems_client/models/get_file_info_response.py +62 -21
  212. robosystems_client/models/get_operation_status_response_getoperationstatus.py +2 -0
  213. robosystems_client/models/get_storage_usage_response_getstorageusage.py +2 -0
  214. robosystems_client/models/graph_info.py +10 -8
  215. robosystems_client/models/graph_limits_response.py +14 -12
  216. robosystems_client/models/graph_metadata.py +14 -12
  217. robosystems_client/models/graph_metrics_response.py +17 -15
  218. robosystems_client/models/graph_metrics_response_estimated_size.py +2 -0
  219. robosystems_client/models/graph_metrics_response_health_status.py +2 -0
  220. robosystems_client/models/graph_metrics_response_node_counts.py +2 -0
  221. robosystems_client/models/graph_metrics_response_relationship_counts.py +2 -0
  222. robosystems_client/models/graph_subscription_response.py +28 -26
  223. robosystems_client/models/graph_subscription_tier.py +15 -13
  224. robosystems_client/models/graph_subscriptions.py +5 -3
  225. robosystems_client/models/graph_tier_backup.py +2 -0
  226. robosystems_client/models/graph_tier_copy_operations.py +2 -0
  227. robosystems_client/models/graph_tier_info.py +15 -13
  228. robosystems_client/models/graph_tier_instance.py +2 -0
  229. robosystems_client/models/graph_tier_limits.py +10 -8
  230. robosystems_client/models/graph_usage_response.py +32 -30
  231. robosystems_client/models/graph_usage_response_recent_events_item.py +2 -0
  232. robosystems_client/models/health_status.py +9 -7
  233. robosystems_client/models/health_status_details_type_0.py +2 -0
  234. robosystems_client/models/http_validation_error.py +12 -8
  235. robosystems_client/models/initial_entity_data.py +38 -36
  236. robosystems_client/models/invite_member_request.py +9 -7
  237. robosystems_client/models/invoice.py +35 -33
  238. robosystems_client/models/invoice_line_item.py +13 -11
  239. robosystems_client/models/invoices_response.py +4 -2
  240. robosystems_client/models/link_token_request.py +21 -23
  241. robosystems_client/models/link_token_request_options_type_0.py +2 -0
  242. robosystems_client/models/list_org_graphs_response_200_item.py +2 -0
  243. robosystems_client/models/list_subgraphs_response.py +15 -13
  244. robosystems_client/models/list_table_files_response.py +27 -11
  245. robosystems_client/models/login_request.py +2 -0
  246. robosystems_client/models/logout_user_response_logoutuser.py +2 -0
  247. robosystems_client/models/{bulk_ingest_request.py → materialize_request.py} +25 -15
  248. robosystems_client/models/materialize_response.py +131 -0
  249. robosystems_client/models/materialize_status_response.py +172 -0
  250. robosystems_client/models/mcp_tool_call.py +7 -5
  251. robosystems_client/models/mcp_tool_call_arguments.py +2 -0
  252. robosystems_client/models/mcp_tools_response.py +4 -2
  253. robosystems_client/models/mcp_tools_response_tools_item.py +2 -0
  254. robosystems_client/models/o_auth_callback_request.py +18 -16
  255. robosystems_client/models/o_auth_init_request.py +14 -12
  256. robosystems_client/models/o_auth_init_request_additional_params_type_0.py +2 -0
  257. robosystems_client/models/o_auth_init_response.py +2 -0
  258. robosystems_client/models/offering_repository_plan.py +9 -7
  259. robosystems_client/models/offering_repository_plan_rate_limits_type_0.py +8 -8
  260. robosystems_client/models/operation_costs.py +4 -2
  261. robosystems_client/models/operation_costs_ai_operations.py +2 -0
  262. robosystems_client/models/operation_costs_token_pricing.py +5 -3
  263. robosystems_client/models/org_detail_response.py +13 -11
  264. robosystems_client/models/org_detail_response_graphs_item.py +2 -0
  265. robosystems_client/models/org_detail_response_limits_type_0.py +2 -0
  266. robosystems_client/models/org_detail_response_members_item.py +2 -0
  267. robosystems_client/models/org_limits_response.py +3 -1
  268. robosystems_client/models/org_limits_response_current_usage.py +2 -0
  269. robosystems_client/models/org_list_response.py +4 -2
  270. robosystems_client/models/org_member_list_response.py +4 -2
  271. robosystems_client/models/org_member_response.py +2 -0
  272. robosystems_client/models/org_response.py +2 -0
  273. robosystems_client/models/org_usage_response.py +7 -5
  274. robosystems_client/models/org_usage_response_daily_trend_item.py +2 -0
  275. robosystems_client/models/org_usage_response_graph_details_item.py +2 -0
  276. robosystems_client/models/org_usage_summary.py +18 -16
  277. robosystems_client/models/password_check_request.py +8 -6
  278. robosystems_client/models/password_check_response.py +3 -1
  279. robosystems_client/models/password_check_response_character_types.py +2 -0
  280. robosystems_client/models/password_policy_response.py +3 -1
  281. robosystems_client/models/password_policy_response_policy.py +2 -0
  282. robosystems_client/models/payment_method.py +23 -21
  283. robosystems_client/models/performance_insights.py +5 -3
  284. robosystems_client/models/performance_insights_operation_stats.py +2 -0
  285. robosystems_client/models/performance_insights_slow_queries_item.py +2 -0
  286. robosystems_client/models/plaid_connection_config.py +30 -30
  287. robosystems_client/models/plaid_connection_config_accounts_type_0_item.py +2 -0
  288. robosystems_client/models/plaid_connection_config_institution_type_0.py +2 -0
  289. robosystems_client/models/portal_session_response.py +2 -0
  290. robosystems_client/models/query_limits.py +2 -0
  291. robosystems_client/models/quick_books_connection_config.py +13 -11
  292. robosystems_client/models/rate_limits.py +2 -0
  293. robosystems_client/models/register_request.py +8 -6
  294. robosystems_client/models/repository_info.py +4 -2
  295. robosystems_client/models/repository_subscriptions.py +4 -2
  296. robosystems_client/models/resend_verification_email_response_resendverificationemail.py +2 -0
  297. robosystems_client/models/reset_password_request.py +2 -0
  298. robosystems_client/models/reset_password_validate_response.py +8 -6
  299. robosystems_client/models/save_view_request.py +138 -0
  300. robosystems_client/models/save_view_response.py +181 -0
  301. robosystems_client/models/schema_export_response.py +16 -14
  302. robosystems_client/models/schema_export_response_data_stats_type_0.py +2 -0
  303. robosystems_client/models/schema_export_response_schema_definition_type_0.py +2 -0
  304. robosystems_client/models/schema_info_response.py +3 -1
  305. robosystems_client/models/schema_info_response_schema.py +2 -0
  306. robosystems_client/models/schema_validation_request.py +18 -17
  307. robosystems_client/models/schema_validation_request_schema_definition_type_0.py +2 -0
  308. robosystems_client/models/schema_validation_response.py +28 -33
  309. robosystems_client/models/schema_validation_response_compatibility_type_0.py +2 -0
  310. robosystems_client/models/schema_validation_response_stats_type_0.py +2 -0
  311. robosystems_client/models/sec_connection_config.py +8 -6
  312. robosystems_client/models/selection_criteria.py +19 -17
  313. robosystems_client/models/service_offering_summary.py +2 -0
  314. robosystems_client/models/service_offerings_response.py +6 -4
  315. robosystems_client/models/sso_complete_request.py +2 -0
  316. robosystems_client/models/sso_exchange_request.py +8 -6
  317. robosystems_client/models/sso_exchange_response.py +2 -0
  318. robosystems_client/models/sso_token_response.py +2 -0
  319. robosystems_client/models/storage_info.py +4 -2
  320. robosystems_client/models/storage_info_included_per_tier.py +2 -0
  321. robosystems_client/models/storage_info_overage_pricing.py +2 -0
  322. robosystems_client/models/storage_limit_response.py +9 -7
  323. robosystems_client/models/storage_limits.py +8 -6
  324. robosystems_client/models/storage_summary.py +2 -0
  325. robosystems_client/models/structure_detail.py +85 -0
  326. robosystems_client/models/subgraph_quota_response.py +23 -21
  327. robosystems_client/models/subgraph_response.py +35 -35
  328. robosystems_client/models/subgraph_response_metadata_type_0.py +2 -0
  329. robosystems_client/models/subgraph_summary.py +14 -12
  330. robosystems_client/models/success_response.py +11 -9
  331. robosystems_client/models/success_response_data_type_0.py +2 -0
  332. robosystems_client/models/sync_connection_request.py +11 -9
  333. robosystems_client/models/sync_connection_request_sync_options_type_0.py +2 -0
  334. robosystems_client/models/sync_connection_response_syncconnection.py +2 -0
  335. robosystems_client/models/table_info.py +12 -10
  336. robosystems_client/models/table_list_response.py +4 -2
  337. robosystems_client/models/table_query_request.py +9 -7
  338. robosystems_client/models/table_query_response.py +2 -0
  339. robosystems_client/models/token_pricing.py +2 -0
  340. robosystems_client/models/transaction_summary_response.py +13 -11
  341. robosystems_client/models/upcoming_invoice.py +10 -8
  342. robosystems_client/models/update_api_key_request.py +13 -11
  343. robosystems_client/models/{update_file_status_response_updatefilestatus.py → update_file_response_updatefile.py} +7 -5
  344. robosystems_client/models/update_member_role_request.py +2 -0
  345. robosystems_client/models/update_org_request.py +14 -12
  346. robosystems_client/models/update_password_request.py +2 -0
  347. robosystems_client/models/update_user_request.py +13 -11
  348. robosystems_client/models/upgrade_subscription_request.py +2 -0
  349. robosystems_client/models/user_graphs_response.py +10 -8
  350. robosystems_client/models/user_response.py +22 -18
  351. robosystems_client/models/validation_error.py +8 -6
  352. robosystems_client/models/view_axis_config.py +276 -0
  353. robosystems_client/models/view_axis_config_element_labels_type_0.py +46 -0
  354. robosystems_client/models/view_axis_config_member_labels_type_0.py +46 -0
  355. robosystems_client/models/view_config.py +127 -0
  356. robosystems_client/models/view_source.py +144 -0
  357. robosystems_client/models/view_source_type.py +9 -0
  358. robosystems_client/types.py +9 -9
  359. {robosystems_client-0.2.15.dist-info → robosystems_client-0.2.16.dist-info}/METADATA +1 -1
  360. robosystems_client-0.2.16.dist-info/RECORD +418 -0
  361. robosystems_client/api/tables/delete_file.py +0 -317
  362. robosystems_client/api/tables/get_file_info.py +0 -249
  363. robosystems_client/api/tables/get_upload_url.py +0 -380
  364. robosystems_client/api/tables/ingest_tables.py +0 -456
  365. robosystems_client/api/tables/list_table_files.py +0 -329
  366. robosystems_client/api/tables/update_file_status.py +0 -395
  367. robosystems_client/models/bulk_ingest_response.py +0 -137
  368. robosystems_client/models/table_ingest_result.py +0 -107
  369. robosystems_client-0.2.15.dist-info/RECORD +0 -396
  370. {robosystems_client-0.2.15.dist-info → robosystems_client-0.2.16.dist-info}/WHEEL +0 -0
  371. {robosystems_client-0.2.15.dist-info → robosystems_client-0.2.16.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,744 @@
1
+ """Subgraph Workspace Client Extension
2
+
3
+ Client for managing subgraph workspaces following the Financial Report Creator architecture.
4
+ Supports creating isolated workspaces, transferring data, and publishing to main graph.
5
+ """
6
+
7
+ from typing import List, Optional, Dict, Any
8
+ from dataclasses import dataclass
9
+ from enum import Enum
10
+ import json
11
+ import httpx
12
+
13
+
14
+ class StorageType(Enum):
15
+ """Subgraph storage types"""
16
+
17
+ IN_MEMORY = "in_memory"
18
+ DISK_BASED = "disk_based"
19
+
20
+
21
+ @dataclass
22
+ class SubgraphWorkspace:
23
+ """Represents a subgraph workspace"""
24
+
25
+ graph_id: str # Full subgraph ID (e.g., kg123_workspace)
26
+ parent_id: str # Parent graph ID (e.g., kg123)
27
+ name: str # Workspace name (e.g., workspace)
28
+ display_name: str
29
+ storage_type: StorageType
30
+ created_at: str
31
+ status: str = "active"
32
+ fork_status: Optional[Dict[str, Any]] = None # Fork operation status if forked
33
+
34
+
35
+ @dataclass
36
+ class ExportResult:
37
+ """Result from exporting subgraph to parquet"""
38
+
39
+ shared_filename: str
40
+ files_exported: List[Dict[str, Any]]
41
+ total_rows: int
42
+ execution_time_ms: int
43
+
44
+
45
+ @dataclass
46
+ class PublishResult:
47
+ """Result from publishing subgraph to main graph"""
48
+
49
+ nodes_created: int
50
+ relationships_created: int
51
+ execution_time_ms: int
52
+ success: bool
53
+
54
+
55
+ class SubgraphWorkspaceClient:
56
+ """
57
+ Client for managing subgraph workspaces.
58
+
59
+ Provides functionality to:
60
+ - Create/delete subgraph workspaces
61
+ - Transfer data from main graph to subgraph
62
+ - Export subgraph to parquet files
63
+ - Publish subgraph to main graph via incremental ingestion
64
+ """
65
+
66
+ def __init__(self, api_client, query_client=None):
67
+ """
68
+ Initialize with API client and optional query client.
69
+
70
+ Args:
71
+ api_client: RoboSystems API client for subgraph operations
72
+ query_client: Optional query client for executing Cypher
73
+ """
74
+ self.api = api_client
75
+ self.query = query_client
76
+
77
+ async def create_workspace(
78
+ self,
79
+ parent_graph_id: str,
80
+ name: str,
81
+ display_name: str = None,
82
+ storage_type: StorageType = StorageType.IN_MEMORY,
83
+ schema_extensions: List[str] = None,
84
+ fork_parent: bool = False,
85
+ ) -> SubgraphWorkspace:
86
+ """
87
+ Create a new subgraph workspace.
88
+
89
+ Args:
90
+ parent_graph_id: Parent graph ID (e.g., kg123)
91
+ name: Workspace name (alphanumeric, 1-20 chars)
92
+ display_name: Optional human-readable name
93
+ storage_type: IN_MEMORY (fast, <10K nodes) or DISK_BASED (persistent, >100K nodes)
94
+ schema_extensions: List of schema extensions (e.g., ["roboledger"])
95
+ fork_parent: If True, copy all data from parent graph (creates a "fork")
96
+
97
+ Returns:
98
+ SubgraphWorkspace object
99
+ """
100
+ # Construct request for subgraph creation
101
+ request_body = {
102
+ "name": name,
103
+ "display_name": display_name or f"Workspace {name}",
104
+ "storage_type": storage_type.value,
105
+ "schema_extensions": schema_extensions or ["roboledger"],
106
+ "fork_parent": fork_parent, # Pass fork flag to server
107
+ }
108
+
109
+ # Use httpx to call API
110
+ async with httpx.AsyncClient() as client:
111
+ headers = {"X-API-Key": self.api.token, "Content-Type": "application/json"}
112
+ response = await client.post(
113
+ f"{self.api._base_url}/v1/graphs/{parent_graph_id}/subgraphs",
114
+ json=request_body,
115
+ headers=headers,
116
+ )
117
+ result = response.json()
118
+
119
+ # Construct full subgraph ID
120
+ subgraph_id = f"{parent_graph_id}_{name}"
121
+
122
+ workspace = SubgraphWorkspace(
123
+ graph_id=subgraph_id,
124
+ parent_id=parent_graph_id,
125
+ name=name,
126
+ display_name=result.get("display_name", display_name),
127
+ storage_type=storage_type,
128
+ created_at=result.get("created_at"),
129
+ status="active",
130
+ )
131
+
132
+ # If fork_parent is True, trigger server-side fork
133
+ # The server will handle the fork operation with progress monitoring
134
+ if fork_parent:
135
+ # Fork happens server-side during creation when fork_parent=True
136
+ # For client-side monitoring, use fork_from_parent_with_sse() method
137
+ pass
138
+
139
+ return workspace
140
+
141
+ async def create_workspace_with_fork(
142
+ self,
143
+ parent_graph_id: str,
144
+ name: str,
145
+ display_name: str = None,
146
+ fork_parent: bool = True,
147
+ fork_options: Dict[str, Any] = None,
148
+ progress_callback: Optional[callable] = None,
149
+ ) -> SubgraphWorkspace:
150
+ """
151
+ Create a subgraph workspace with fork from parent using SSE monitoring.
152
+
153
+ This method creates a subgraph and monitors the fork operation via SSE
154
+ if fork_parent=True. The fork operation copies data from the parent
155
+ graph to the new subgraph.
156
+
157
+ Args:
158
+ parent_graph_id: Parent graph ID
159
+ name: Workspace name (alphanumeric only, 1-20 chars)
160
+ display_name: Human-readable display name
161
+ fork_parent: If True, fork data from parent graph
162
+ fork_options: Fork options dict:
163
+ - tables: List of tables to copy or "all" (default: "all")
164
+ - exclude_patterns: List of table patterns to exclude (e.g., ["Report*"])
165
+ progress_callback: Optional callback(msg: str, pct: float) for progress updates
166
+
167
+ Returns:
168
+ SubgraphWorkspace with fork_status if fork was performed
169
+ """
170
+ # Create request body
171
+ request_body = {
172
+ "name": name,
173
+ "display_name": display_name or f"Workspace {name}",
174
+ "fork_parent": fork_parent,
175
+ "metadata": {"fork_options": fork_options} if fork_options else None,
176
+ }
177
+
178
+ # Use httpx directly to call API
179
+ async with httpx.AsyncClient() as client:
180
+ headers = {"X-API-Key": self.api.token, "Content-Type": "application/json"}
181
+
182
+ # Call API to create subgraph with fork
183
+ response = await client.post(
184
+ f"{self.api._base_url}/v1/graphs/{parent_graph_id}/subgraphs",
185
+ json=request_body,
186
+ headers=headers,
187
+ )
188
+ result = response.json()
189
+
190
+ # If fork_parent=True, response includes operation_id for SSE monitoring
191
+ if fork_parent and "operation_id" in result:
192
+ operation_id = result["operation_id"]
193
+
194
+ # Monitor fork progress via SSE
195
+ if progress_callback:
196
+ # Connect to SSE endpoint
197
+ sse_url = f"{self.api._base_url}/v1/operations/{operation_id}/stream"
198
+ headers = {"X-API-Key": self.api.token}
199
+
200
+ async with httpx.AsyncClient() as client:
201
+ async with client.stream("GET", sse_url, headers=headers) as sse_response:
202
+ async for line in sse_response.aiter_lines():
203
+ if line.startswith("data: "):
204
+ try:
205
+ event_data = json.loads(line[6:])
206
+ if event_data.get("event") == "operation_progress":
207
+ msg = event_data.get("data", {}).get("message", "")
208
+ pct = event_data.get("data", {}).get("progress_percent", 0)
209
+ if progress_callback:
210
+ await progress_callback(msg, pct)
211
+ elif event_data.get("event") == "operation_completed":
212
+ if progress_callback:
213
+ await progress_callback("Fork completed", 100)
214
+ break
215
+ elif event_data.get("event") == "operation_error":
216
+ error = event_data.get("data", {}).get("error", "Unknown error")
217
+ if progress_callback:
218
+ await progress_callback(f"Fork failed: {error}", 0)
219
+ break
220
+ except json.JSONDecodeError:
221
+ continue
222
+
223
+ # Get final status via API
224
+ async with httpx.AsyncClient() as client:
225
+ headers = {"X-API-Key": self.api.token}
226
+ status_response = await client.get(
227
+ f"{self.api._base_url}/v1/operations/{operation_id}/status", headers=headers
228
+ )
229
+ final_status = status_response.json()
230
+
231
+ # Construct full subgraph ID
232
+ subgraph_id = f"{parent_graph_id}_{name}"
233
+
234
+ workspace = SubgraphWorkspace(
235
+ graph_id=subgraph_id,
236
+ parent_id=parent_graph_id,
237
+ name=name,
238
+ display_name=display_name or f"Workspace {name}",
239
+ storage_type=StorageType.IN_MEMORY,
240
+ created_at=final_status.get("created_at"),
241
+ status="active",
242
+ fork_status=final_status.get("result", {}).get("fork_status"),
243
+ )
244
+
245
+ return workspace
246
+
247
+ # Non-fork path (immediate response)
248
+ subgraph_id = f"{parent_graph_id}_{name}"
249
+
250
+ return SubgraphWorkspace(
251
+ graph_id=subgraph_id,
252
+ parent_id=parent_graph_id,
253
+ name=name,
254
+ display_name=result.get("display_name", display_name),
255
+ storage_type=StorageType.IN_MEMORY,
256
+ created_at=result.get("created_at"),
257
+ status="active",
258
+ )
259
+
260
+ async def delete_workspace(
261
+ self,
262
+ parent_graph_id: str,
263
+ workspace_name: str,
264
+ force: bool = False,
265
+ create_backup: bool = False,
266
+ ) -> bool:
267
+ """
268
+ Delete a subgraph workspace.
269
+
270
+ Args:
271
+ parent_graph_id: Parent graph ID
272
+ workspace_name: Workspace name to delete
273
+ force: Force deletion even if subgraph contains data
274
+ create_backup: Create backup before deletion
275
+
276
+ Returns:
277
+ True if deleted successfully
278
+ """
279
+ params = {"force": force, "create_backup": create_backup}
280
+
281
+ response = await self.api.delete(
282
+ f"/v1/graphs/{parent_graph_id}/subgraphs/{workspace_name}", params=params
283
+ )
284
+
285
+ return response.status_code == 200
286
+
287
+ async def list_workspaces(self, parent_graph_id: str) -> List[SubgraphWorkspace]:
288
+ """
289
+ List all subgraph workspaces for a parent graph.
290
+
291
+ Args:
292
+ parent_graph_id: Parent graph ID
293
+
294
+ Returns:
295
+ List of SubgraphWorkspace objects
296
+ """
297
+ response = await self.api.get(f"/v1/graphs/{parent_graph_id}/subgraphs")
298
+ subgraphs = response.json()
299
+
300
+ workspaces = []
301
+ for subgraph in subgraphs:
302
+ workspaces.append(
303
+ SubgraphWorkspace(
304
+ graph_id=f"{parent_graph_id}_{subgraph['name']}",
305
+ parent_id=parent_graph_id,
306
+ name=subgraph["name"],
307
+ display_name=subgraph.get("display_name", ""),
308
+ storage_type=StorageType(subgraph.get("storage_type", "in_memory")),
309
+ created_at=subgraph.get("created_at", ""),
310
+ status=subgraph.get("status", "active"),
311
+ )
312
+ )
313
+
314
+ return workspaces
315
+
316
+ async def copy_data_from_main_graph(
317
+ self,
318
+ workspace_id: str,
319
+ parent_graph_id: str,
320
+ node_types: List[str],
321
+ filters: Dict[str, Any] = None,
322
+ ) -> int:
323
+ """
324
+ Copy data from main graph to subgraph workspace.
325
+
326
+ Queries nodes from main graph and creates them in subgraph.
327
+
328
+ Args:
329
+ workspace_id: Subgraph workspace ID (e.g., kg123_workspace)
330
+ parent_graph_id: Parent graph ID to query from
331
+ node_types: List of node types to copy (e.g., ["Element", "Period", "Unit"])
332
+ filters: Optional filters for querying (e.g., {"period_end": "2024-12-31"})
333
+
334
+ Returns:
335
+ Number of nodes copied
336
+ """
337
+ if not self.query:
338
+ raise ValueError("Query client required for data transfer")
339
+
340
+ total_copied = 0
341
+
342
+ for node_type in node_types:
343
+ # Build query for main graph
344
+ where_clause = ""
345
+ if filters:
346
+ conditions = []
347
+ for key, value in filters.items():
348
+ conditions.append(f"n.{key} = '{value}'")
349
+ where_clause = f"WHERE {' AND '.join(conditions)}"
350
+
351
+ # Query from main graph
352
+ query_cypher = f"""
353
+ MATCH (n:{node_type})
354
+ {where_clause}
355
+ RETURN n
356
+ """
357
+
358
+ result = await self.query.query(parent_graph_id, query_cypher)
359
+
360
+ if result and result.data:
361
+ # Batch create in subgraph
362
+ for batch in self._batch_nodes(result.data, 100):
363
+ create_cypher = self._build_batch_create_cypher(node_type, batch)
364
+ await self.query.query(workspace_id, create_cypher)
365
+ total_copied += len(batch)
366
+
367
+ return total_copied
368
+
369
+ async def copy_facts_with_aspects(
370
+ self,
371
+ workspace_id: str,
372
+ parent_graph_id: str,
373
+ fact_set_ids: List[str] = None,
374
+ period_start: str = None,
375
+ period_end: str = None,
376
+ entity_id: str = None,
377
+ ) -> int:
378
+ """
379
+ Copy facts with all their aspects (element, period, unit, dimensions).
380
+
381
+ This is optimized for copying complete fact data with relationships.
382
+
383
+ Args:
384
+ workspace_id: Subgraph workspace ID
385
+ parent_graph_id: Parent graph ID
386
+ fact_set_ids: Optional list of fact set IDs to copy
387
+ period_start: Optional start date filter
388
+ period_end: Optional end date filter
389
+ entity_id: Optional entity filter
390
+
391
+ Returns:
392
+ Number of facts copied
393
+ """
394
+ if not self.query:
395
+ raise ValueError("Query client required for fact transfer")
396
+
397
+ # Build WHERE clause
398
+ conditions = []
399
+ params = {}
400
+
401
+ if fact_set_ids:
402
+ conditions.append("fs.identifier IN $fact_set_ids")
403
+ params["fact_set_ids"] = fact_set_ids
404
+
405
+ if period_start and period_end:
406
+ conditions.append("p.end_date >= $period_start AND p.end_date <= $period_end")
407
+ params["period_start"] = period_start
408
+ params["period_end"] = period_end
409
+
410
+ if entity_id:
411
+ conditions.append("e.identifier = $entity_id")
412
+ params["entity_id"] = entity_id
413
+
414
+ where_clause = f"WHERE {' AND '.join(conditions)}" if conditions else ""
415
+
416
+ # Query facts with all relationships from main graph
417
+ query_cypher = f"""
418
+ MATCH (fs:FactSet)-[:FACT_SET_CONTAINS_FACT]->(f:Fact)
419
+ MATCH (f)-[:FACT_HAS_ELEMENT]->(el:Element)
420
+ MATCH (f)-[:FACT_HAS_PERIOD]->(p:Period)
421
+ MATCH (f)-[:FACT_HAS_ENTITY]->(e:Entity)
422
+ OPTIONAL MATCH (f)-[:FACT_HAS_UNIT]->(u:Unit)
423
+ OPTIONAL MATCH (f)-[:FACT_HAS_DIMENSION]->(d:FactDimension)
424
+ {where_clause}
425
+ RETURN f, el, p, e, u, collect(d) as dimensions
426
+ """
427
+
428
+ result = await self.query.query(parent_graph_id, query_cypher, params)
429
+
430
+ if not result or not result.data:
431
+ return 0
432
+
433
+ # Create nodes and relationships in subgraph
434
+ # This would be done in batches with proper MERGE statements
435
+ facts_copied = 0
436
+
437
+ for row in result.data:
438
+ # Create fact and all related nodes in subgraph
439
+ create_cypher = self._build_fact_create_cypher(row)
440
+ await self.query.query(workspace_id, create_cypher)
441
+ facts_copied += 1
442
+
443
+ return facts_copied
444
+
445
+ async def export_to_parquet(
446
+ self, workspace_id: str, shared_filename: str, tables: List[str] = None
447
+ ) -> ExportResult:
448
+ """
449
+ Export subgraph to parquet files.
450
+
451
+ Each table is exported to a separate parquet file with the shared filename
452
+ for provenance tracking and incremental ingestion.
453
+
454
+ Args:
455
+ workspace_id: Subgraph workspace ID
456
+ shared_filename: Shared filename for all tables (e.g., "report_nvda_2024q4.parquet")
457
+ tables: List of tables to export (default: all report tables)
458
+
459
+ Returns:
460
+ ExportResult with file details
461
+ """
462
+ if tables is None:
463
+ tables = [
464
+ "Report",
465
+ "ReportSection",
466
+ "FactSet",
467
+ "Fact",
468
+ "Structure",
469
+ "Association",
470
+ "Element",
471
+ "Period",
472
+ "Unit",
473
+ ]
474
+
475
+ request_body = {
476
+ "shared_filename": shared_filename,
477
+ "export_all_tables": False,
478
+ "tables": tables,
479
+ }
480
+
481
+ response = await self.api.post(
482
+ f"/v1/graphs/{workspace_id}/export", json=request_body
483
+ )
484
+
485
+ result = response.json()
486
+
487
+ return ExportResult(
488
+ shared_filename=shared_filename,
489
+ files_exported=result.get("files_exported", []),
490
+ total_rows=sum(f.get("row_count", 0) for f in result.get("files_exported", [])),
491
+ execution_time_ms=result.get("execution_time_ms", 0),
492
+ )
493
+
494
+ async def publish_to_main_graph(
495
+ self,
496
+ workspace_id: str,
497
+ parent_graph_id: str,
498
+ shared_filename: str,
499
+ delete_workspace: bool = True,
500
+ ) -> PublishResult:
501
+ """
502
+ Publish workspace to main graph via incremental ingestion.
503
+
504
+ This is the complete publish flow:
505
+ 1. Export subgraph to parquet
506
+ 2. Incremental ingest to main graph (filtered by filename)
507
+ 3. Delete workspace (optional)
508
+
509
+ Args:
510
+ workspace_id: Subgraph workspace ID
511
+ parent_graph_id: Parent graph to publish to
512
+ shared_filename: Filename to use for export/ingest
513
+ delete_workspace: Whether to delete workspace after publish
514
+
515
+ Returns:
516
+ PublishResult with statistics
517
+ """
518
+ # Step 1: Export to parquet
519
+ await self.export_to_parquet(workspace_id, shared_filename)
520
+
521
+ # Step 2: Incremental ingest to main graph
522
+ ingest_request = {
523
+ "file_names": [shared_filename], # Filter to only this report
524
+ "ignore_errors": True,
525
+ "rebuild": False,
526
+ }
527
+
528
+ response = await self.api.post(
529
+ f"/v1/graphs/{parent_graph_id}/tables/ingest", json=ingest_request
530
+ )
531
+
532
+ ingest_result = response.json()
533
+
534
+ # Step 3: Delete workspace (optional)
535
+ if delete_workspace:
536
+ workspace_name = workspace_id.split("_")[-1]
537
+ await self.delete_workspace(parent_graph_id, workspace_name)
538
+
539
+ return PublishResult(
540
+ nodes_created=ingest_result.get("nodes_created", 0),
541
+ relationships_created=ingest_result.get("relationships_created", 0),
542
+ execution_time_ms=ingest_result.get("execution_time_ms", 0),
543
+ success=ingest_result.get("status") == "success",
544
+ )
545
+
546
+ def _batch_nodes(self, nodes: List[Dict], batch_size: int):
547
+ """Helper to batch nodes for efficient creation"""
548
+ for i in range(0, len(nodes), batch_size):
549
+ yield nodes[i : i + batch_size]
550
+
551
+ def _build_batch_create_cypher(self, node_type: str, nodes: List[Dict]) -> str:
552
+ """Helper to build batch CREATE cypher"""
553
+ creates = []
554
+ for i, node_data in enumerate(nodes):
555
+ node = node_data.get("n", node_data)
556
+ props = json.dumps(node).replace('"', "'")
557
+ creates.append(f"CREATE (n{i}:{node_type} {props})")
558
+
559
+ return "\n".join(creates)
560
+
561
+ def _build_fact_create_cypher(self, row: Dict) -> str:
562
+ """Helper to build cypher for creating fact with all relationships"""
563
+ # This would build proper MERGE statements for fact and all related nodes
564
+ # Simplified for illustration
565
+ return f"""
566
+ MERGE (f:Fact {{identifier: '{row["f"]["identifier"]}'}})
567
+ SET f = {json.dumps(row["f"]).replace('"', "'")}
568
+
569
+ MERGE (el:Element {{identifier: '{row["el"]["identifier"]}'}})
570
+ SET el = {json.dumps(row["el"]).replace('"', "'")}
571
+
572
+ MERGE (f)-[:FACT_HAS_ELEMENT]->(el)
573
+ """
574
+
575
+ async def fork_from_parent_with_sse(
576
+ self,
577
+ workspace_id: str,
578
+ parent_graph_id: str,
579
+ fork_options: Optional[Dict[str, Any]] = None,
580
+ progress_callback: Optional[callable] = None,
581
+ ) -> Dict[str, Any]:
582
+ """
583
+ Fork data from parent graph with SSE progress monitoring.
584
+
585
+ This method triggers a server-side fork operation and monitors progress
586
+ via Server-Sent Events (SSE) for real-time updates on large operations.
587
+
588
+ Args:
589
+ workspace_id: Target subgraph workspace ID
590
+ parent_graph_id: Source parent graph ID
591
+ fork_options: Options for selective forking:
592
+ - tables: List of tables or "all"
593
+ - period_filter: Date range filter
594
+ - entity_filter: Entity IDs to include
595
+ - exclude_patterns: Tables to exclude (e.g., ["Report*"])
596
+ progress_callback: Optional callback for progress updates
597
+
598
+ Returns:
599
+ Fork result with statistics
600
+
601
+ Example:
602
+ >>> async def on_progress(event):
603
+ ... print(f"Progress: {event['message']}")
604
+ >>>
605
+ >>> result = await workspace_client.fork_from_parent_with_sse(
606
+ ... workspace_id="kg123_dev",
607
+ ... parent_graph_id="kg123",
608
+ ... fork_options={
609
+ ... "tables": "all",
610
+ ... "exclude_patterns": ["Report*"],
611
+ ... "period_filter": {"start": "2024-01-01", "end": "2024-12-31"}
612
+ ... },
613
+ ... progress_callback=on_progress
614
+ ... )
615
+ """
616
+ # Start fork operation and get SSE endpoint
617
+ fork_request = {
618
+ "operation": "fork",
619
+ "source_graph_id": parent_graph_id,
620
+ "target_graph_id": workspace_id,
621
+ "options": fork_options or {},
622
+ }
623
+
624
+ # Initiate fork operation
625
+ response = await self.api.post(
626
+ f"/v1/graphs/{workspace_id}/operations/fork", json=fork_request
627
+ )
628
+
629
+ operation = response.json()
630
+ operation_id = operation.get("operation_id")
631
+
632
+ if not operation_id:
633
+ # If no SSE available, fall back to synchronous wait
634
+ return operation
635
+
636
+ # Connect to SSE endpoint for progress monitoring
637
+ sse_url = f"{self.api.base_url}/v1/operations/{operation_id}/stream"
638
+ headers = getattr(self.api, "_headers", {})
639
+
640
+ async with httpx.AsyncClient() as client:
641
+ async with client.stream("GET", sse_url, headers=headers) as response:
642
+ async for line in response.aiter_lines():
643
+ if line.startswith("data: "):
644
+ data = line[6:].strip()
645
+ if data == "[DONE]":
646
+ break
647
+
648
+ try:
649
+ event = json.loads(data)
650
+
651
+ # Call progress callback if provided
652
+ if progress_callback:
653
+ await progress_callback(event)
654
+
655
+ # Check for completion
656
+ if event.get("status") in ["completed", "failed"]:
657
+ return event
658
+
659
+ except json.JSONDecodeError:
660
+ continue
661
+
662
+ # Get final status if SSE ended without completion event
663
+ final_response = await self.api.get(f"/v1/operations/{operation_id}")
664
+ return final_response.json()
665
+
666
+ async def write_view_to_workspace(
667
+ self, workspace_id: str, view_data: Dict[str, Any], report_name: str = None
668
+ ) -> str:
669
+ """
670
+ Write view/report data to subgraph workspace.
671
+
672
+ Creates Report, FactSet, Structure, and Association nodes.
673
+
674
+ Args:
675
+ workspace_id: Subgraph workspace ID
676
+ view_data: View data including facts, structures, associations
677
+ report_name: Optional report name
678
+
679
+ Returns:
680
+ Report ID created
681
+ """
682
+ if not self.query:
683
+ raise ValueError("Query client required for writing view data")
684
+
685
+ import uuid
686
+
687
+ report_id = str(uuid.uuid4())
688
+
689
+ # Create Report node
690
+ report_cypher = f"""
691
+ CREATE (r:Report {{
692
+ identifier: '{report_id}',
693
+ name: '{report_name or "Draft Report"}',
694
+ status: 'draft',
695
+ created_at: datetime(),
696
+ ai_generated: false
697
+ }})
698
+ RETURN r.identifier as report_id
699
+ """
700
+
701
+ await self.query.query(workspace_id, report_cypher)
702
+
703
+ # Create FactSet and Facts
704
+ if "facts" in view_data:
705
+ factset_id = str(uuid.uuid4())
706
+ factset_cypher = f"""
707
+ MATCH (r:Report {{identifier: '{report_id}'}})
708
+ CREATE (fs:FactSet {{
709
+ identifier: '{factset_id}',
710
+ name: 'View Facts'
711
+ }})
712
+ CREATE (r)-[:REPORT_HAS_FACT_SET]->(fs)
713
+ """
714
+ await self.query.query(workspace_id, factset_cypher)
715
+
716
+ # Add facts to factset
717
+ for fact in view_data["facts"]:
718
+ fact_cypher = f"""
719
+ MATCH (fs:FactSet {{identifier: '{factset_id}'}})
720
+ CREATE (f:Fact {{
721
+ identifier: randomUUID(),
722
+ element_id: '{fact.get("element_id")}',
723
+ value: {fact.get("value", 0)},
724
+ period_end: '{fact.get("period_end", "")}'
725
+ }})
726
+ CREATE (fs)-[:FACT_SET_CONTAINS_FACT]->(f)
727
+ """
728
+ await self.query.query(workspace_id, fact_cypher)
729
+
730
+ # Create Structure and Associations
731
+ if "structures" in view_data:
732
+ for structure in view_data["structures"]:
733
+ struct_cypher = f"""
734
+ MATCH (r:Report {{identifier: '{report_id}'}})
735
+ CREATE (s:Structure {{
736
+ identifier: randomUUID(),
737
+ name: '{structure.get("name", "View Structure")}',
738
+ type: 'presentation'
739
+ }})
740
+ CREATE (r)-[:REPORT_HAS_STRUCTURE]->(s)
741
+ """
742
+ await self.query.query(workspace_id, struct_cypher)
743
+
744
+ return report_id