temper-rb 0.5.1
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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +291 -0
- data/lib/temper/act.rb +47 -0
- data/lib/temper/client.rb +96 -0
- data/lib/temper/cognitive_maps.rb +75 -0
- data/lib/temper/connection.rb +113 -0
- data/lib/temper/contexts.rb +54 -0
- data/lib/temper/credentials.rb +138 -0
- data/lib/temper/errors.rb +154 -0
- data/lib/temper/generated/api/access_api.rb +356 -0
- data/lib/temper/generated/api/auditor_api.rb +228 -0
- data/lib/temper/generated/api/blobs_api.rb +785 -0
- data/lib/temper/generated/api/cognitive_maps_api.rb +996 -0
- data/lib/temper/generated/api/contexts_api.rb +1039 -0
- data/lib/temper/generated/api/data_artifact_shapes_api.rb +243 -0
- data/lib/temper/generated/api/data_artifacts_api.rb +261 -0
- data/lib/temper/generated/api/events_api.rb +164 -0
- data/lib/temper/generated/api/facets_api.rb +406 -0
- data/lib/temper/generated/api/graph_api.rb +612 -0
- data/lib/temper/generated/api/health_api.rb +84 -0
- data/lib/temper/generated/api/ingest_api.rb +398 -0
- data/lib/temper/generated/api/invitations_api.rb +514 -0
- data/lib/temper/generated/api/invocations_api.rb +308 -0
- data/lib/temper/generated/api/meta_api.rb +169 -0
- data/lib/temper/generated/api/profile_api.rb +219 -0
- data/lib/temper/generated/api/query_api.rb +97 -0
- data/lib/temper/generated/api/reblocking_api.rb +95 -0
- data/lib/temper/generated/api/relationships_api.rb +332 -0
- data/lib/temper/generated/api/resources_api.rb +1329 -0
- data/lib/temper/generated/api/schema_api.rb +218 -0
- data/lib/temper/generated/api/search_api.rb +97 -0
- data/lib/temper/generated/api/slack_link_api.rb +159 -0
- data/lib/temper/generated/api/steward_api.rb +372 -0
- data/lib/temper/generated/api/teams_api.rb +687 -0
- data/lib/temper/generated/api_client.rb +441 -0
- data/lib/temper/generated/api_error.rb +58 -0
- data/lib/temper/generated/api_model_base.rb +88 -0
- data/lib/temper/generated/configuration.rb +393 -0
- data/lib/temper/generated/models/accept_invitation_response.rb +239 -0
- data/lib/temper/generated/models/act_input.rb +238 -0
- data/lib/temper/generated/models/act_invocation.rb +271 -0
- data/lib/temper/generated/models/act_name.rb +104 -0
- data/lib/temper/generated/models/act_quantity.rb +219 -0
- data/lib/temper/generated/models/act_refusal.rb +192 -0
- data/lib/temper/generated/models/actor_authority.rb +41 -0
- data/lib/temper/generated/models/add_member_request.rb +213 -0
- data/lib/temper/generated/models/advance_watermark_ack.rb +188 -0
- data/lib/temper/generated/models/advance_watermark_request.rb +161 -0
- data/lib/temper/generated/models/agent_authorship.rb +227 -0
- data/lib/temper/generated/models/anchor_address_resolution.rb +106 -0
- data/lib/temper/generated/models/anchor_address_resolution_one_of.rb +189 -0
- data/lib/temper/generated/models/anchor_address_resolution_one_of1.rb +242 -0
- data/lib/temper/generated/models/anchor_address_resolution_one_of2.rb +189 -0
- data/lib/temper/generated/models/anchor_shape.rb +239 -0
- data/lib/temper/generated/models/anchor_verdict.rb +41 -0
- data/lib/temper/generated/models/append_block_payload.rb +250 -0
- data/lib/temper/generated/models/artifact_commit_request.rb +337 -0
- data/lib/temper/generated/models/artifact_commit_response.rb +192 -0
- data/lib/temper/generated/models/artifact_view.rb +466 -0
- data/lib/temper/generated/models/assert_relationship_request.rb +406 -0
- data/lib/temper/generated/models/atlas_edge.rb +327 -0
- data/lib/temper/generated/models/atlas_entry.rb +221 -0
- data/lib/temper/generated/models/atlas_home.rb +195 -0
- data/lib/temper/generated/models/atlas_node.rb +329 -0
- data/lib/temper/generated/models/atlas_subgraph.rb +195 -0
- data/lib/temper/generated/models/audit_citation.rb +220 -0
- data/lib/temper/generated/models/audit_sweep_row.rb +220 -0
- data/lib/temper/generated/models/auditor_dispatch_tick_request.rb +150 -0
- data/lib/temper/generated/models/auditor_dispatch_tick_response.rb +178 -0
- data/lib/temper/generated/models/auditor_job_complete_ack.rb +175 -0
- data/lib/temper/generated/models/bind_team_outcome.rb +218 -0
- data/lib/temper/generated/models/bind_team_request.rb +166 -0
- data/lib/temper/generated/models/blob_commit_response.rb +283 -0
- data/lib/temper/generated/models/blob_delete_ack.rb +191 -0
- data/lib/temper/generated/models/blob_relation_ack.rb +165 -0
- data/lib/temper/generated/models/blob_relation_assert_request.rb +404 -0
- data/lib/temper/generated/models/blob_relation_direction.rb +40 -0
- data/lib/temper/generated/models/blob_relation_edge_direction.rb +40 -0
- data/lib/temper/generated/models/blob_relation_row.rb +390 -0
- data/lib/temper/generated/models/blob_summary.rb +256 -0
- data/lib/temper/generated/models/blob_upload_begin_request.rb +219 -0
- data/lib/temper/generated/models/blob_upload_begin_response.rb +165 -0
- data/lib/temper/generated/models/blob_upload_finalize_request.rb +211 -0
- data/lib/temper/generated/models/blob_upload_progress.rb +220 -0
- data/lib/temper/generated/models/blob_upload_segment_info.rb +227 -0
- data/lib/temper/generated/models/block_chunk_ref.rb +217 -0
- data/lib/temper/generated/models/block_fold_disposition.rb +106 -0
- data/lib/temper/generated/models/block_fold_disposition_one_of.rb +245 -0
- data/lib/temper/generated/models/block_fold_disposition_one_of1.rb +189 -0
- data/lib/temper/generated/models/block_fold_disposition_one_of2.rb +189 -0
- data/lib/temper/generated/models/block_provenance_row.rb +348 -0
- data/lib/temper/generated/models/block_read.rb +106 -0
- data/lib/temper/generated/models/block_read_one_of.rb +311 -0
- data/lib/temper/generated/models/block_read_one_of1.rb +297 -0
- data/lib/temper/generated/models/block_read_one_of2.rb +215 -0
- data/lib/temper/generated/models/block_successor.rb +177 -0
- data/lib/temper/generated/models/blocks_response.rb +194 -0
- data/lib/temper/generated/models/body_storage.rb +40 -0
- data/lib/temper/generated/models/bridge.rb +217 -0
- data/lib/temper/generated/models/bulk_reassign_ack.rb +167 -0
- data/lib/temper/generated/models/bulk_reassign_request.rb +191 -0
- data/lib/temper/generated/models/change_role_request.rb +187 -0
- data/lib/temper/generated/models/charter_block.rb +220 -0
- data/lib/temper/generated/models/charter_disposition.rb +42 -0
- data/lib/temper/generated/models/citation_audit_request.rb +231 -0
- data/lib/temper/generated/models/citation_audit_row.rb +366 -0
- data/lib/temper/generated/models/claimed_audit_job.rb +249 -0
- data/lib/temper/generated/models/claimed_job.rb +220 -0
- data/lib/temper/generated/models/close_invocation_request.rb +197 -0
- data/lib/temper/generated/models/cogmap_analytics_row.rb +220 -0
- data/lib/temper/generated/models/cogmap_detail.rb +224 -0
- data/lib/temper/generated/models/cogmap_foundation_row.rb +247 -0
- data/lib/temper/generated/models/cogmap_grant_body.rb +295 -0
- data/lib/temper/generated/models/cogmap_region_metrics_row.rb +248 -0
- data/lib/temper/generated/models/cogmap_region_row.rb +269 -0
- data/lib/temper/generated/models/cogmap_regulation_row.rb +228 -0
- data/lib/temper/generated/models/cogmap_revoke_body.rb +191 -0
- data/lib/temper/generated/models/cogmap_row.rb +341 -0
- data/lib/temper/generated/models/cogmap_staleness.rb +185 -0
- data/lib/temper/generated/models/combine_node.rb +263 -0
- data/lib/temper/generated/models/combine_op.rb +41 -0
- data/lib/temper/generated/models/composition.rb +203 -0
- data/lib/temper/generated/models/composition_trace.rb +167 -0
- data/lib/temper/generated/models/confidence_band.rb +41 -0
- data/lib/temper/generated/models/content_response.rb +213 -0
- data/lib/temper/generated/models/context_create_request.rb +176 -0
- data/lib/temper/generated/models/context_owner_ref.rb +106 -0
- data/lib/temper/generated/models/context_owner_ref_one_of.rb +166 -0
- data/lib/temper/generated/models/context_owner_ref_one_of1.rb +166 -0
- data/lib/temper/generated/models/context_panorama.rb +221 -0
- data/lib/temper/generated/models/context_row.rb +404 -0
- data/lib/temper/generated/models/context_row_with_counts.rb +430 -0
- data/lib/temper/generated/models/create_cogmap_outcome.rb +217 -0
- data/lib/temper/generated/models/create_cogmap_request.rb +221 -0
- data/lib/temper/generated/models/create_invitation_request.rb +213 -0
- data/lib/temper/generated/models/create_request_body.rb +184 -0
- data/lib/temper/generated/models/create_review_body.rb +148 -0
- data/lib/temper/generated/models/deactivated.rb +189 -0
- data/lib/temper/generated/models/delete_response.rb +165 -0
- data/lib/temper/generated/models/denied.rb +189 -0
- data/lib/temper/generated/models/device_overrides.rb +162 -0
- data/lib/temper/generated/models/discouraged_open_meta_key.rb +191 -0
- data/lib/temper/generated/models/dispatch_tick_request.rb +161 -0
- data/lib/temper/generated/models/dispatch_tick_response.rb +178 -0
- data/lib/temper/generated/models/disposition.rb +41 -0
- data/lib/temper/generated/models/doc_type_description.rb +247 -0
- data/lib/temper/generated/models/doc_type_summary.rb +219 -0
- data/lib/temper/generated/models/drift_sweep_row.rb +258 -0
- data/lib/temper/generated/models/edge_facet_row.rb +332 -0
- data/lib/temper/generated/models/edge_facet_set_request.rb +288 -0
- data/lib/temper/generated/models/edge_facets_response.rb +193 -0
- data/lib/temper/generated/models/edge_filter.rb +192 -0
- data/lib/temper/generated/models/edge_kind.rb +42 -0
- data/lib/temper/generated/models/element_event.rb +307 -0
- data/lib/temper/generated/models/element_kind.rb +40 -0
- data/lib/temper/generated/models/embed_dispatch_summary.rb +355 -0
- data/lib/temper/generated/models/enforcement_mode.rb +40 -0
- data/lib/temper/generated/models/entitlements.rb +234 -0
- data/lib/temper/generated/models/entry_bounds.rb +247 -0
- data/lib/temper/generated/models/error_body.rb +164 -0
- data/lib/temper/generated/models/error_detail.rb +201 -0
- data/lib/temper/generated/models/error_details.rb +105 -0
- data/lib/temper/generated/models/event_cursor_response.rb +150 -0
- data/lib/temper/generated/models/event_trail.rb +241 -0
- data/lib/temper/generated/models/exact_arm.rb +226 -0
- data/lib/temper/generated/models/exact_hit.rb +193 -0
- data/lib/temper/generated/models/extent.rb +106 -0
- data/lib/temper/generated/models/extent_one_of.rb +189 -0
- data/lib/temper/generated/models/extent_one_of1.rb +189 -0
- data/lib/temper/generated/models/extent_one_of2.rb +215 -0
- data/lib/temper/generated/models/facet_ack.rb +168 -0
- data/lib/temper/generated/models/facet_predicate.rb +191 -0
- data/lib/temper/generated/models/facet_retract_ack.rb +165 -0
- data/lib/temper/generated/models/facet_set_request.rb +304 -0
- data/lib/temper/generated/models/finalize_payload.rb +212 -0
- data/lib/temper/generated/models/fold_relationship_request.rb +248 -0
- data/lib/temper/generated/models/grant_outcome.rb +166 -0
- data/lib/temper/generated/models/graph_edge_row.rb +421 -0
- data/lib/temper/generated/models/group_key_meta.rb +217 -0
- data/lib/temper/generated/models/health_response.rb +202 -0
- data/lib/temper/generated/models/home_cogmap.rb +297 -0
- data/lib/temper/generated/models/home_context.rb +281 -0
- data/lib/temper/generated/models/id_kind.rb +104 -0
- data/lib/temper/generated/models/id_provenance.rb +105 -0
- data/lib/temper/generated/models/id_provenance_one_of.rb +215 -0
- data/lib/temper/generated/models/id_provenance_one_of1.rb +215 -0
- data/lib/temper/generated/models/id_set.rb +214 -0
- data/lib/temper/generated/models/idp_revocation.rb +41 -0
- data/lib/temper/generated/models/illegal_transition.rb +225 -0
- data/lib/temper/generated/models/ingest_create_response.rb +105 -0
- data/lib/temper/generated/models/ingest_delta.rb +334 -0
- data/lib/temper/generated/models/ingest_payload.rb +478 -0
- data/lib/temper/generated/models/ingest_state.rb +40 -0
- data/lib/temper/generated/models/inherited_read_grant.rb +219 -0
- data/lib/temper/generated/models/inherited_share.rb +192 -0
- data/lib/temper/generated/models/input_source.rb +106 -0
- data/lib/temper/generated/models/input_source_one_of.rb +227 -0
- data/lib/temper/generated/models/input_source_one_of1.rb +189 -0
- data/lib/temper/generated/models/input_source_one_of2.rb +189 -0
- data/lib/temper/generated/models/insufficient_authority.rb +241 -0
- data/lib/temper/generated/models/intention.rb +212 -0
- data/lib/temper/generated/models/invitation_status.rb +42 -0
- data/lib/temper/generated/models/invitation_token_request.rb +165 -0
- data/lib/temper/generated/models/invitee_invitation.rb +447 -0
- data/lib/temper/generated/models/invocation_ack.rb +191 -0
- data/lib/temper/generated/models/invocation_act_row.rb +269 -0
- data/lib/temper/generated/models/invocation_close_ack.rb +213 -0
- data/lib/temper/generated/models/invocation_summary.rb +296 -0
- data/lib/temper/generated/models/invocation_view.rb +433 -0
- data/lib/temper/generated/models/join_request.rb +403 -0
- data/lib/temper/generated/models/join_request_status.rb +42 -0
- data/lib/temper/generated/models/kind_owner_input.rb +105 -0
- data/lib/temper/generated/models/kind_owner_input_one_of.rb +164 -0
- data/lib/temper/generated/models/kind_owner_input_one_of1.rb +164 -0
- data/lib/temper/generated/models/lineage_node.rb +326 -0
- data/lib/temper/generated/models/managed_meta.rb +249 -0
- data/lib/temper/generated/models/match_location.rb +188 -0
- data/lib/temper/generated/models/materialize_ack.rb +307 -0
- data/lib/temper/generated/models/materialize_delta.rb +296 -0
- data/lib/temper/generated/models/materialize_request.rb +150 -0
- data/lib/temper/generated/models/merge_policy.rb +40 -0
- data/lib/temper/generated/models/meta_update_payload.rb +358 -0
- data/lib/temper/generated/models/narrowed_by.rb +210 -0
- data/lib/temper/generated/models/no_prior_standing.rb +189 -0
- data/lib/temper/generated/models/no_standing.rb +189 -0
- data/lib/temper/generated/models/node_home.rb +40 -0
- data/lib/temper/generated/models/open_invocation_request.rb +204 -0
- data/lib/temper/generated/models/open_meta_convention.rb +180 -0
- data/lib/temper/generated/models/ord_op.rb +42 -0
- data/lib/temper/generated/models/orphan_node.rb +264 -0
- data/lib/temper/generated/models/outcome_declaration.rb +177 -0
- data/lib/temper/generated/models/pending_invitation_counts.rb +177 -0
- data/lib/temper/generated/models/plan_refusal.rb +220 -0
- data/lib/temper/generated/models/plan_refusal_details.rb +167 -0
- data/lib/temper/generated/models/polarity.rb +40 -0
- data/lib/temper/generated/models/profile.rb +313 -0
- data/lib/temper/generated/models/profile_auth_link.rb +332 -0
- data/lib/temper/generated/models/profile_update_request.rb +169 -0
- data/lib/temper/generated/models/profile_with_entitlements.rb +344 -0
- data/lib/temper/generated/models/property_op.rb +106 -0
- data/lib/temper/generated/models/property_op_one_of.rb +189 -0
- data/lib/temper/generated/models/property_op_one_of1.rb +217 -0
- data/lib/temper/generated/models/property_op_one_of2.rb +227 -0
- data/lib/temper/generated/models/property_predicate.rb +191 -0
- data/lib/temper/generated/models/provenance_source.rb +106 -0
- data/lib/temper/generated/models/provenance_source_one_of.rb +214 -0
- data/lib/temper/generated/models/provenance_source_one_of1.rb +214 -0
- data/lib/temper/generated/models/provenance_source_one_of2.rb +216 -0
- data/lib/temper/generated/models/public_system_settings.rb +169 -0
- data/lib/temper/generated/models/quantity_scale.rb +106 -0
- data/lib/temper/generated/models/quantity_scale_one_of.rb +189 -0
- data/lib/temper/generated/models/quantity_scale_one_of1.rb +215 -0
- data/lib/temper/generated/models/quantity_scale_one_of2.rb +189 -0
- data/lib/temper/generated/models/query_response.rb +195 -0
- data/lib/temper/generated/models/reassign_ack.rb +191 -0
- data/lib/temper/generated/models/reassign_context_outcome.rb +243 -0
- data/lib/temper/generated/models/reassign_context_request.rb +166 -0
- data/lib/temper/generated/models/reassign_resource_request.rb +165 -0
- data/lib/temper/generated/models/reblock_candidate.rb +192 -0
- data/lib/temper/generated/models/reblock_outcome.rb +109 -0
- data/lib/temper/generated/models/reblock_outcome_one_of.rb +165 -0
- data/lib/temper/generated/models/reblock_outcome_one_of1.rb +165 -0
- data/lib/temper/generated/models/reblock_outcome_one_of1_in_progress.rb +166 -0
- data/lib/temper/generated/models/reblock_outcome_one_of2.rb +165 -0
- data/lib/temper/generated/models/reblock_outcome_one_of3.rb +165 -0
- data/lib/temper/generated/models/reblock_outcome_one_of4.rb +165 -0
- data/lib/temper/generated/models/reblock_outcome_one_of4_error.rb +165 -0
- data/lib/temper/generated/models/reblock_outcome_one_of_reblocked.rb +165 -0
- data/lib/temper/generated/models/reblock_receipt.rb +259 -0
- data/lib/temper/generated/models/reblock_request.rb +215 -0
- data/lib/temper/generated/models/reblock_scope.rb +106 -0
- data/lib/temper/generated/models/reblock_scope_one_of.rb +166 -0
- data/lib/temper/generated/models/reblock_scope_one_of1.rb +166 -0
- data/lib/temper/generated/models/reblock_summary.rb +350 -0
- data/lib/temper/generated/models/reconcile_cogmap_request.rb +199 -0
- data/lib/temper/generated/models/reconcile_edge.rb +253 -0
- data/lib/temper/generated/models/reconcile_edge_tombstone.rb +217 -0
- data/lib/temper/generated/models/reconcile_entry.rb +318 -0
- data/lib/temper/generated/models/reconcile_outcome.rb +327 -0
- data/lib/temper/generated/models/reconcile_telos.rb +167 -0
- data/lib/temper/generated/models/reconcile_telos_block.rb +191 -0
- data/lib/temper/generated/models/reconcile_tombstone.rb +165 -0
- data/lib/temper/generated/models/refusal.rb +112 -0
- data/lib/temper/generated/models/refusal_reason.rb +104 -0
- data/lib/temper/generated/models/region_disclosure.rb +193 -0
- data/lib/temper/generated/models/region_hit.rb +192 -0
- data/lib/temper/generated/models/relationship_ack.rb +165 -0
- data/lib/temper/generated/models/relationship_target.rb +40 -0
- data/lib/temper/generated/models/remove_member_outcome.rb +165 -0
- data/lib/temper/generated/models/rename_context_outcome.rb +300 -0
- data/lib/temper/generated/models/rename_context_request.rb +166 -0
- data/lib/temper/generated/models/requested.rb +189 -0
- data/lib/temper/generated/models/residual_bucket.rb +191 -0
- data/lib/temper/generated/models/residual_context.rb +201 -0
- data/lib/temper/generated/models/residual_groups.rb +193 -0
- data/lib/temper/generated/models/residual_owned_reach.rb +202 -0
- data/lib/temper/generated/models/resource_annotate_request.rb +261 -0
- data/lib/temper/generated/models/resource_create_request.rb +355 -0
- data/lib/temper/generated/models/resource_facet_row.rb +317 -0
- data/lib/temper/generated/models/resource_facets.rb +226 -0
- data/lib/temper/generated/models/resource_facets_response.rb +193 -0
- data/lib/temper/generated/models/resource_filter.rb +265 -0
- data/lib/temper/generated/models/resource_grant_body.rb +295 -0
- data/lib/temper/generated/models/resource_hit.rb +216 -0
- data/lib/temper/generated/models/resource_lineage.rb +224 -0
- data/lib/temper/generated/models/resource_list_response.rb +313 -0
- data/lib/temper/generated/models/resource_revoke_body.rb +191 -0
- data/lib/temper/generated/models/resource_section.rb +41 -0
- data/lib/temper/generated/models/resource_sort_field.rb +45 -0
- data/lib/temper/generated/models/resource_update_request.rb +379 -0
- data/lib/temper/generated/models/resource_view.rb +592 -0
- data/lib/temper/generated/models/restore_context_outcome.rb +274 -0
- data/lib/temper/generated/models/retire_context_outcome.rb +247 -0
- data/lib/temper/generated/models/return_spec.rb +189 -0
- data/lib/temper/generated/models/retype_relationship_request.rb +290 -0
- data/lib/temper/generated/models/revoke_outcome.rb +165 -0
- data/lib/temper/generated/models/revoked.rb +189 -0
- data/lib/temper/generated/models/reweight_relationship_request.rb +264 -0
- data/lib/temper/generated/models/score_kind.rb +104 -0
- data/lib/temper/generated/models/scoring.rb +192 -0
- data/lib/temper/generated/models/search_params.rb +254 -0
- data/lib/temper/generated/models/search_reason.rb +41 -0
- data/lib/temper/generated/models/search_response.rb +217 -0
- data/lib/temper/generated/models/search_result_row.rb +343 -0
- data/lib/temper/generated/models/search_scope.rb +41 -0
- data/lib/temper/generated/models/search_scope_info.rb +199 -0
- data/lib/temper/generated/models/segment_info.rb +200 -0
- data/lib/temper/generated/models/segmented_begin.rb +212 -0
- data/lib/temper/generated/models/segmented_begin_response.rb +247 -0
- data/lib/temper/generated/models/shape_declare_request.rb +315 -0
- data/lib/temper/generated/models/shape_emptiness.rb +42 -0
- data/lib/temper/generated/models/shape_view.rb +438 -0
- data/lib/temper/generated/models/share_context_outcome.rb +218 -0
- data/lib/temper/generated/models/share_context_request.rb +166 -0
- data/lib/temper/generated/models/slack_disconnect_request.rb +166 -0
- data/lib/temper/generated/models/slack_disconnect_response.rb +168 -0
- data/lib/temper/generated/models/slack_disconnected_principal.rb +269 -0
- data/lib/temper/generated/models/slice_request.rb +216 -0
- data/lib/temper/generated/models/sort_order.rb +40 -0
- data/lib/temper/generated/models/stage_disposition.rb +42 -0
- data/lib/temper/generated/models/stage_input.rb +105 -0
- data/lib/temper/generated/models/stage_input_one_of.rb +241 -0
- data/lib/temper/generated/models/stage_input_one_of1.rb +253 -0
- data/lib/temper/generated/models/stage_input_trace.rb +241 -0
- data/lib/temper/generated/models/stage_node.rb +105 -0
- data/lib/temper/generated/models/stage_output.rb +105 -0
- data/lib/temper/generated/models/stage_output_one_of.rb +217 -0
- data/lib/temper/generated/models/stage_output_one_of1.rb +217 -0
- data/lib/temper/generated/models/stage_relation.rb +40 -0
- data/lib/temper/generated/models/stage_result.rb +423 -0
- data/lib/temper/generated/models/stage_trace.rb +451 -0
- data/lib/temper/generated/models/standing.rb +43 -0
- data/lib/temper/generated/models/standing_shape.rb +355 -0
- data/lib/temper/generated/models/subscription.rb +267 -0
- data/lib/temper/generated/models/subscription_override.rb +193 -0
- data/lib/temper/generated/models/system_access_details.rb +206 -0
- data/lib/temper/generated/models/team_create_request.rb +217 -0
- data/lib/temper/generated/models/team_detail.rb +313 -0
- data/lib/temper/generated/models/team_invitation.rb +406 -0
- data/lib/temper/generated/models/team_member_detail.rb +265 -0
- data/lib/temper/generated/models/team_member_row.rb +265 -0
- data/lib/temper/generated/models/team_member_source.rb +40 -0
- data/lib/temper/generated/models/team_role.rb +42 -0
- data/lib/temper/generated/models/team_row.rb +287 -0
- data/lib/temper/generated/models/team_update_request.rb +159 -0
- data/lib/temper/generated/models/territory.rb +298 -0
- data/lib/temper/generated/models/territory_kind.rb +41 -0
- data/lib/temper/generated/models/territory_overview.rb +223 -0
- data/lib/temper/generated/models/unbind_team_outcome.rb +218 -0
- data/lib/temper/generated/models/unrecognized_standing.rb +215 -0
- data/lib/temper/generated/models/unshare_context_outcome.rb +218 -0
- data/lib/temper/generated/models/vault_config.rb +174 -0
- data/lib/temper/generated/models/via_entry.rb +305 -0
- data/lib/temper/generated/models/wide_arm.rb +252 -0
- data/lib/temper/generated/models/wide_hit.rb +193 -0
- data/lib/temper/generated/version.rb +15 -0
- data/lib/temper/generated.rb +402 -0
- data/lib/temper/refs.rb +36 -0
- data/lib/temper/resources.rb +68 -0
- data/lib/temper/validate.rb +127 -0
- data/lib/temper/version.rb +11 -0
- data/lib/temper.rb +47 -0
- metadata +525 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 053faaf3ac47a6d158e0b6b01f1ee9b676721480efdb0d37da4a5a78c4852d13
|
|
4
|
+
data.tar.gz: 916b5ba30ee421ec644905e3dedafb900c6189536fe0afd3b1bf8fa561584f7e
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 7ee3400fe23a21d1ed53d766001502080c5c01b719a0b40602c8205f83ea7ba612b5c855fb3264955784c238df67e94505e27fb89d2b7cd1b1d4b0f142cc9128
|
|
7
|
+
data.tar.gz: c92c7ad413560450bdc8801f49a6c5c52cb5140e2452b8564aee7bd9c7d072233758056025218617d63728767214e94e2b86dd7731df07096ffdb7fbcc12352c
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Tasker Systems
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
# temper-rb
|
|
2
|
+
|
|
3
|
+
A pure-Ruby SDK for the [Temper](https://temperkb.io) knowledge-base API.
|
|
4
|
+
|
|
5
|
+
There is no native extension: one source gem, no compiler on the install box, no
|
|
6
|
+
platform matrix. The client core is generated from the API's `openapi.json` and
|
|
7
|
+
committed, so building and testing this gem needs neither Docker nor a JVM.
|
|
8
|
+
|
|
9
|
+
> **The integration how-to lives in the repo:**
|
|
10
|
+
> [docs/sdks/temper-rb.md](https://github.com/tasker-systems/temper/blob/main/docs/sdks/temper-rb.md).
|
|
11
|
+
> It covers the two callers, both machine-credential mint paths, the token
|
|
12
|
+
> lifecycle, attribution across the enqueue boundary, the error taxonomy, and
|
|
13
|
+
> going live. This README is the quickstart.
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```ruby
|
|
18
|
+
gem 'temper-rb'
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Ruby >= 3.1.
|
|
22
|
+
|
|
23
|
+
## Configure
|
|
24
|
+
|
|
25
|
+
```ruby
|
|
26
|
+
Temper.configure do |c|
|
|
27
|
+
c.base_url = ENV.fetch('TEMPER_API_URL')
|
|
28
|
+
c.device_id = ENV['TEMPER_DEVICE_ID'] # optional; sets X-Temper-Device-Id
|
|
29
|
+
end
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The connection is **process-global**. The **token is per call**. Constructing a
|
|
33
|
+
`Temper::Client` does no I/O, so build one per request if you like.
|
|
34
|
+
|
|
35
|
+
## Puma — a token the caller already holds
|
|
36
|
+
|
|
37
|
+
```ruby
|
|
38
|
+
client = Temper::Client.new(
|
|
39
|
+
credentials: Temper::Credentials::BearerToken.new(session_token))
|
|
40
|
+
|
|
41
|
+
client.resources.create(
|
|
42
|
+
title: 'Postmortem', context_ref: '@dana/incidents',
|
|
43
|
+
doc_type_name: 'note', content: markdown,
|
|
44
|
+
act: Temper::Act.new(confidence: :probable, reasoning: 'summarised the incident'))
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
A `BearerToken` does no I/O and **cannot refresh** — `refresh!` raises. A user's
|
|
48
|
+
token is not the app's to re-mint.
|
|
49
|
+
|
|
50
|
+
`Temper::Act` refuses to be built with `reasoning`, `rationale`, `persona`, or
|
|
51
|
+
`model` unless you also give `confidence` — the server would reject it with a
|
|
52
|
+
400, so the gem rejects it locally instead.
|
|
53
|
+
|
|
54
|
+
## Sidekiq — a machine principal
|
|
55
|
+
|
|
56
|
+
```ruby
|
|
57
|
+
CREDENTIALS = Temper::Credentials::ClientCredentials.new(
|
|
58
|
+
token_url: ENV.fetch('TEMPER_M2M_TOKEN_URL'),
|
|
59
|
+
client_id: ENV.fetch('TEMPER_M2M_CLIENT_ID'),
|
|
60
|
+
client_secret: ENV.fetch('TEMPER_M2M_CLIENT_SECRET'),
|
|
61
|
+
audience: ENV['TEMPER_M2M_AUDIENCE']) # Auth0 only — omit for temper-issued
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
It caches the token until 60 seconds before its absolute expiry, mints under a
|
|
65
|
+
mutex (Puma threads race a cold cache), and re-mints once on a 401 — because a job
|
|
66
|
+
that holds a token across a long unit of work can outlive it, and
|
|
67
|
+
refresh-ahead-of-expiry alone does not save you there.
|
|
68
|
+
|
|
69
|
+
### Two mint paths
|
|
70
|
+
|
|
71
|
+
The token request is form-encoded on both (RFC 6749 §4). Only the config differs.
|
|
72
|
+
|
|
73
|
+
| | Auth0-issued (`temper admin machine provision`) | Temper-issued (`temper admin machine issue`) |
|
|
74
|
+
|---|---|---|
|
|
75
|
+
| `client_id` | your Auth0 M2M app's client id | minted by temper, prefixed `tmpr_` |
|
|
76
|
+
| `client_secret` | from Auth0 | printed **once** at `issue` |
|
|
77
|
+
| `token_url` | your Auth0 tenant's `/oauth/token` | **your own instance's** `/oauth/token` |
|
|
78
|
+
| `audience` | **required** — must equal the API's `AUTH_AUDIENCE` | **omit it** |
|
|
79
|
+
|
|
80
|
+
Temper's own authorization server mints with its server-side `AS_AUDIENCE` and
|
|
81
|
+
ignores a request-supplied one, so the SDK leaves `audience` off the wire entirely
|
|
82
|
+
rather than sending an empty string.
|
|
83
|
+
|
|
84
|
+
## Correlation across the enqueue boundary
|
|
85
|
+
|
|
86
|
+
The Puma request writes as the signed-in user; the Sidekiq job it enqueues writes
|
|
87
|
+
as the **machine profile**. Two authors, honestly — the machine really did make the
|
|
88
|
+
second write. A correlation id stitches them together in the event ledger.
|
|
89
|
+
|
|
90
|
+
```ruby
|
|
91
|
+
correlation = SecureRandom.uuid
|
|
92
|
+
PostmortemJob.perform_async(correlation)
|
|
93
|
+
# ...and in the worker:
|
|
94
|
+
act = Temper::Act.new(confidence: :probable, correlation: correlation)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Correlation is provenance, never authorization. Nothing gates on it, and an act
|
|
98
|
+
that supplies none self-roots to its own event id — so you may always omit it.
|
|
99
|
+
|
|
100
|
+
## Errors
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
Temper::Error
|
|
104
|
+
├─ Temper::TransientError # let it escape → Sidekiq retries
|
|
105
|
+
│ ├─ RateLimited (429, #retry_after)
|
|
106
|
+
│ ├─ ServerError (5xx)
|
|
107
|
+
│ └─ ConnectionError (timeout / refused)
|
|
108
|
+
└─ Temper::PermanentError # rescue it → dead-letter
|
|
109
|
+
├─ Unauthorized (401)
|
|
110
|
+
├─ Forbidden (403)
|
|
111
|
+
│ └─ SystemAccessRequired
|
|
112
|
+
├─ NotFound (404)
|
|
113
|
+
├─ Conflict (409)
|
|
114
|
+
└─ BadRequest (400 / 422)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Every exception carries `#status`, `#code`, `#message`, and `#details`.
|
|
118
|
+
|
|
119
|
+
`SystemAccessRequired` adds `#refusal` — a **typed** reason the server refused,
|
|
120
|
+
which is what lets a worker tell "never granted" from "granted and then revoked"
|
|
121
|
+
without matching on the message string:
|
|
122
|
+
|
|
123
|
+
```ruby
|
|
124
|
+
rescue Temper::SystemAccessRequired => e
|
|
125
|
+
case e.refusal
|
|
126
|
+
when Temper::Generated::Denied then request_access! # never granted — ask
|
|
127
|
+
when Temper::Generated::Requested then wait # asked, pending review
|
|
128
|
+
when Temper::Generated::Revoked then alert_operator! # had it, lost it
|
|
129
|
+
else log.warn("refused: #{e.refusal_kind}") # a reason newer than this gem
|
|
130
|
+
end
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Data-bearing refusals carry their payload: an `IllegalTransition` names the `act`
|
|
134
|
+
it refused and the standing it refused it `from`. `#refusal` is `nil` when the
|
|
135
|
+
reason is one this gem was not generated against — `#refusal_kind` still returns
|
|
136
|
+
the name the server used, so an unfamiliar refusal is logged rather than lost.
|
|
137
|
+
|
|
138
|
+
The split is load-bearing, not decorative: Sidekiq retries a job whose exception
|
|
139
|
+
escapes, so a 409 classified transient would spin forever and a 503 classified
|
|
140
|
+
permanent would be silently dropped.
|
|
141
|
+
|
|
142
|
+
Idempotent reads retry three times on 5xx and transport failures. **Writes are
|
|
143
|
+
never auto-retried.** The SDK classifies; it does not decide to re-submit.
|
|
144
|
+
|
|
145
|
+
## Composition bounds raise before the request `[2026-08-28]`
|
|
146
|
+
|
|
147
|
+
`/api/query`'s contract publishes ceilings on what one composition may declare, and the
|
|
148
|
+
generated models enforce them in their attribute writers — which `initialize` calls — so
|
|
149
|
+
these raise `ArgumentError` locally rather than returning a `BadRequest` with a typed
|
|
150
|
+
refusal. The writers are **not** gated on `client_side_validation`, so this cannot be
|
|
151
|
+
switched off.
|
|
152
|
+
|
|
153
|
+
| field | ceiling |
|
|
154
|
+
|---|---|
|
|
155
|
+
| `Composition#stages` | 64 |
|
|
156
|
+
| `Intention#query` | 4096 |
|
|
157
|
+
| `IdSet#ids` | 256 |
|
|
158
|
+
| `ResourceFilter#doc_type` / `#tags`, `EdgeFilter#labels` | 256 |
|
|
159
|
+
|
|
160
|
+
**This is a behaviour change for code that already builds large plans**: a 300-id `IdSet`
|
|
161
|
+
used to construct fine and reach the server. It now raises before any HTTP call.
|
|
162
|
+
|
|
163
|
+
**The gem counts characters; the server counts bytes.** A 4096-character CJK question is
|
|
164
|
+
8192 bytes — it constructs cleanly here and is refused server-side as `intention_too_long`.
|
|
165
|
+
The skew is one-directional (a UTF-8 string is never fewer bytes than characters), so the
|
|
166
|
+
gem can only under-enforce, never refuse something the server would have run.
|
|
167
|
+
|
|
168
|
+
The per-stage predicate and probe caps and the aggregate embed budget
|
|
169
|
+
(`intention_budget_exceeded`) are deliberately not enforced here — neither is a contract
|
|
170
|
+
fact — and arrive as refusals.
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
## Going live
|
|
174
|
+
|
|
175
|
+
Authentication is not authorization. A valid M2M token does **not** get you in on
|
|
176
|
+
its own: temper keeps a registration allowlist, so your `client_id` must be
|
|
177
|
+
registered before your first call. An unregistered (or revoked) client
|
|
178
|
+
authenticates cleanly at its issuer and is then rejected with a terminal
|
|
179
|
+
`Unauthorized` — `client 'X' is not registered with this instance` — which the SDK
|
|
180
|
+
classifies as a `PermanentError` (a Sidekiq worker dead-letters it rather than
|
|
181
|
+
retrying). Registered but un-granted, you then get a `SystemAccessRequired` 403.
|
|
182
|
+
Those are the two walls, in that order.
|
|
183
|
+
|
|
184
|
+
Registration and reach happen in one command, on whichever mint path you chose:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
# Auth0-issued: register the M2M application you already created
|
|
188
|
+
temper admin machine provision \
|
|
189
|
+
--client-id "$TEMPER_M2M_CLIENT_ID" --label "acme-worker" \
|
|
190
|
+
--owner-team acme-eng --team acme-eng:member --cogmap <map-ref>
|
|
191
|
+
|
|
192
|
+
# Temper-issued: temper mints the client id and secret; the secret prints once
|
|
193
|
+
temper admin machine issue \
|
|
194
|
+
--label "acme-worker" \
|
|
195
|
+
--owner-team acme-eng --team acme-eng:member --cogmap <map-ref>
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Each `--team` gives **team membership** for read reach; each `--cogmap` applies a
|
|
199
|
+
**cogmap write grant**. Both are repeatable — reach is plural and explicit, and is
|
|
200
|
+
never inferred from `--owner-team` (which records the machine's owner only).
|
|
201
|
+
|
|
202
|
+
This need not be an operator ticket: minting is authorized for a system admin **or
|
|
203
|
+
the owner of the team that will own the machine**, so a team owner can register
|
|
204
|
+
their own team's machine. A teamless machine is admin-only.
|
|
205
|
+
|
|
206
|
+
**Rotation.** `temper admin machine rotate-secret` rolls a temper-issued **secret**
|
|
207
|
+
(same `client_id`), keeping the previous one valid for a grace window while you
|
|
208
|
+
redeploy the app with the new secret. `temper admin machine rebind` is a different
|
|
209
|
+
operation: a **new `client_id`** bound to the same agent profile, for rotating the
|
|
210
|
+
Auth0 application behind a machine — and it is system-admin only. Rotating an Auth0
|
|
211
|
+
*secret* needs no temper action at all.
|
|
212
|
+
|
|
213
|
+
See
|
|
214
|
+
[docs/guides/machine-credentials.md](https://github.com/tasker-systems/temper/blob/main/docs/guides/machine-credentials.md)
|
|
215
|
+
for the operator's side.
|
|
216
|
+
|
|
217
|
+
Assert it worked at boot rather than discovering it on the first write:
|
|
218
|
+
|
|
219
|
+
```ruby
|
|
220
|
+
Temper::Client.new(credentials: CREDENTIALS).whoami
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
An unregistered client surfaces as `Unauthorized` naming the client id; a
|
|
224
|
+
registered-but-under-granted one surfaces as `Forbidden` / `SystemAccessRequired`
|
|
225
|
+
naming the missing grant — both from the server's `error.details`, not a bare 4xx.
|
|
226
|
+
|
|
227
|
+
## Forking
|
|
228
|
+
|
|
229
|
+
The connection holds sockets. Call `Temper.reset_connection!` in a forked worker:
|
|
230
|
+
|
|
231
|
+
```ruby
|
|
232
|
+
# config/puma.rb
|
|
233
|
+
on_worker_boot { Temper.reset_connection! }
|
|
234
|
+
|
|
235
|
+
# config/initializers/sidekiq.rb
|
|
236
|
+
Sidekiq.configure_server { |_| Temper.reset_connection! }
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
Strictly speaking the sockets are already safe: `connection_pool` (>= 2.4, which
|
|
240
|
+
`net-http-persistent` pools through) drops them from a `Process._fork` hook, and
|
|
241
|
+
this gem's test suite proves a forked child opens its own socket. The hooks above
|
|
242
|
+
clear *this gem's* memoized client rather than relying on a transitive
|
|
243
|
+
dependency's default. Keep them.
|
|
244
|
+
|
|
245
|
+
## Addressing
|
|
246
|
+
|
|
247
|
+
Resources are addressed by **ref**: a bare UUID, or the decorated
|
|
248
|
+
`sluggify(title)-<uuid>` form. Resolution is trailing-UUID-only, so a stale slug
|
|
249
|
+
half is harmless.
|
|
250
|
+
|
|
251
|
+
```ruby
|
|
252
|
+
client.resources.show('p4-design-the-gem-019f4912-3f20-7fd3-814f-13a5ddbe3cd7')
|
|
253
|
+
client.resources.show('019f4912-3f20-7fd3-814f-13a5ddbe3cd7') # identical
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
`Temper.parse_ref` is available directly, and never touches the network.
|
|
257
|
+
|
|
258
|
+
## Cognitive maps
|
|
259
|
+
|
|
260
|
+
The SDK authors into a map incrementally — `cognitive_maps.author` (ingest with
|
|
261
|
+
`home_cogmap_id`), `assert_relationship`, and `set_facet` — all paths where the
|
|
262
|
+
server chunks and embeds for you.
|
|
263
|
+
|
|
264
|
+
**Bulk reconcile is not exposed.** `PUT /api/cognitive-maps/{id}` takes a
|
|
265
|
+
pre-embedded desired-state manifest: its `chunks_packed` is a required,
|
|
266
|
+
client-computed 768-dimension BGE embedding, carried verbatim with no server-side
|
|
267
|
+
fallback. Ruby has no embedder, so that path is physically out of reach. It is a
|
|
268
|
+
CLI operator's job, not a Rails request's. If you truly need it, reach
|
|
269
|
+
`Temper::Generated::CognitiveMapsApi#reconcile` and pack the chunks yourself.
|
|
270
|
+
|
|
271
|
+
## Versioning
|
|
272
|
+
|
|
273
|
+
`Temper::VERSION` is the gem's own SemVer. `Temper::CONTRACT_VERSION` names the
|
|
274
|
+
`openapi.json` it was generated against. They answer different questions and are
|
|
275
|
+
not forced to agree.
|
|
276
|
+
|
|
277
|
+
## Development
|
|
278
|
+
|
|
279
|
+
```bash
|
|
280
|
+
bundle install
|
|
281
|
+
bundle exec rake # rubocop + rspec
|
|
282
|
+
bundle exec rake generate # regenerate lib/temper/generated/** (needs Docker)
|
|
283
|
+
bundle exec rake drift # fail if the committed core drifts from the contract
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
`rake generate` is the only writer of `lib/temper/generated/**`. Never hand-edit
|
|
287
|
+
that tree; the hand-written skin lives beside it, in `lib/temper/*.rb`.
|
|
288
|
+
|
|
289
|
+
## License
|
|
290
|
+
|
|
291
|
+
MIT.
|
data/lib/temper/act.rb
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Temper
|
|
4
|
+
# Act context for a write. Optional on every call.
|
|
5
|
+
#
|
|
6
|
+
# The constructor invariant mirrors ActInput::into_act_context: Rust's
|
|
7
|
+
# AgentAuthorship.confidence is non-Option, so authorship without confidence is
|
|
8
|
+
# a 400. Rejecting it here is the parse-don't-validate answer -- an invalid Act
|
|
9
|
+
# cannot be constructed, so no call site can send one.
|
|
10
|
+
#
|
|
11
|
+
# `correlation` and `invocation` are exempt: correlation is provenance, never
|
|
12
|
+
# authorship, and an act with no supplied correlation self-roots to its own
|
|
13
|
+
# event id. Nothing gates on it, so the gem may always omit it.
|
|
14
|
+
class Act
|
|
15
|
+
AUTHORSHIP_FIELDS = %i[reasoning rationale persona model].freeze
|
|
16
|
+
|
|
17
|
+
def initialize(confidence: nil, reasoning: nil, rationale: nil, persona: nil, model: nil,
|
|
18
|
+
correlation: nil, invocation: nil)
|
|
19
|
+
authorship = { reasoning: reasoning, rationale: rationale, persona: persona, model: model }
|
|
20
|
+
require_confidence!(confidence, authorship)
|
|
21
|
+
|
|
22
|
+
@fields = authorship.merge(
|
|
23
|
+
confidence: confidence&.to_s,
|
|
24
|
+
correlation_id: correlation,
|
|
25
|
+
invocation_id: invocation
|
|
26
|
+
).compact.freeze
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Symbol-keyed, nils omitted: the server distinguishes an absent key from null.
|
|
30
|
+
# These are the seven ActInput wire keys, which flatten into ~30 write bodies
|
|
31
|
+
# and onto the query string of DELETE /api/resources/{id}.
|
|
32
|
+
def to_h
|
|
33
|
+
@fields.dup
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def require_confidence!(confidence, authorship)
|
|
39
|
+
return unless confidence.nil?
|
|
40
|
+
|
|
41
|
+
supplied = authorship.compact.keys
|
|
42
|
+
return if supplied.empty?
|
|
43
|
+
|
|
44
|
+
raise ArgumentError, "Temper::Act requires `confidence:` when supplying #{supplied.join(', ')}"
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Temper
|
|
4
|
+
# A cheap façade over the process-global connection. Holds a credential and
|
|
5
|
+
# nothing else; constructing one does no I/O, so a Puma request can build one
|
|
6
|
+
# per user and a Sidekiq process can memoize one.
|
|
7
|
+
class Client
|
|
8
|
+
MAX_READ_ATTEMPTS = 3
|
|
9
|
+
# 200ms, 400ms -- mirroring MAX_ATTEMPTS and the backoff in
|
|
10
|
+
# crates/temper-client/src/http.rs.
|
|
11
|
+
DEFAULT_BACKOFF = ->(attempt) { sleep(0.2 * (2**(attempt - 1))) }
|
|
12
|
+
|
|
13
|
+
def initialize(credentials:, backoff: DEFAULT_BACKOFF)
|
|
14
|
+
@credentials = credentials
|
|
15
|
+
@backoff = backoff
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Assert the machine profile resolved, and report what it can reach, rather
|
|
19
|
+
# than discovering it on the first write.
|
|
20
|
+
#
|
|
21
|
+
# Authentication is not authorization. A minted M2M token does not even yield a
|
|
22
|
+
# profile on its own: the client_id must already be registered (lookup-or-401 --
|
|
23
|
+
# there is no JIT-create branch), and then, without a cogmap write grant and team
|
|
24
|
+
# membership, every call authenticates cleanly and 403s.
|
|
25
|
+
def whoami
|
|
26
|
+
call(idempotent: true) { |api| Generated::ProfileApi.new(api).get_profile }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def resources
|
|
30
|
+
@resources ||= Resources.new(self)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def contexts
|
|
34
|
+
@contexts ||= Contexts.new(self)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def cognitive_maps
|
|
38
|
+
@cognitive_maps ||= CognitiveMaps.new(self)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# SearchParams names the field `query`, not `q`.
|
|
42
|
+
def search(query, **opts)
|
|
43
|
+
params = Generated::SearchParams.new({ query: query }.merge(opts))
|
|
44
|
+
call(idempotent: true) { |api| Generated::SearchApi.new(api).search(params) }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def graph
|
|
48
|
+
Generated::GraphApi.new(Temper.api_client)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# The one seam every surface module goes through.
|
|
52
|
+
#
|
|
53
|
+
# idempotent: true => a safe method. 5xx and transport failures retry.
|
|
54
|
+
# idempotent: false => a write. NEVER auto-retried.
|
|
55
|
+
#
|
|
56
|
+
# A 401 is repaired once, for reads and writes alike: re-authenticating is not
|
|
57
|
+
# re-submitting. BearerToken#refresh! raises, so a bearer caller makes exactly
|
|
58
|
+
# one request and the Unauthorized propagates out of refresh! itself.
|
|
59
|
+
def call(idempotent: false, &block)
|
|
60
|
+
attempt = 0
|
|
61
|
+
reminted = false
|
|
62
|
+
|
|
63
|
+
begin
|
|
64
|
+
attempt += 1
|
|
65
|
+
Temper.with_token(@credentials.token) { block.call(Temper.api_client) }
|
|
66
|
+
rescue Generated::ApiError => e
|
|
67
|
+
error = ErrorMapper.call(e)
|
|
68
|
+
|
|
69
|
+
if repair_credentials?(error, reminted)
|
|
70
|
+
reminted = true
|
|
71
|
+
retry
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
raise error unless retryable_read?(error, idempotent, attempt)
|
|
75
|
+
|
|
76
|
+
@backoff.call(attempt)
|
|
77
|
+
retry
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
private
|
|
82
|
+
|
|
83
|
+
# BearerToken#refresh! raises Unauthorized, so a bearer caller never reaches
|
|
84
|
+
# the retry -- the raise propagates straight out of refresh!.
|
|
85
|
+
def repair_credentials?(error, reminted)
|
|
86
|
+
return false unless error.is_a?(Unauthorized) && !reminted
|
|
87
|
+
|
|
88
|
+
@credentials.refresh!
|
|
89
|
+
true
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def retryable_read?(error, idempotent, attempt)
|
|
93
|
+
idempotent && error.is_a?(TransientError) && attempt < MAX_READ_ATTEMPTS
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Temper
|
|
4
|
+
# Incremental cognitive-map authoring (D9).
|
|
5
|
+
#
|
|
6
|
+
# Every path here is server-recompute: the server chunks and embeds. Bulk
|
|
7
|
+
# reconcile (PUT /api/cognitive-maps/{id}) is deliberately absent -- its
|
|
8
|
+
# ReconcileEntry.chunks_packed is a required, PRE-EMBEDDED String, carried
|
|
9
|
+
# verbatim with no server-side ONNX fallback, so a Ruby client cannot physically
|
|
10
|
+
# reach it without a 768-dim BGE embedder. It is a CLI operator's job, not a
|
|
11
|
+
# Rails request's. Reach Generated::CognitiveMapsApi#reconcile directly if you
|
|
12
|
+
# hand-pack chunks.
|
|
13
|
+
class CognitiveMaps
|
|
14
|
+
DEFAULT_POLARITY = 'forward'
|
|
15
|
+
|
|
16
|
+
def initialize(client)
|
|
17
|
+
@client = client
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# POST /api/cognitive-maps -> 200 CreateCogmapOutcome.
|
|
21
|
+
#
|
|
22
|
+
# Genesis takes an Option<ReconcileTelos>, so a charter-less map is creatable
|
|
23
|
+
# -- but CreateCogmapRequest still requires `telos_title`. Charter-less is not
|
|
24
|
+
# title-less. CreateCogmapRequest carries no act keys.
|
|
25
|
+
def create(name:, telos_title:, telos: nil, cogmap_id: nil, telos_resource_id: nil)
|
|
26
|
+
attrs = { name: name, telos_title: telos_title }
|
|
27
|
+
attrs[:telos] = telos unless telos.nil?
|
|
28
|
+
attrs[:cogmap_id] = cogmap_id unless cogmap_id.nil?
|
|
29
|
+
attrs[:telos_resource_id] = telos_resource_id unless telos_resource_id.nil?
|
|
30
|
+
|
|
31
|
+
body = Generated::CreateCogmapRequest.new(attrs)
|
|
32
|
+
@client.call { |api| Generated::CognitiveMapsApi.new(api).genesis(body) }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# A map node is a NEW resource that distills from its sources; ingest with
|
|
36
|
+
# home_cogmap_id is how it is born. The server chunks and embeds.
|
|
37
|
+
def author(cogmap_ref, title:, content:, context_ref:, doc_type_name:, act: nil, **opts)
|
|
38
|
+
@client.resources.create(
|
|
39
|
+
title: title, context_ref: context_ref, doc_type_name: doc_type_name,
|
|
40
|
+
content: content, act: act, home_cogmap_id: Temper.parse_ref(cogmap_ref), **opts
|
|
41
|
+
)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# POST /api/relationships (not /api/relationships/assert). The contract requires
|
|
45
|
+
# all of source, target, edge_kind, polarity, label, weight; the seven act keys
|
|
46
|
+
# flatten on, as they do on IngestPayload.
|
|
47
|
+
#
|
|
48
|
+
# edge_kind is one of express, contains, leads_to, near.
|
|
49
|
+
def assert_relationship(source:, target:, edge_kind:, label:, weight:,
|
|
50
|
+
polarity: DEFAULT_POLARITY, act: nil)
|
|
51
|
+
body = Generated::AssertRelationshipRequest.new(
|
|
52
|
+
{ source: Temper.parse_ref(source), target: Temper.parse_ref(target),
|
|
53
|
+
edge_kind: edge_kind, polarity: polarity, label: label, weight: weight }
|
|
54
|
+
.merge(act_hash(act))
|
|
55
|
+
)
|
|
56
|
+
@client.call { |api| Generated::RelationshipsApi.new(api).assert(body) }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# POST /api/facets (not /api/facets/set). `values` is plural, and is the
|
|
60
|
+
# facet's typed value payload.
|
|
61
|
+
def set_facet(resource:, values:, weight: nil, act: nil)
|
|
62
|
+
attrs = { resource: Temper.parse_ref(resource), values: values }
|
|
63
|
+
attrs[:weight] = weight unless weight.nil?
|
|
64
|
+
|
|
65
|
+
body = Generated::FacetSetRequest.new(attrs.merge(act_hash(act)))
|
|
66
|
+
@client.call { |api| Generated::FacetsApi.new(api).set_facet(body) }
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
private
|
|
70
|
+
|
|
71
|
+
def act_hash(act)
|
|
72
|
+
act.nil? ? {} : act.to_h
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'faraday'
|
|
4
|
+
require 'faraday/gzip'
|
|
5
|
+
require 'faraday/net_http_persistent'
|
|
6
|
+
require 'uri'
|
|
7
|
+
|
|
8
|
+
module Temper
|
|
9
|
+
# Thread.current[] is FIBER-local in Ruby (Thread#thread_variable_get is the
|
|
10
|
+
# thread-local one). Fiber[] would read better but arrived in 3.2, and the
|
|
11
|
+
# gem's floor is 3.1.
|
|
12
|
+
TOKEN_KEY = :temper_access_token
|
|
13
|
+
private_constant :TOKEN_KEY
|
|
14
|
+
|
|
15
|
+
class << self
|
|
16
|
+
# One ApiClient per process => one Faraday connection => one
|
|
17
|
+
# net-http-persistent per-thread pool.
|
|
18
|
+
#
|
|
19
|
+
# A fresh Configuration + ApiClient per request is the obvious fix for the
|
|
20
|
+
# generated singletons' single shared access_token, and it is a trap: fresh
|
|
21
|
+
# client, fresh connection, TLS handshake per request. Instead the connection
|
|
22
|
+
# is process-global and the TOKEN is call-scoped, via access_token_getter.
|
|
23
|
+
def api_client
|
|
24
|
+
connection_mutex.synchronize { @api_client ||= build_api_client }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Call from Puma's on_worker_boot and from Sidekiq.configure_server, so a
|
|
28
|
+
# forked worker never inherits its parent's sockets.
|
|
29
|
+
def reset_connection!
|
|
30
|
+
connection_mutex.synchronize { @api_client = nil }
|
|
31
|
+
nil
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def current_token
|
|
35
|
+
Thread.current[TOKEN_KEY]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def with_token(token)
|
|
39
|
+
previous = Thread.current[TOKEN_KEY]
|
|
40
|
+
Thread.current[TOKEN_KEY] = token
|
|
41
|
+
yield
|
|
42
|
+
ensure
|
|
43
|
+
Thread.current[TOKEN_KEY] = previous
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
def connection_mutex
|
|
49
|
+
@connection_mutex ||= Mutex.new
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def build_api_client
|
|
53
|
+
generated = build_generated_config
|
|
54
|
+
Generated::ApiClient.new(generated).tap do |client|
|
|
55
|
+
client.default_headers['X-Temper-Surface'] = 'sdk'
|
|
56
|
+
client.default_headers['X-Temper-Device-Id'] = config.device_id if config.device_id
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def build_generated_config
|
|
61
|
+
Generated::Configuration.new.tap do |c|
|
|
62
|
+
apply_endpoint(c, base_uri)
|
|
63
|
+
c.access_token_getter = -> { Temper.current_token }
|
|
64
|
+
configure_faraday(c)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def base_uri
|
|
69
|
+
raise ArgumentError, 'Temper.config.base_url is not set' if config.base_url.nil?
|
|
70
|
+
|
|
71
|
+
# Every request puts the bearer token on this URL, so the scheme is
|
|
72
|
+
# checked where the client is built, not per request. The opt-in is
|
|
73
|
+
# configuration here (not a kwarg) because the gem's URL is process-wide.
|
|
74
|
+
Validate.require_endpoint(config.base_url, name: 'base_url',
|
|
75
|
+
allow_insecure_http: config.allow_insecure_http)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def apply_endpoint(generated_config, base)
|
|
79
|
+
generated_config.scheme = base.scheme
|
|
80
|
+
generated_config.host = host_with_port(base)
|
|
81
|
+
generated_config.base_path = base.path
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# `configure_faraday_connection` REGISTERS the block; `configure_connection` is
|
|
85
|
+
# the invoker the generated ApiClient calls with the connection.
|
|
86
|
+
#
|
|
87
|
+
# It runs AFTER build_connection sets conn.adapter(Faraday.default_adapter), so
|
|
88
|
+
# setting the adapter here replaces it. An adapter set via `configure_middleware`
|
|
89
|
+
# runs BEFORE, and would be silently overwritten by the default -- costing a TLS
|
|
90
|
+
# handshake per request while nothing fails.
|
|
91
|
+
#
|
|
92
|
+
# `conn.request :gzip` installs faraday-gzip's decompression middleware. It sets
|
|
93
|
+
# Accept-Encoding: gzip,deflate and inflates the response in Faraday's
|
|
94
|
+
# on_complete -- OUTSIDE Net::HTTP. That is the whole point: the
|
|
95
|
+
# net_http_persistent adapter bypasses Net::HTTP's transparent gzip handling, so
|
|
96
|
+
# without this a `Content-Encoding: gzip` body reaches the deserializer as raw
|
|
97
|
+
# compressed bytes and every read returns nil (issue #446). Order is irrelevant
|
|
98
|
+
# -- Faraday keeps the adapter last regardless of call order -- but registering
|
|
99
|
+
# the request middleware before the adapter reads in stack order.
|
|
100
|
+
def configure_faraday(generated_config)
|
|
101
|
+
generated_config.configure_faraday_connection do |conn|
|
|
102
|
+
conn.request :gzip
|
|
103
|
+
conn.adapter :net_http_persistent, pool_size: 5
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def host_with_port(base)
|
|
108
|
+
return base.host if base.port.nil? || base.port == base.default_port
|
|
109
|
+
|
|
110
|
+
"#{base.host}:#{base.port}"
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|