#!/usr/bin/env bash set -euo pipefail ROOT="$(cd "$(dirname "$0")/.." && pwd)" CONFIG_PATH="${CONTINUITY_PROVIDER_CONFIG:-$ROOT/build/system/continuity_provider.json}" COMMAND="${1:-status}" ARG1="${2:-}" ARG2="${3:-}" if [ ! -f "$CONFIG_PATH" ]; then echo "continuity provider config not found: $CONFIG_PATH" >&2 exit 1 fi json_config() { jq "$1" "$CONFIG_PATH" } config_value() { jq -r "$1" "$CONFIG_PATH" } external_base_url() { config_value '.external.base_url' } external_url() { local path="$1" printf '%s%s' "$(external_base_url)" "$path" } api_key_header() { config_value '.external.api_key_header' } tenant_header() { config_value '.external.tenant_header' } api_key_value() { if [ -n "${CONTINUITY_PROVIDER_API_KEY:-}" ]; then printf '%s' "$CONTINUITY_PROVIDER_API_KEY" else config_value '.external.api_key_default' fi } tenant_value() { if [ -n "${CONTINUITY_PROVIDER_TENANT:-}" ]; then printf '%s' "$CONTINUITY_PROVIDER_TENANT" else config_value '.external.tenant_default' fi } health_ok() { local body body="$(curl -fsS "$(external_url "$(config_value '.external.health_path')")" 2>/dev/null || true)" [ "$body" = "ok" ] } curl_json() { local method="$1" local url="$2" local data="${3:-}" if [ -n "$data" ]; then curl -fsS -X "$method" \ -H 'content-type: application/json' \ -H "$(api_key_header): $(api_key_value)" \ -H "$(tenant_header): $(tenant_value)" \ -d "$data" \ "$url" else curl -fsS -X "$method" \ -H "$(api_key_header): $(api_key_value)" \ -H "$(tenant_header): $(tenant_value)" \ "$url" fi } fallback_pointer_path() { local rel rel="$(config_value '.fallback.latest_pointer_path')" printf '%s/%s' "$ROOT" "$rel" } fallback_status() { local pointer_path pointer_path="$(fallback_pointer_path)" if [ ! -f "$pointer_path" ]; then jq -n '{provider:"local_fallback", available:false}' return 0 fi jq -n \ --argjson pointer "$(cat "$pointer_path")" \ '{ provider:"local_fallback", available:true, continuity_version_id:$pointer.continuity_version_id, predecessor_id:$pointer.predecessor_id, default_surface:$pointer.default_surface, surface_ids:$pointer.surface_ids, endpoint_ids:$pointer.endpoint_ids, lineage_path:$pointer.lineage_path, surface_registry_path:$pointer.surface_registry_path, status:$pointer.status }' } fallback_surfaces() { local pointer_path registry_path pointer_path="$(fallback_pointer_path)" if [ ! -f "$pointer_path" ]; then jq -n '{provider:"local_fallback", items:[]}' return 0 fi registry_path="$(jq -r '.surface_registry_path' "$pointer_path")" registry_path="$ROOT/$registry_path" if [ ! -f "$registry_path" ]; then jq -n '{provider:"local_fallback", items:[]}' return 0 fi jq -n \ --argjson registry "$(cat "$registry_path")" \ '{ provider:"local_fallback", items: [ $registry.surfaces[] | { surface_id:.id, version_id:$registry.continuity_version_id, activated:(.id == $registry.default_surface), title:.title, purpose:.purpose } ] }' } fallback_lineage() { local version_id="$1" local pointer_path lineage_path pointer_path="$(fallback_pointer_path)" if [ ! -f "$pointer_path" ]; then jq -n '{provider:"local_fallback", available:false}' return 0 fi lineage_path="$(jq -r '.lineage_path' "$pointer_path")" lineage_path="$ROOT/$lineage_path" if [ ! -f "$lineage_path" ]; then jq -n '{provider:"local_fallback", available:false}' return 0 fi jq -n \ --arg requested_version "$version_id" \ --argjson lineage "$(cat "$lineage_path")" \ 'if $requested_version != "" and $requested_version != $lineage.continuity_version_id then {provider:"local_fallback", available:false} else { provider:"local_fallback", available:true, version_id:$lineage.continuity_version_id, predecessor:$lineage.predecessor_id, receipts_required:$lineage.receipts_required, verified:false, promoted:false, manifest_path:$lineage.manifest_path } end' } instantiate_payload() { local version_id="$1" local predecessor="$2" if [ -n "$version_id" ] && [ -f "$version_id" ]; then predecessor="$(jq -r '.predecessor_id // .predecessor // "hv-conversational-control-plane-v0"' "$version_id")" version_id="$(jq -r '.continuity_version_id // .version_id // "hv-continuity-control-plane-v1"' "$version_id")" fi jq -n \ --arg version_id "${version_id:-hv-continuity-control-plane-v1}" \ --arg predecessor "${predecessor:-hv-conversational-control-plane-v0}" \ '{ goal:"Instantiate continuity runtime", ops:[ { op:"instantiate_continuity_runtime", args:{ version_id:$version_id, predecessor:$predecessor, receipts_required:["r-chat-history-graph-20260408","r-chat-history-pass-20260408"], receipts_ready:["r-chat-history-graph-20260408","r-chat-history-pass-20260408"], promote_if_verified:true } } ] }' } case "$COMMAND" in status) if health_ok; then curl_json GET "$(external_url "$(config_value '.external.versions_path')")" \ | jq '{provider:"external_nextgen", available:true, items:.items}' else fallback_status fi ;; surfaces) if health_ok; then curl_json GET "$(external_url "$(config_value '.external.surfaces_path')")" \ | jq '{provider:"external_nextgen", items:.items}' else fallback_surfaces fi ;; lineage) if [ -z "$ARG1" ]; then echo "usage: continuity_provider.sh lineage " >&2 exit 1 fi if health_ok; then curl_json GET "$(external_url "$(config_value '.external.versions_path')")/$ARG1/lineage" \ | jq '. + {provider:"external_nextgen"}' else fallback_lineage "$ARG1" fi ;; activate) if [ -z "$ARG1" ]; then echo "usage: continuity_provider.sh activate [version_id]" >&2 exit 1 fi if health_ok; then curl_json POST \ "$(external_url "$(config_value '.external.surfaces_path')")/$ARG1/activate" \ "$(jq -n --arg version_id "${ARG2:-hv-continuity-control-plane-v1}" '{version_id:$version_id}')" else echo "activate is not supported in local fallback mode" >&2 exit 1 fi ;; instantiate) if health_ok; then curl_json POST \ "$(external_url "$(config_value '.external.nextgen_path')")" \ "$(instantiate_payload "$ARG1" "$ARG2")" else "$ROOT/runtime/materialize_continuity_slice.sh" "${ARG1:-$ROOT/runtime/examples/continuity_v1_manifest.json}" fi ;; *) echo "unsupported command: $COMMAND" >&2 exit 1 ;; esac